/* ============================================================================
   brand-member.css —— 原 brand.css 的 第 3 段（会员系统：等级 / 积分 / 券 / 收藏 / 订单 / 称号 / 头像 / 上传弹窗表单）
   ----------------------------------------------------------------------------
   **逐字搬过来、没有重排一行**（原第 1497–2338 行）。拆的理由：brand.css 涨到 4278 行，
   改一条规则要在大文件里翻；分段后按主题定位，每段 ≤1000 行。

   🔴 **加载顺序就是层叠顺序**：本文件必须在 brand.css 之后引用（HTML 里已按序写 5 个 link）。
      段内规则**不要搬到别的段** —— 位置一变，覆盖关系就变，视觉会飘（而截图未必看得出来）。
      要验证拆分无损，跑 `node _probe_style_hash.cjs` 对比拆分前的指纹。
   ========================================================================== */
/* ============================================================================
   会员系统（member.js 配套）· 等级 / 积分 / 券 / 收藏 / 订单
   配色沿用 CMYK 四色 + 品牌金做「工艺升级」梯度，不新增色相
   ========================================================================= */

/* ── 页头会员入口 ─────────────────────────────────────────── */
.member-btn {
  position: relative;
  display: inline-flex; align-items: center; gap: 8px;
  height: 34px; padding: 0 13px;
  border: 1px solid var(--ink-4); border-radius: var(--r-nav);
  background: var(--ink-2); color: var(--text);
  font-size: 13px; font-weight: 700; text-decoration: none; cursor: pointer;
  white-space: nowrap;
}
.member-btn:hover { border-color: var(--brand-2); color: var(--gold-ink); }
.member-btn .m-nick { max-width: 8em; overflow: hidden; text-overflow: ellipsis; }
/* 2026-10-21：头像下拉菜单整个删除（店主「把原本的下拉菜单删掉」）。
   一并删掉的规则：.m-caret / .member-btn.open .m-caret / .m-menu /
   .member-btn.open .m-menu / .m-menu-hd(+hover,+b,+mono) / .m-menu-stat /
   .m-menu a,button(+hover) / button[data-logout]:hover —— 共 11 条。
   🔴 别把这段留着「以后可能用」：留着就会有人照着它把菜单加回来。
   现在 #mEntry 是普通 <a href="account.html">，只有昵称 + 等级徽章。 */

/* ── 等级徽章（工艺梯度：灰 → 青 → 洋红 → 金 → 典藏）──────── */
.badge.lvl { border-radius: 9px; letter-spacing: .04em; }
.badge.lvl.lv-proof   {
  /* 2026-10-24：var(--text-3) 压在 16% 暖灰底上只有 4.4:1 → 用 --text-2（近 9:1），仍比主文字弱一档 */
  color: var(--text-2); border-color: var(--ink-4); background: rgba(110,106,99,.16);
}
.badge.lvl.lv-mono    { color: var(--c-cyan); border-color: rgba(0,168,168,.5); background: rgba(0,168,168,.14); }
.badge.lvl.lv-process {
  /* 洋红 #E6007E 本身偏暗（深底 3.5:1）→ 提亮一档；色相不变，仍是"套色"那支洋红 */
  color: #FF5CAA; border-color: rgba(255,92,170,.5); background: rgba(230,0,126,.14);
}
.badge.lvl.lv-foil    { color: var(--gold-ink);   border-color: rgba(255,224,0,.55); background: rgba(255,224,0,.14); }
.badge.lvl.lv-archive {
  color: var(--on-accent); border-color: var(--brand-2); font-weight: 800;
  background: linear-gradient(100deg, var(--gold) 0%, #f0c94a 55%, var(--brand-2) 100%);
}

/* ── 收藏按钮 ─────────────────────────────────────────────── */
.fav-btn {
  position: absolute; top: 8px; right: 8px; z-index: 3;
  width: 30px; height: 30px; padding: 0; border-radius: 50%;
  border: 1px solid var(--ink-4); background: rgba(20,20,20,.72);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; transition: border-color .2s ease, background .2s ease;
}
.fav-btn svg { width: 15px; height: 15px; fill: none; stroke: var(--text-2); stroke-width: 2; }
.fav-btn:hover { border-color: var(--brand-2); background: rgba(20,20,20,.92); }
.fav-btn:hover svg { stroke: var(--gold); }
.fav-btn.on svg { fill: var(--gold); stroke: var(--gold); }
.fav-btn.lg { position: static; width: 46px; height: 46px; flex: none; }
.fav-btn.lg svg { width: 20px; height: 20px; }

/* ── 会员提示（详情页 / 卡库）─────────────────────────────── */
.m-hint {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 12px; padding: 10px 14px;
  background: var(--ink-2); border: 1px solid var(--ink-4); border-left: 3px solid var(--brand-2);
  border-radius: var(--r-l3); font-size: 12.5px; color: var(--text-2);
}
.m-hint .num { color: var(--gold-ink); }
.m-hint a { color: var(--gold-ink); font-weight: 700; margin-left: auto; }

/* ── 购物车：会员条 / 券选择 / 积分 ───────────────────────── */
.m-bar {
  margin: -4px 0 12px; padding: 9px 12px;
  background: rgba(184,147,46,.10); border: 1px solid rgba(184,147,46,.35);
  border-radius: var(--r-l3); font-size: 12px; color: var(--text-2); line-height: 1.6;
}
.m-bar a { color: var(--gold-ink); font-weight: 700; }
.sum-row.off b { color: var(--green); }
.sum-points {
  margin-top: 10px; padding: 8px 12px; border-radius: var(--r-l3);
  background: var(--ink-2); border: 1px dashed var(--ink-4);
  font-size: 12px; color: var(--text-2); text-align: center;
}
.sum-points b { color: var(--gold-ink); }
.cp-wrap { margin: 12px 0; padding-top: 12px; border-top: 1px solid var(--ink-4); }
.cp-hd { font-size: 11.5px; font-weight: 800; letter-spacing: .08em; color: var(--text-3); margin-bottom: 8px; }
.cp-list { display: grid; gap: 6px; }
.cp-opt {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 11px; border: 1px solid var(--ink-4); border-radius: var(--r-l3);
  background: var(--ink-2); color: var(--text-2);
  font: inherit; font-size: 12.5px; text-align: left; cursor: pointer;
  transition: border-color .2s ease, color .2s ease;
}
.cp-opt:hover { border-color: var(--brand-2); color: var(--gold-ink); }
.cp-opt.on { border-color: var(--gold); color: var(--gold-ink); background: rgba(255,224,0,.08); }
.cp-opt.on::before { content: "◆"; color: var(--gold-ink); font-size: 9px; margin-right: 6px; }
.cp-exp { font-size: 10.5px; color: var(--text-3); }
.cp-note { margin-top: 8px; font-size: 11.5px; color: var(--brick); }
.ck-member {
  padding: 10px 12px; border-radius: var(--r-l3);
  background: var(--ink-2); border: 1px solid var(--ink-4);
  font-size: 12.5px; color: var(--text-2);
}
.ck-member a { color: var(--gold-ink); font-weight: 700; }

/* 店铺后台不可用时的警示块（2026-09-30）
   背景：下单口 /api/order 只在中间层里有。直接双击 html / 普通 http 打开时它不存在，
   而前端原来**静默降级**成"本地演示流程" —— 订单只写浏览器本地，收卡端永远 0 单，
   店主完全看不出来。现在进结算页 + 下单成功/失败时都要显式说清。 */
.shop-warn {
  margin-top: 12px; padding: 10px 12px; border-radius: var(--r-l3);
  background: rgba(230,0,126,.07); border: 1px solid rgba(230,0,126,.35);
  color: var(--brick, #a3231c); font-size: 12px; line-height: 1.65;
}
.shop-warn b { color: inherit; }
.shop-ok {
  margin-top: 10px; padding: 8px 12px; border-radius: var(--r-l3);
  background: rgba(255,224,0,.08); border: 1px solid rgba(255,224,0,.35);
  color: var(--text-2); font-size: 12px; line-height: 1.6;
}

/* ── 会员中心：登录 / 注册 ────────────────────────────────── */
/* 2026-10-26：右栏「等级阶梯」整块删除后只剩一张表单卡 ——
   两列栅格会把表单压到半宽（左边一条、右边一片空），所以改成**单列 + 居中定宽**。
   为什么不再留空列：登录页是"只做一件事"的页面，空白列只会让人以为右侧加载失败。 */
.auth-grid {
  display: grid; grid-template-columns: minmax(0, 680px);
  justify-content: center;
  gap: 20px; align-items: start;
}
.auth-tabs { display: flex; gap: 8px; margin-bottom: 18px; }
.auth-tab {
  flex: 1; padding: 10px 0; border: 1px solid var(--ink-4); border-radius: var(--r-nav);
  background: var(--ink-2); color: var(--text-2); font: inherit; font-size: 13.5px; font-weight: 700; cursor: pointer;
}
.auth-tab.on { background: var(--gold); border-color: var(--gold); color: var(--on-accent); }
.auth-form { display: grid; gap: 14px; }
.fl { display: grid; gap: 6px; }
.fl > span { font-size: 11.5px; font-weight: 700; letter-spacing: .08em; color: var(--text-3); }
.auth-err { min-height: 16px; font-size: 12px; color: var(--brick); }
.auth-alt { font-size: 12.5px; color: var(--text-3); text-align: center; }
.lnk {
  border: 0; background: transparent; padding: 0; margin-left: 4px;
  color: var(--gold-ink); font: inherit; font-weight: 700; text-decoration: underline; cursor: pointer;
}

/* ── 登录方式段控（2026-10-25 手机号登录）─────────────────────────────
   与上面的 .auth-tabs 分两级：`.auth-tabs` 是「登录 / 注册」（页面级），
   这个是「手机号 / 账号密码」（表单内）。两者做成同样重的大按钮会看不出主次，
   所以这里用胶囊 + 小一号字。 */
.auth-seg {
  display: inline-flex; gap: 2px;
  padding: 3px; margin-bottom: 2px;
  border-radius: 999px;
  background: var(--ink-2);
  border: 1px solid var(--ink-4);
  justify-self: start;
}
.auth-seg > button {
  padding: 6px 14px; border: 0; border-radius: 999px;
  background: transparent; color: var(--text-3);
  font: inherit; font-size: 12.5px; font-weight: 700; cursor: pointer;
  transition: background .16s, color .16s;
}
.auth-seg > button.on { background: var(--gold); color: var(--on-accent); }
.auth-body { display: grid; gap: 14px; }
/* 🔴 必须显式写：`.auth-body { display:grid }` 会盖掉浏览器默认的 `[hidden]{display:none}`，
   于是 hidden 完全不生效、两段表单会同时出现。 */
.auth-body[hidden] { display: none !important; }

/* 验证码一行：输入框吃掉剩余宽度，按钮永不换行 */
.auth-code { display: flex; gap: 8px; align-items: stretch; }
.auth-code .input { flex: 1 1 auto; min-width: 0; }
.auth-send {
  flex: none; min-width: 104px; white-space: nowrap;
  /* 倒计时数字用等宽数字，否则 59→58 会左右跳 */
  font-variant-numeric: tabular-nums;
}
.auth-send:disabled { opacity: .55; cursor: default; }

/* ── 「已记住手机号」（2026-10-26 手机号 + 密码，3 天内免验证）────────────
   3 天内只填密码，所以手机号退化成**只读的一行**：显示掩码（不把完整号码
   摆在屏幕上，店里有旁人的时候不该被看见）+ 一句到期时间 + 一颗「换号」。
   为什么不做成 disabled 的 input：禁用输入框会让人以为"这里能改但坏了"，
   一行文字 + 明确的「换号」按钮才是这件事的真实状态。 */
.auth-dev {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 9px 12px;
  border-radius: var(--r-nav);
  background: var(--ink-2);
  border: 1px solid var(--ink-4);
}
.auth-dev-lb { font-size: 11.5px; font-weight: 700; letter-spacing: .08em; color: var(--text-3); }
.auth-dev b { font-size: 15px; letter-spacing: .04em; color: var(--text); }
.auth-dev-tag {
  font-size: 10.5px; font-weight: 700; line-height: 1.6;
  padding: 1px 7px; border-radius: 999px;
  color: var(--gold-ink);
  background: rgba(184, 147, 46, .14);
  border: 1px solid rgba(184, 147, 46, .32);
}
.auth-dev .lnk { margin-left: auto; font-size: 12px; }

/* 一段说明（表单内），与 `.auth-alt` 分开：那个是"去注册/去登录"的行 */
.auth-hint { font-size: 11.5px; line-height: 1.7; color: var(--text-3); }
.auth-alt-2 { margin-top: -6px; font-size: 11.5px; }
.auth-alt-2 .lnk { color: var(--text-3); font-weight: 600; text-decoration: none; }
.auth-alt-2 .lnk:hover { color: var(--gold-ink); text-decoration: underline; }

/* ── 会员中心（2026-09-20 用户拍板改版，参考影之诗「个人信息」页）──
   左 = 竖排资料卡（.me-side 挂 .ov 类名给夹具/锚点当钩子，布局在此覆盖）
   右 = 信息面板区（等级+积分兑换 两列，下接券/收藏/订单/设置） */
.me-grid { display: grid; grid-template-columns: 320px minmax(0, 1fr); gap: 18px; align-items: start; }
.me-main { display: grid; gap: 18px; min-width: 0; }
.me-main > .panel { margin: 0; }
.me-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; align-items: start; }
.me-side {
  display: block; text-align: center;
  position: sticky; top: 86px;           /* 滚右边长面板时资料卡跟随（对齐游戏里资料卡常驻左栏的手感） */
}
.me-ava {
  position: relative;
  width: 92px; height: 92px; margin: 6px auto 14px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 34px; font-weight: 800; color: var(--gold-ink);
  background: radial-gradient(120% 120% at 30% 25%, var(--ink-2), var(--ink-3));
  border: 2px solid rgba(184,147,46,.55);
  box-shadow: 0 10px 26px rgba(0,0,0,.45);
  /* 2026-09-20 拍板：头像可点换（仅内置头像），按钮化 + 悬停浮出 ✎ */
  padding: 0; cursor: pointer; overflow: visible;
  transition: border-color .2s ease;
}
.me-ava img {
  width: 100%; height: 100%; object-fit: cover; border-radius: 50%; display: block;
}
.me-ava:hover { border-color: var(--gold); }
/* 悬停浮出的是**写清楚的文字**而不是 ✎ 符号（2026-10-01 会员中心改版 B）：
   原来页面上有四处长相各异的「可点」提示（✎ 徽章 / ✎ 文字 / 独立按钮 / 下划线链接），
   用户得逐个试探。统一成「同一层级只用一种形态」后，这一处是胶囊 + 明说动作。 */
.me-ava-pen {
  position: absolute; left: 50%; bottom: -10px; right: auto;
  transform: translateX(-50%) scale(.9);
  padding: 3px 10px; border-radius: 99px;
  font-size: 10.5px; font-weight: 800; letter-spacing: .04em; line-height: 1.3; font-style: normal;
  white-space: nowrap; background: var(--ink); border: 1px solid var(--ink-4); color: var(--text-3);
  opacity: 0;
  transition: opacity .18s ease, transform .18s ease, color .18s ease, border-color .18s ease;
}
.me-ava:hover .me-ava-pen, .me-ava:focus-visible .me-ava-pen {
  opacity: 1; transform: translateX(-50%); color: var(--gold-ink); border-color: rgba(255,224,0,.5);
}
.me-namebar { display: flex; align-items: center; justify-content: center; gap: 8px; min-height: 34px; }
.me-nick {
  font-size: 17px; font-weight: 800; color: var(--text);
  max-width: 190px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 昵称旁的改动入口：常驻小胶囊（不再靠悬停才现身） */
.me-pen {
  background: none; border: 1px solid var(--ink-4); border-radius: 99px;
  color: var(--text-3); cursor: pointer; font-size: 11px; font-weight: 700; padding: 2px 8px;
  transition: color .2s ease, border-color .2s ease;
}
.me-pen:hover { color: var(--gold-ink); border-color: rgba(255,224,0,.5); }
.me-btns { display: flex; gap: 8px; justify-content: center; margin-top: 18px; }
.me-btns .btn { flex: 1 1 0; padding-left: 0; padding-right: 0; white-space: nowrap; }
/* 退出登录降级为页脚文字链（2026-10-01）：危险操作不该和「收藏夹 / 我的订单」并列成三等分 */
.me-foot { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--ink-4); }
.me-foot .lnk { color: var(--text-3); font-weight: 700; text-decoration: none; font-size: 12px; }
.me-foot .lnk:hover { color: var(--brick); text-decoration: underline; }
.me-meta { margin-top: 18px; border-top: 1px solid var(--ink-4); padding-top: 6px; text-align: left; }
/* 侧栏等级组：进度条 + 升级提示 + 注册日期（把原来三行碎信息并成一组） */
.me-lvbox { padding: 10px 2px 8px; }
.me-since { margin-top: 8px; font-size: 11px; color: var(--text-3); }
.me-row {
  display: flex; align-items: center; gap: 10px; padding: 9px 2px;
  font-size: 12.5px; color: var(--text-3); border-bottom: 1px dashed var(--ink-4);
}
.me-row:last-child { border-bottom: none; }
.me-row > span { flex: none; width: 32px; }
.me-row b { color: var(--text); font-weight: 700; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.me-row .lnk { margin-left: auto; font-size: 11.5px; flex: none; }
/* 右栏等级面板头（对齐参考图「阶位」板块：徽章 + 等级名 + 消费额） */
.me-lvhd { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.me-lvname { font-size: 15px; font-weight: 800; color: var(--text); }
.me-lvspent { margin-left: auto; font-size: 12px; color: var(--text-3); }
.me-lvspent .num { color: var(--gold-ink); }
@media (max-width: 920px) {
  .me-grid { grid-template-columns: 1fr; }
  .me-side { position: static; }
  .me-cols { grid-template-columns: 1fr; }
}

.ov-prog { height: 8px; border-radius: 99px; background: var(--ink); border: 1px solid var(--ink-4); overflow: hidden; }
.ov-prog i { display: block; height: 100%; background: linear-gradient(90deg, var(--brand-2), var(--gold)); }
.ov-note { margin-top: 10px; font-size: 12.5px; color: var(--text-2); line-height: 1.7; }
.ov-note b { color: var(--text); }
.ov-note .num { color: var(--gold-ink); }

.blk-t {
  margin: 0 0 14px; font-size: 13px; font-weight: 800; letter-spacing: .08em; color: var(--text-3);
}
.two-col { display: grid; grid-template-columns: minmax(0,1.1fr) minmax(0,1fr); gap: 20px; margin-top: 20px; align-items: start; }
.two-col > .panel { margin: 0; }

/* ── 等级表 ───────────────────────────────────────────────── */
.lvl-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.lvl-table th {
  text-align: left; padding: 8px 10px; font-size: 11px; font-weight: 800;
  letter-spacing: .08em; color: var(--text-3); border-bottom: 1px solid var(--ink-4);
}
.lvl-table th.num, .lvl-table td.num { text-align: right; }
.lvl-table td { padding: 10px; border-bottom: 1px solid var(--ink-4); color: var(--text-2); }
.lvl-table tr.on td { background: rgba(255,224,0,.06); color: var(--text); }

/* ── 积分兑换 ─────────────────────────────────────────────── */
.redeem-grid { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 10px; }
.redeem-card {
  padding: 12px 14px; border: 1px solid var(--ink-4); border-radius: var(--r-l1); background: var(--ink-2);
}
.redeem-card.off { opacity: .55; }
.rc-t { font-size: 13px; font-weight: 700; }
.rc-m { font-size: 11.5px; color: var(--text-3); margin: 6px 0 10px; line-height: 1.6; }
.redeem-card .btn { width: 100%; }

/* ── 券卡 ─────────────────────────────────────────────────── */
.cp-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 10px; }
.cp-card {
  padding: 12px 14px; border: 1px solid rgba(255,224,0,.35); border-radius: var(--r-l1);
  background: linear-gradient(120deg, rgba(255,224,0,.09), rgba(20,20,20,0));
}
.cp-card.dead { border-color: var(--ink-4); background: var(--ink-2); opacity: .6; }
.cc-t { font-size: 13px; font-weight: 700; }
.cc-c { font-size: 11px; color: var(--gold-ink); margin: 5px 0; }
.cp-card.dead .cc-c { color: var(--text-3); }
.cc-m { font-size: 11px; color: var(--text-3); }
.cp-empty {
  padding: 20px; text-align: center; font-size: 12.5px; color: var(--text-3);
  background: var(--ink-2); border: 1px dashed var(--ink-4); border-radius: var(--r-l1);
}
.cp-empty a { color: var(--gold-ink); font-weight: 700; }

/* ── 会员中心改版（2026-10-01 用户拍板 B 档：视觉权重 + 交互闭环）──
   症状：三个真正的「成绩单」（积分 / 可用券 / 距下一级）全被做成标题后的小灰字，
   首屏最大的色块反而是一个空头像；兑换区是一屏等大灰卡；兑换不可逆却无二次确认。 */

/* 资产概览条：把三个数字提成首屏视觉锚。金色纪律不变 ——
   本页只有「积分余额 + 主按钮 + 券码」用金色，其余数字走 --text。 */
.asset-strip { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.as-cell { padding: 2px 18px; border-left: 1px solid var(--ink-4); min-width: 0; }
.as-cell:first-child { border-left: 0; padding-left: 2px; }
.as-lb { font-size: 11px; font-weight: 800; letter-spacing: .08em; color: var(--text-3); margin-bottom: 8px; }
.as-num { font-size: 26px; font-weight: 800; line-height: 1.15; color: var(--text); overflow-wrap: anywhere; }
.as-num.gold { color: var(--gold-ink); }
.as-unit { font-size: 13px; font-weight: 700; margin-left: 4px; color: var(--text-2); }
.as-sub { margin-top: 7px; font-size: 11.5px; color: var(--text-3); }
.as-note {
  margin: 16px 0 0; padding-top: 12px; border-top: 1px solid var(--ink-4);
  font-size: 11.5px; color: var(--text-3); line-height: 1.75;
}
.as-note .num { color: var(--text); font-weight: 700; }

/* 折叠块（等级规则 / 历史券）—— 原生 <details>：零 JS、键盘与读屏可用 */
.fold { border-top: 1px solid var(--ink-4); margin-top: 16px; }
.fold-hd {
  display: flex; align-items: center; gap: 8px; cursor: pointer; list-style: none;
  padding: 11px 0 10px; font-size: 12.5px; font-weight: 800; color: var(--text-2);
}
.fold-hd::-webkit-details-marker { display: none; }
.fold-hd .muted { font-weight: 600; font-size: 11.5px; }
.fold-ct { color: var(--text-3); font-weight: 700; font-size: 11.5px; }
.fold-arw { margin-left: auto; color: var(--text-3); font-size: 10px; transition: transform .2s ease; }
.fold-arw::before { content: "▾"; }
.fold[open] .fold-arw { transform: rotate(180deg); }
.fold-bd { padding-bottom: 2px; }

/* 积分兑换：可用项（卡片）／待攒项（紧凑行 + 可达性进度）
   换算不是估的 —— 规则就是「1 积分 = ￥1 实付」，所以「还差 N 分」⇔「约再买 ￥N」。 */
.rd-lb { margin: 0 0 10px; font-size: 11px; font-weight: 800; letter-spacing: .08em; color: var(--text-3); }
.rd-lb.gap-top { margin-top: 18px; }
.rd-lb + .redeem-grid { margin-bottom: 4px; }
.redeem-card.can {
  border-color: rgba(255,224,0,.42);
  background: linear-gradient(120deg, rgba(255,224,0,.07), rgba(20,20,20,0));
}
.redeem-list { display: grid; }
.rd-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start;
  gap: 2px 14px; padding: 11px 2px; border-bottom: 1px solid var(--ink-4);
}
.rd-row:last-child { border-bottom: 0; }
.rr-t { font-size: 12.5px; font-weight: 700; color: var(--text-2); }
.rr-m { font-size: 11.5px; color: var(--text-3); margin-top: 4px; }
.rr-gap { font-size: 12px; font-weight: 700; color: var(--text-2); white-space: nowrap; text-align: right; }
.rr-gap .num { color: var(--gold-ink); }
.rr-bar {
  grid-column: 1 / -1; height: 4px; margin-top: 9px; border-radius: 99px;
  background: var(--ink); border: 1px solid var(--ink-4); overflow: hidden;
}
.rr-bar i { display: block; height: 100%; background: linear-gradient(90deg, var(--brand-2), var(--gold)); }

/* 兑换确认 / 成功回执弹窗 */
.rd-modal { width: min(460px, 100%); }
.rd-conf { margin-top: 6px; }
.rd-crow {
  display: flex; align-items: baseline; gap: 12px;
  padding: 9px 0; border-bottom: 1px solid var(--ink-4); font-size: 12.5px;
}
.rd-crow:last-child { border-bottom: 0; }
.rd-crow > span { flex: none; width: 66px; color: var(--text-3); }
.rd-crow > b { color: var(--text); font-weight: 700; min-width: 0; }
.rd-crow > b.gold { color: var(--gold-ink); }
.rd-warn { margin: 12px 0 0; font-size: 12px; color: var(--brick); line-height: 1.7; }
.rd-warn.calm { color: var(--text-3); }
.cp-hist { margin-top: 16px; }
@media (max-width: 700px) {
  .asset-strip { grid-template-columns: 1fr; }
  .as-cell { border-left: 0; border-top: 1px solid var(--ink-4); padding: 12px 2px; }
  .as-cell:first-child { border-top: 0; padding-top: 2px; }
}

/* ── 收藏夹 ───────────────────────────────────────────────── */
.fav-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
.fav-card {
  position: relative; display: block; padding: 10px; text-decoration: none;
  border: 1px solid var(--ink-4); border-radius: var(--r-l1); background: var(--ink-2);
  transition: border-color .2s ease;
}
.fav-card:hover { border-color: var(--brand-2); }
.fav-card img { width: 100%; border-radius: 5px; display: block; margin-bottom: 9px; }
.fc-t { font-size: 13px; font-weight: 700; color: var(--text); }
.fc-m { font-size: 10.5px; color: var(--text-3); margin: 4px 0 8px; }
.fc-f { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* ── 订单 ─────────────────────────────────────────────────── */
.od { padding: 14px 0; border-bottom: 1px solid var(--ink-4); }
.od:last-child { border-bottom: 0; padding-bottom: 0; }
.od-hd { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; font-size: 12.5px; }
.od-no { color: var(--gold-ink); font-weight: 700; }
.od-items { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0; }
.od-it {
  padding: 4px 9px; border-radius: 99px; background: var(--ink); border: 1px solid var(--ink-4);
  font-size: 11.5px; color: var(--text-2);
}
.od-it .mono { color: var(--text-3); font-size: 10px; }
.od-ft { font-size: 11.5px; color: var(--text-3); }

/* ── 我的订单页（orders.html · 2026-09-30）─────────────────────
   一单一张卡：抬头（单号/状态/时间/金额）→ 明细（**带卡图**）
   → 收货与物流 → 页脚（金额明细 + 操作按钮）。 */
.mo {
  border: 1px solid var(--ink-4); border-radius: var(--r-l1);
  background: var(--ink-2); padding: 14px 16px; margin-bottom: 14px;
}
.mo-hd { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 12.5px; }
.mo-no { color: var(--gold-ink); font-weight: 700; letter-spacing: .02em; }
.mo-time { font-size: 11.5px; }
.mo-total { margin-left: auto; font-size: 15px; color: var(--text); }
.mo-state {
  padding: 2px 9px; border-radius: 99px; font-size: 11px; font-weight: 700;
  border: 1px solid currentColor;
}
.st-wait { color: var(--text-3); }
.st-go   { color: var(--gold-ink); }
.st-ok   { color: var(--green, #3fb950); }
.st-warn { color: var(--brand-2); }
.st-bad  { color: var(--brick); }

.mo-items {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 10px; margin: 12px 0;
}
.mo-it {
  display: flex; align-items: center; gap: 11px; text-decoration: none;
  padding: 8px; border: 1px solid var(--ink-4); border-radius: var(--r-l1);
  background: var(--ink); transition: border-color .2s ease;
}
a.mo-it:hover { border-color: var(--brand-2); }
/* 缩略图盒子固定尺寸：图与占位字标叠在一起，图挂了就露出字标 */
.mo-it-th {
  position: relative; flex: 0 0 52px; width: 52px; height: 70px;
  border-radius: 5px; overflow: hidden; background: var(--ink-3);
}
.mo-it-th img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mo-it-ph {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 20px; font-weight: 800; color: var(--text-3); z-index: -1;
}
.mo-it-b { min-width: 0; flex: 1; }
.mo-it-n { font-size: 13px; font-weight: 700; color: var(--text); margin-bottom: 4px; }
.mo-it-m { font-size: 10.5px; color: var(--text-3); }
.mo-it-p { margin-top: 6px; font-size: 12.5px; color: var(--text-2); }
.mo-it-q { margin-left: 8px; color: var(--text-3); font-size: 11.5px; }

.mo-info { display: grid; gap: 7px; padding: 10px 0; border-top: 1px dashed var(--ink-4); }
.mo-recv { font-size: 12px; color: var(--text-2); display: flex; gap: 8px; flex-wrap: wrap; align-items: baseline; }
.mi-k { color: var(--text-3); font-size: 11px; }
.mi-addr { color: var(--text-3); font-size: 11.5px; }
.mo-track {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  padding: 8px 11px; border-radius: var(--r-l3); font-size: 12px;
  background: rgba(63,185,80,.08); border: 1px solid rgba(63,185,80,.32); color: var(--text-2);
}
.mo-track.off { background: var(--ink); border-color: var(--ink-4); }
.mt-ic { font-size: 14px; }
.mt-no { color: var(--gold-ink); letter-spacing: .04em; }
.mo-refund {
  display: flex; align-items: center; gap: 9px; font-size: 12px; color: var(--text-2);
  padding: 7px 11px; border-radius: var(--r-l3);
  background: rgba(139,30,45,.10); border: 1px solid rgba(139,30,45,.35);
}
.mo-refund .mono { color: var(--gold-ink); }

.mo-ft {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding-top: 11px; border-top: 1px solid var(--ink-4);
}
.mo-sum { font-size: 11.5px; color: var(--text-3); }
.mo-sum b { color: var(--text); font-size: 13px; }
.mo-acts { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }

/* 未登录时购物车摘要里的会员条要高亮（游客不能下单） */
.m-bar.warn { border-color: var(--brick); background: rgba(139,30,45,.12); }
.m-bar.warn b { color: var(--text); }

/* ── 设置 ─────────────────────────────────────────────────── */
/* 前缀统一为 settings-*。原用 .set-grid，与首页「按系列找」的 .set-grid（系列卡 5 列）
   （那个已于 2026-10-16 随版块独立成页删除，见文件上部三次清理注释）
   同名 —— 两份定义在同一文件里静默互相覆盖，首页系列卡列数长期走错。
   2026-09-19 拆名消歧：首页保留 .set-grid，会员设置改用 .settings-*。 */
.settings-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; }
.settings-box {
  padding: 14px; border: 1px solid var(--ink-4); border-radius: var(--r-l1);
  background: var(--ink-2); display: grid; gap: 12px; align-content: start;
}
.settings-box.danger { border-color: rgba(139,30,45,.55); background: rgba(139,30,45,.10); }
.settings-t { font-size: 12px; font-weight: 800; letter-spacing: .08em; color: #ff8b93; }
.settings-msg { min-height: 15px; font-size: 11.5px; color: var(--gold-ink); }

/* ── 称号（account.html 我的称号 · 字典 data/titles.js）────── */
/* 横幅图自带称号字样与人物立绘（约 3.3:1），直接整图渲染，不加文字层 */
.title-banner { display: block; width: 100%; height: auto; border-radius: 8px; }
.ti-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 12px; }
.ti-card {
  padding: 10px; border: 1px solid var(--ink-4); border-radius: var(--r-l1);
  background: var(--ink-2); transition: border-color .2s ease;
}
.ti-card:hover { border-color: var(--brand-2); }
.ti-card.on { border-color: var(--gold); background: linear-gradient(120deg, rgba(255,224,0,.08), rgba(20,20,20,0)); }
.ti-card.locked { opacity: .55; }
.ti-card.locked .title-banner { filter: grayscale(1) brightness(.75); }
.ti-banner { margin-bottom: 10px; }
.ti-ft { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 30px; }
.ti-name { font-size: 12px; font-weight: 700; color: var(--text-2); }
.ti-lock { font-size: 11px; }
/* 资料块上的称号入口（2026-09-20 拍板：称号不做独立板块，附在概览资料里、点击弹窗更换） */
.ov-title {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 14px; padding: 6px 10px;
  background: none; border: 1px dashed var(--ink-4); border-radius: var(--r-l1);
  cursor: pointer; color: var(--text-2); position: relative;
  transition: border-color .2s ease;
}
.ov-title:hover { border-color: var(--gold); }
.ov-title .title-banner { width: auto; height: 36px; border-radius: 6px; }
.ov-title-empty { font-size: 12.5px; font-weight: 700; padding: 4px 6px; }
/* 称号入口的角标：与头像 / 昵称两处统一为「文字胶囊」，不再用 ✎ */
.ov-title-pen {
  font-size: 10.5px; font-weight: 800; letter-spacing: .04em; line-height: 1.3;
  padding: 2px 8px; border-radius: 99px;
  border: 1px solid var(--ink-4); color: var(--text-3);
  transition: opacity .2s ease, color .2s ease, border-color .2s ease;
}
.ov-title:hover .ov-title-pen { color: var(--gold-ink); border-color: rgba(255,224,0,.5); }
/* 弹窗里的称号选择器：复用 .ti-card，pick = 可点候选、sel = 本次选中（金框） */
.title-modal { width: min(620px, 100%); }
.ti-pick { margin: 14px 22px 0; }
.ti-pick .ti-card.pick { cursor: pointer; }
.ti-pick .ti-card.sel {
  border-color: var(--gold);
  background: linear-gradient(120deg, rgba(255,224,0,.08), rgba(20,20,20,0));
  box-shadow: 0 0 0 1px var(--gold);
}
/* 称号兑换码入口（2026-09-21 拍板权限制：弹窗底部一行，输码兑奖当场解锁） */
.ti-redeem { display: flex; gap: 8px; margin: 14px 22px 0; }
/* 称号发放面板（account.html 店主专属 · 2026-09-21 拍板） */
.tg-row { display: flex; gap: 8px; }
.tg-row .input:first-child { flex: 1; min-width: 0; }
.tg-btns { display: flex; gap: 8px; align-items: center; margin-top: 10px; }
.tg-btns .spacer { flex: 1; }
.tg-codes { margin-top: 12px; display: grid; gap: 6px; }
.tg-code {
  display: flex; gap: 10px; align-items: baseline; font-size: 12px;
  padding: 6px 10px; border: 1px solid var(--ink-4); border-radius: 8px; background: var(--ink-2);
}
.tg-code .t { font-weight: 700; color: var(--text-2); }
.tg-code .muted { margin-left: auto; }
.tg-code.used { opacity: .5; }

/* ── 内置头像选择器（account.html 更换头像弹窗 · 字典 data/avatars.js）──
   2026-09-20 拍板：只内置不上传。格子沿用 .ti-card 的 sel 金框手感，圆头像居中 */
.av-grid {
  margin: 14px 22px 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 10px;
}
.av-card {
  padding: 12px 8px 10px; text-align: center; cursor: pointer;
  border: 1px solid var(--ink-4); border-radius: var(--r-l1); background: var(--ink-2);
  transition: border-color .2s ease, box-shadow .2s ease;
}
.av-card:hover { border-color: var(--brand-2); }
.av-card.sel {
  border-color: var(--gold);
  background: linear-gradient(120deg, rgba(255,224,0,.08), rgba(20,20,20,0));
  box-shadow: 0 0 0 1px var(--gold);
}
.av-img {
  width: 56px; height: 56px; margin: 0 auto 8px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; overflow: hidden;
  font-size: 22px; font-weight: 800; color: var(--gold-ink);
  background: radial-gradient(120% 120% at 30% 25%, var(--ink-2), var(--ink-3));
  border: 2px solid rgba(184,147,46,.45);
}
.av-img img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; display: block; }
.av-name { font-size: 11.5px; font-weight: 700; color: var(--text-2); }

/* ── 卡组弹窗表单（decks.html 玩家上传 & meta.html 店主编辑 共用）──
   2026-09-20 拍板：decks.html 改玩家上传广场、meta.html 承接上位环境，两处表单同款 */
.up-modal { width: min(680px, 100%); max-height: 86vh; display: flex; flex-direction: column; }
.up-body { padding: 14px 22px 4px; overflow-y: auto; display: grid; gap: 12px; }
.up-row { display: flex; gap: 12px; }
.up-row .fl { flex: 1; min-width: 0; }
.up-row3 .fl:nth-child(2) { flex: none; width: 150px; }
textarea.input { resize: vertical; font-family: inherit; line-height: 1.7; }
.up-check { min-height: 20px; font-size: 12.5px; }
.up-check .ok { color: var(--gold-ink); font-weight: 700; }

/* ── 校验提示：工具行右端，白字（2026-10-06，同日二次拍板）──────────────────
   位置：`.up-toprow` 末尾（紧挨「基本卡组 0/40–50 · 进化卡组 0/10」），
       `margin-left: auto` 顶到最右；顺带把网格底部那 36px（26 行高 + 10 行距）还给卡图。
   内容：**通过时**一句「✓ 校验通过 · 预计造价 ￥X」；
       **未通过时一个字都不写** —— 那几句与旁边的计数完全重复，用户要求删掉
       （原因仍在 `title` 上，悬停可查，不是真丢）。
   `flex: 0 1 auto` = 只占内容宽、放不下才缩，永远不溢出。 */
#upMask .up-toprow .up-check {
  flex: 0 1 auto; margin-left: auto; min-width: 0; max-width: 100%;
  padding-bottom: 8px; text-align: right; line-height: 1.45;
  font-size: 12px; color: #fff;
}
/* 未通过校验时 upCheck() 不写任何字 → 连那 8px 与 min-height 一起收掉，
   让它真正「不存在」，不在工具行右侧留一块空白。 */
#upMask .up-toprow .up-check:empty { display: none; }
#upMask .up-toprow .up-check .chk { color: #fff; margin-right: 10px; }
#upMask .up-toprow .up-check .chk::before { content: "· "; color: rgba(255,255,255,.45); }
#upMask .up-toprow .up-check .ok { color: #fff; }
#upMask .up-toprow .up-check .warn { color: rgba(255,255,255,.72); margin-left: 10px; }
.dk-rank.hub { background: transparent; color: var(--brand-2); border: 1px solid var(--brand-2); }

/* 上传卡组弹窗单独收紧遮罩内边距：`.mask` 原本给自己留 22px，
   是弹窗长不高的唯一原因。只作用于这个遮罩，其它弹窗仍走 .mask 的 22px。 */
#upMask { padding: 8px 14px; }

/* ── 高度预算（2026-10-06：作者留言改常驻后重算）──────────────
   弹窗已经顶到视口上限（calc(100vh - 18px)），所以“作者留言常驻”吃掉的
   100 多 px 只能从别的常驻块里抠。当前账（视口 1615×909）：

     弹窗 891  − 页头 26 − 工具行 39 − 作者留言 117 − 页脚 39 − 正文内边距 6
     = 卡图网格 **601px**

   ⚠️ **卡图尺寸是阶梯式的**：先由网格高反算出列数，列数再决定单格宽。
   网格 601px → 7 列 → 卡图 **208×290**；只要矮到 591px 下面，就会掉到 8 列→只剩 178px。
   所以这里的内边距不是随便改的 —— 它们凑在一起才能把卡图抬过台阶，
   单独改一两个 2px 是看不出效果的。改完请跑 `_verify_upzone.cjs`，它会打印实测尺寸。

   ── /* ── 卡组上传 · 卡图墙构筑（decks.html · 2026-09-21 二次拍板）──
   
   对齐 svehelperwin 的构筑体验：大面板 + 本职业卡图网格，
   顶部「基本 / 进化」切换目标区，悬停卡面浮出数量与 ＋ / －。

   2026-10-01 用户反馈「卡图太小、看不清」→ 面板与卡图一起放大。
   实测量到的变化（视口 1440×1000，见验收脚本 `_verify_upzone.cjs`）：
     单格卡图 154 → 215 px（卡面面积约 2 倍，卡上的效果文字终于读得清）
     网格可视高 325 → 450+ px（下面四条一起省出来的：抬高上限、收窄行距、压紧头尾）
   ⚠️ `max-height` 必须跟着抬 —— 只写 `height` 没用，`.modal` 的 86vh 会把它卡住
      （第一次就是只改了 height，实测还是 860px 封顶）。
   🔴 单格宽度只由下面 .up-grid 的 --upg-cols 决定（由 upGridFit() 按高度反算）；
      .upg-card 的高度由自身 aspect-ratio 推出来，别在任何地方手写卡图高度。

   2026-10-06 用户要求「预览大框再往下拉长点」：
     高度 95vh → calc(100vh - 18px)，配合上面 #upMask 的内边距收紧（22 → 8px）。
     `- 18px` 而不是 `- 16px`：留 2px 余量，免得子像素取整让弹窗比视口高 1px
     （验收里有「弹窗零溢出」这条断言）。
     ⚠️ `height` 与 `max-height` 必须**一起写** —— `.modal` 的全局 `max-height: 88vh`
       会把只写了 height 的弹窗卡住（第一次踩过）。 */
.up-modal-lg {
  width: min(1560px, 97vw);
  /* 高度写两遍：先 vh 兜底，再 dvh 覆盖（2026-10-23）。
     手机浏览器的 vh 取的是「地址栏收起后」的最大可视高度，而地址栏在时
     可视区比它矮 —— 按 vh 算出来的弹窗会把底部按钮排推出屏幕外。
     dvh 跟着真实可视高度走；不支持的浏览器仍用上一行 vh。 */
  height: min(calc(100vh - 18px), 1280px);
  height: min(calc(100dvh - 18px), 1280px);
  max-height: min(calc(100vh - 18px), 1280px);
  max-height: min(calc(100dvh - 18px), 1280px);
}
/* 页头：标题与副说明**并成一行**（原来是两行，占 69px）。这一行省下的 33px
   直接变成卡图网格的高度 —— 见 .up-note 那段注释里的尺寸账。 */
.up-modal-lg .modal-hd { display: flex; align-items: baseline; gap: 12px; padding: 4px 22px 0; }
.up-modal-lg .modal-hd h3 { margin: 0; flex: none; }
.up-modal-lg .up-body { gap: 8px; }
.up-modal-lg .modal-ft { padding: 6px 22px 6px; }
/* 上下内边距 14/4 → 6/0：这 8px 同样直接变成卡图网格的高度。
   2026-10-06：留言块改成常驻后它又少了 6px —— 见下面那段「高度预算」。 */
.up-modal-lg .up-body { display: flex; flex-direction: column; overflow: hidden; gap: 10px; padding: 6px 22px 0; }
.up-toprow { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; }
.up-toprow .fl { flex: 1; min-width: 150px; }
.up-toprow .fl > span { font-size: 11.5px; }
.up-toprow .input { padding: 7px 10px; }

/* ── 作者留言输入区（上传卡组 · 2026-10-01，2026-10-06 改折叠）──────────
   卡组自带的说明文字（随卡组保存、展示在构筑详情页顶部），作者一次写完、别人只读。

   2026-10-06 二次拍板：**常驻展开，不做折叠**。中间那版默认收起（省 108px 给网格）
   被用户否掉了 —— 折叠态只留一行「＋ 作者留言」，作者根本不知道这里能写字。
   现在这块固定占着高度，卡图尺寸由 upGridFit() 按**剩下的**可视高反算，
   所以不需要任何「展开 / 收起后重算」的钩子，`[data-open]` 那套也一并删了。 */
.up-note { display: flex; flex-direction: column; gap: 4px; }
.up-note-hd { display: flex; align-items: baseline; gap: 8px; }
.up-note-hd .up-note-t { font-size: 12.5px; font-weight: 700; color: var(--text-2); }
.up-note-bd { display: flex; flex-direction: column; gap: 4px; }
.up-note .hint { font-weight: 400; letter-spacing: 0; }
/* 常驻展开后留言块固定占 138px，而弹窗已经顶到视口高度上限 —— 这块多高，
   卡图就少多高。3 行（92px）对一个「选填」字段太奢侈，压到 2 行（60px）：
   右下角仍可手动拖高，`upNoteText()` 一个字都不少。 */
.up-note textarea {
  width: 100%; min-height: 46px; max-height: 140px; resize: vertical;
  font-size: 12.5px; line-height: 1.7;
}
.up-note-ft { display: flex; align-items: center; gap: 10px; min-height: 12px; font-size: 11.5px; }
.up-note-n { color: var(--text-3); font-variant-numeric: tabular-nums; }
.up-note-n.over { color: var(--gold-ink); font-weight: 700; }
.up-note-msg { flex: 1; color: var(--text-3); }
.up-note-msg.ok { color: var(--text-3); }
.up-note-msg.warn { color: var(--gold-ink); }
.up-note-msg.bad { color: #F3B6C2; }
.up-zonetabs {
  display: inline-flex; gap: 4px; flex: none; margin-left: auto;
  border: 1px solid var(--ink-4); border-radius: 9px; padding: 3px; background: var(--ink-2);
}
.up-zonetabs button {
  border: 0; background: none; color: var(--text-2); cursor: pointer;
  font: 700 13px/1 var(--sans); padding: 9px 14px; border-radius: 7px; white-space: nowrap;
  transition: background .15s ease, color .15s ease;
}
.up-zonetabs button b { color: var(--gold-ink); }
.up-zonetabs button i { font-style: normal; font-weight: 400; opacity: .55; font-size: 11px; }
.up-zonetabs button:hover { color: var(--gold-ink); }
.up-zonetabs button.on { background: var(--gold); color: #141414; }
.up-zonetabs button.on b, .up-zonetabs button.on i { color: #141414; opacity: .8; }
/* 2026-10-06：`.up-gridbar`（找卡独占一行）已撤，找卡并入 .up-toprow。
   两个输入按「名字固定、找卡吃掉剩余」分配，宽屏下名字不至于拉成一条长条。 */
.up-toprow .up-name { flex: 0 1 220px; }
.up-toprow .up-find { flex: 1 1 260px; }
.up-gridn { font-weight: 400; font-size: 11.5px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.up-grid {
  flex: 1; overflow-y: auto; min-height: 180px;
  display: grid; grid-template-columns: repeat(var(--upg-cols, 6), minmax(0, 1fr));
  gap: 12px; padding: 2px; align-content: start;
  overscroll-behavior: contain;
}
/* 滚动条走全站那一份（见文件开头铁律） */
.up-grid-empty { grid-column: 1 / -1; font-size: 12.5px; padding: 18px 4px; }
/* 2026-09-21 三次拍板（滑动卡顿修复 + 同日四次修正）：
   ① 高度改由 .upg-card 自身 aspect-ratio 提供、img 改绝对定位铺满 ——
      「网格 auto 行 + img aspect-ratio」组合踩过 Chromium 塌 2px 的坑
      （overflow:hidden 触发），卡片自身定高后天然免疫；
   ② 卡顿修复：.mask 去掉 backdrop-filter（见第 10 节）+ img decoding=async。
      初版的 content-visibility:auto 已撤 —— 焦点元素落在其跳过区会触发
      Chromium 布局失效循环（页面假死：悬停失效、点击无响应，2026-09-21 用户实测），
      与「＋/－ 按钮持有焦点」叠加时必现；配合网格委托里的 btn.blur() 双保险；
   ③ 滚动条按站内口径美化（对齐 .filters-in：细轨深灰、悬停金）。 */
.upg-card {
  position: relative; aspect-ratio: 445 / 620; align-self: start;
  border-radius: 8px; cursor: pointer;
  border: 1px solid var(--ink-4); background: var(--ink-2);
  transition: border-color .15s ease;
}
.upg-card:hover { border-color: var(--gold); }
.upg-card img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block;
  border-radius: 7px 7px 0 0;
}
/* 已选角标：不悬停也看得到这张卡在当前目标区里的张数 */
.upg-own {
  position: absolute; top: 5px; right: 5px; pointer-events: none;
  background: rgba(20,20,20,.92); color: var(--gold-ink);
  font-size: 13px; font-weight: 700; border-radius: 6px; padding: 3px 8px;
  border: 1px solid rgba(255,224,0,.5);
}
/* 悬停控制层：数量大字 + ＋ / － 圆钮（对齐参考截图） */
.upg-ctl {
  position: absolute; inset: 0; pointer-events: none;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  background: rgba(10,10,10,.55); opacity: 0; transition: opacity .15s ease;
}
.upg-card:hover .upg-ctl, .upg-card:focus-within .upg-ctl { opacity: 1; }
.upg-n { font-size: 32px; color: #fff; text-shadow: 0 1px 8px rgba(0,0,0,.7); }
.upg-btns { display: flex; gap: 14px; pointer-events: auto; }
.upg-btns button {
  width: 46px; height: 46px; border-radius: 50%; border: 0; padding: 0;
  background: rgba(245,245,240,.95); color: #141414;
  font: 800 22px/1 var(--sans); cursor: pointer;
  transition: background .15s ease, transform .15s ease;
}
.upg-btns button:hover { background: var(--gold); transform: scale(1.06); }
.upg-btns button:disabled { opacity: .35; cursor: default; transform: none; }
/* 窄屏 / 小窗：卡图跟着窗口缩，别让一行只塞得下一张、也别撑出横向滚动 */
@media (max-width: 1120px) {
  .up-modal-lg { width: 97vw; }
  .up-grid { grid-template-columns: repeat(auto-fill, minmax(158px, 1fr)); }
}
@media (max-width: 760px) {
  .up-grid { grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); gap: 8px; }
}
.up-paste { border-top: 1px dashed var(--ink-4); padding-top: 10px; display: grid; gap: 8px; }
.up-paste-ft { display: flex; gap: 8px; justify-content: flex-end; }
/* 筛选按钮（2026-09-21 拍板：弹站内居中筛选弹窗，点选即时生效） */
.up-fbtn { position: relative; flex: none; align-self: flex-end; }
.up-fbtn.on { border-color: var(--gold); color: var(--gold-ink); }
.up-fbadge {
  position: absolute; top: -7px; right: -7px; font-style: normal;
  min-width: 17px; height: 17px; padding: 0 4px; border-radius: 9px;
  background: var(--gold); color: #141414; font: 700 11px/17px var(--sans);
  text-align: center; pointer-events: none;
}
/* ── 上传构筑 · 筛选弹窗（decks.html · 2026-09-21 六次拍板改版）────
   视觉词汇与卡库页筛选栏完全同源：.fopt 药丸 / .fopt.has-ico 职业徽章 /
   .fopts.scroll 两列网格 + .fsub 分节（补充包 / 预组 / PR卡），不再另造 .f-chip 一套。
   留白按美化字典放宽：弹窗 640px、组距 22px、组标 11px/800/.14em、药丸呼吸感对齐卡库页。 */
/* 弹窗本体**永不滚动**（.modal 基类的 overflow:auto 会在弹窗层漏出系统默认粗滚动条，
   2026-09-21 用户拍板修掉）—— 改 flex 纵排，头部 / 底栏固定，只有 .fmodal-bd 内滚
   （细轨深灰悬停金），系列 / 种族长清单再各自内滚，三层互不串。 */
.fmodal {
  width: min(640px, 100%);
  display: flex; flex-direction: column;
  overflow: hidden;
}
.fmodal-bd {
  flex: 1; min-height: 0;
  padding: 8px 28px 2px;
  overflow-y: auto; overscroll-behavior: contain;
}
/* 滚动条走全站那一份（见文件开头铁律） */
.f-g { margin-bottom: 22px; }
.f-g:last-child { margin-bottom: 14px; }
.f-g > h4 {
  margin: 0 0 10px; font-size: 11px; font-weight: 800; letter-spacing: .14em;
  color: var(--text-3);
}
.f-g .fopts { gap: 8px; }
.f-g .fopt { padding: 7px 13px; font-size: 12.5px; }
.f-g .fopt.has-ico { padding: 5px 13px 5px 6px; }
.f-g .fopt.has-ico .fopt-ico { width: 26px; height: 30px; }
/* 长清单（系列 / 种族）：两列网格限高滚动，滚到头不穿透带动弹窗后面的页面 */
.fmodal .lim-lg, .fmodal .lim-sm {
  max-height: 252px; overflow-y: auto; overscroll-behavior: contain;
  padding-right: 6px;
}
.fmodal .lim-sm { max-height: 162px; }
/* 滚动条走全站那一份（见文件开头铁律） */
/* 2026-10-01：「只看进化印版」勾选项已删（原来是 .f-evo 这一组）。
   目标区（基本 / 进化卡组）现在是**硬隔离**的 —— 主卡组里根本不会出现进化印版，
   进化卡组里也只会出现进化印版，再留一个勾选框只会勾出空网格。 */

/* ── 轻提示 ───────────────────────────────────────────────── */
.toast {
  /* 🔴 2026-10-26 店主：「复制牌组码的提示跑到下面那页去了」——
     提示本身没错，是**层级**错了：牌组码/导出图那两个弹窗的遮罩是 `z-index:880`，
     而 toast 只有 200，于是它被压在遮罩后面，看着像是在底下的页面里冒出来。
     全站最高层是 960（弹窗栈），toast 提到 1000 —— 任何弹窗打开时都必须看得见。 */
  position: fixed; left: 50%; bottom: 34px; z-index: 1000;
  transform: translate(-50%, 12px); opacity: 0;
  padding: 11px 20px; border-radius: var(--r-l1);
  background: var(--ink-3); border: 1px solid var(--gold); color: var(--text);
  font-size: 13px; font-weight: 600; box-shadow: var(--shadow-2);
  transition: opacity .25s ease, transform .25s ease;
}
.toast.on { opacity: 1; transform: translate(-50%, 0); }
.toast.danger { border-color: var(--brick); }

/* ── 响应式 ───────────────────────────────────────────────── */
@media (max-width: 900px) {
  .auth-grid, .ov, .two-col { grid-template-columns: 1fr; }
  .fav-grid { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); }
}
@media (max-width: 680px) {
  .member-btn { padding: 0 10px; font-size: 12px; height: 32px; }
  .member-btn .badge.lvl { display: none; }
  /* 页头空间紧张：缩间距，给会员 + 购物车让位 */
  .topbar-in { gap: 10px; }
  .brand { gap: 8px; margin-right: 0; }
  .topbar-right { gap: 6px; }
  .cart-btn { padding: 8px 10px; font-size: 12.5px; gap: 6px; }
  .redeem-grid { grid-template-columns: 1fr 1fr; }
  .fav-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .settings-grid { grid-template-columns: 1fr; }
  .cp-cards { grid-template-columns: 1fr; }
}

/* ══ 资料卡跨页常驻（2026-10-18）════════════════════════════════════════════
   用户：「这一块要常驻，无论是点我的卡组、收藏或者任何一个」。
   非 profile 页把 `.mycard-slot` 挂在页面最上面、下面紧跟块状二级导航，
   所以只要一个下边距；profile.html 自己那条 #myNav 自带 margin，不会叠出双倍间距。 */
.mycard-slot { margin: 0 0 22px; }
/* 未登录的门禁条：整块可点（跳 profile.html 登录），所以不能有「看起来像链接」的下划线 */
a.profile-card.pf-gate { text-decoration: none; color: inherit; transition: border-color .15s, background .15s; }
a.profile-card.pf-gate:hover { border-color: var(--gold); background: var(--ink-3); }
/* ══ 购物车「暂时买不到」那一段（2026-10-18）══════════════════════════════
   库存清空后购物车里 29 件全部买不到，原来整页空白 → 用户以为东西丢了。
   现在它们留在商品列表下方，标明「暂时售完 / 已下架」；补货后自动回到可结算。 */
.cart-unavail { margin-top: 14px; }
.cart-unavail h3 { margin: 0 0 6px; font-size: 13px; font-weight: 800; letter-spacing: .04em; color: var(--text-2); }
.cart-unavail p { margin: 0 0 10px; font-size: 12px; line-height: 1.6; color: var(--text-3); }
.cu-row { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-top: 1px dashed var(--ink-4); }
.cu-row img { width: 30px; border-radius: 4px; flex: none; }
.cu-n { flex: 1 1 auto; min-width: 0; font-size: 12.5px; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cu-q { flex: none; font-size: 12px; color: var(--text-3); }
.cu-t { flex: none; font-size: 11px; font-weight: 700; color: #d98a8a; }

/* ── 收藏页：文件夹（2026-10-21）────────────────────────────────────── */
.fav-dirs { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 14px; }
.fav-dir {
  display: inline-flex; align-items: center; gap: 8px; padding: 8px 13px;
  font: inherit; font-size: 13px; color: var(--text-2); cursor: pointer;
  background: var(--ink-2); border: 1px solid var(--ink-4); border-radius: 10px;
  transition: border-color .12s, box-shadow .12s, color .12s;
}
.fav-dir:hover { border-color: rgba(255,224,0,.45); color: var(--text); }
.fav-dir.on { border-color: var(--gold); color: var(--text); box-shadow: 0 0 0 2px rgba(255,224,0,.16); }
.fav-dir-c { font-style: normal; font-size: 11px; font-weight: 700; color: var(--gold-ink); }
.fav-dir.add { border-style: dashed; color: var(--text-3); }
.fav-dir-tools { display: inline-flex; gap: 8px; margin-left: auto; }

.fc-dir {
  position: absolute; left: 8px; top: 8px; max-width: calc(100% - 52px);
  padding: 2px 8px; border-radius: 999px; font-size: 10.5px; line-height: 1.6;
  color: var(--gold-ink); background: rgba(8,14,24,.82); border: 1px solid rgba(255,224,0,.4);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer;
}
.fc-dir:hover { background: rgba(255,224,0,.16); }

.fav-pop {
  position: absolute; z-index: 960; width: 216px; padding: 6px;
  background: var(--ink-2); border: 1px solid var(--ink-4); border-radius: 10px;
  box-shadow: 0 16px 40px rgba(0,0,0,.5);
}
.fav-pop-t { display: block; padding: 5px 9px 7px; font-size: 11px; color: var(--text-3); font-weight: 500; }
.fav-pop-i {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 9px;
  font: inherit; font-size: 12.5px; text-align: left; color: var(--text-2);
  background: transparent; border: 0; border-radius: 7px; cursor: pointer;
}
.fav-pop-i:hover { background: var(--ink-3); color: var(--text); }
.fav-pop-i.on { color: var(--gold-ink); }
.fav-pop-i i { margin-left: auto; font-style: normal; }
.fav-pop-i.add { color: var(--text-3); border-top: 1px solid var(--ink-4); border-radius: 0 0 7px 7px; margin-top: 4px; }
.fav-ask .modal { width: min(420px, 100%); }
.fav-ask .fav-ask-i { width: 100%; box-sizing: border-box; }

/* 我的回收 · 逐项报价单（2026-10-21）*/
.q-sheet { margin: 10px 0 0; padding: 11px 12px; border-radius: 10px;
  background: var(--ink-3); border: 1px solid var(--ink-4); }
.q-hd { display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  margin-bottom: 8px; font-size: 12px; color: var(--text-3); }
.q-hd b { color: var(--text); font-size: 13px; }
.q-hd span b { color: var(--gold-ink); font-size: 15px; }
.q-tb { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.q-tb th { text-align: left; font-weight: 500; font-size: 11px; color: var(--text-3);
  padding: 0 6px 6px; border-bottom: 1px solid var(--ink-4); }
.q-tb td { padding: 7px 6px; border-bottom: 1px dashed rgba(255,255,255,.06); color: var(--text-2);
  vertical-align: middle; }
.q-tb tr:last-child td { border-bottom: 0; }
.q-tb .num { text-align: right; }
.q-tb .q-i { width: 24px; color: var(--text-3); }
.q-tb .q-n { color: var(--text); }
.q-tb .q-n i { display: inline-block; margin-left: 6px; padding: 0 6px; border-radius: 999px;
  font-size: 10.5px; font-style: normal; color: var(--gold-ink); border: 1px solid rgba(255,224,0,.35); }
/* 卡图（2026-10-21）：明细里出现「某张卡」就必须给图 —— 项目铁律「卡名一律用图」。
   48px 竖版、与持有明细同比例（1:1.4，cover 不会切掉卡名/费用）。
   34px 试过：缩到看不清是哪张牌（卡名区只剩几像素），而柜台和玩家都要靠它认卡。
   🔴 别给 td 本身设 display:flex —— 那会把 table-cell 变成块级，整列对齐全崩；
      这里用 inline-block + vertical-align 排版。 */
.q-img { display: inline-block; vertical-align: middle; flex: 0 0 auto;
  width: 48px; aspect-ratio: 1 / 1.4; margin-right: 9px; padding: 0; border: 0;
  border-radius: 5px; overflow: hidden; background: var(--ink-4); cursor: pointer;
  line-height: 0; }
.q-img > img { width: 100%; height: 100%; object-fit: cover; display: block; }
.q-img.is-ph { line-height: 1.4; text-align: center; font-size: 15px; color: var(--text-3);
  border: 1px dashed rgba(255,255,255,.14); cursor: default; }
.q-nm { display: inline; vertical-align: middle; }
.q-note { margin: 8px 0 0; font-size: 11.5px; line-height: 1.7; color: var(--text-3); }

/* 现金 / 积分 切换（2026-10-21 月卡权益第 4 条）
   为什么做成两段小胶囊而不是下拉：一张单往往只有两三行，胶囊一眼看全，
   而且**当前选中的那个必须能看出成本**（行内会写「现金 ￥3 → 3.15 积分」），
   下拉展开才能看到，等于让人凭记忆比价。 */
.q-tb .q-p { width: 92px; text-align: right; white-space: nowrap; }
.q-seg { display: inline-flex; border: 1px solid var(--ink-4); border-radius: 999px;
  overflow: hidden; background: var(--ink-2); vertical-align: middle; }
.q-sg { appearance: none; border: 0; background: transparent; cursor: pointer;
  padding: 3px 9px; font-size: 11.5px; line-height: 1.5; color: var(--text-3);
  font-family: inherit; transition: background .12s, color .12s; }
.q-sg:hover { color: var(--text); }
.q-sg.on { background: rgba(255,255,255,.10); color: var(--text); font-weight: 600; }
.q-sg[data-pay="points"].on { background: rgba(255,224,0,.16); color: var(--gold-ink); }
.q-tag { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 11px;
  color: var(--text-3); border: 1px solid var(--ink-4); }
.q-tag.is-pts { color: var(--gold-ink); border-color: rgba(255,224,0,.35); }
/* 换成积分的那一行：小计划掉，换算出「现金 ￥X → Y 积分」 */
.q-tb tr.is-pts .q-s { color: var(--text-3); }
.q-tb .q-s s { text-decoration: line-through; opacity: .55; }
.q-conv { display: block; margin: 2px 0 0 57px; font-size: 11px; line-height: 1.5;
  color: var(--text-3); }
.q-conv b { color: var(--gold-ink); font-weight: 700; }
/* 合计条 */
.q-sum { display: flex; align-items: baseline; justify-content: flex-end; gap: 6px;
  margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--ink-4);
  font-size: 12px; color: var(--text-3); }
.q-sum b { font-size: 15px; color: var(--text); }
.q-sum b.pt { color: var(--gold-ink); }
.q-sum i { font-style: normal; color: var(--text-3); padding: 0 4px; }
/* 批量提交条（2026-10-23）：逐项改动先在本地攒着，这里一次性发出去。
   有改动时整条一直亮着 —— 让玩家清楚「还没告诉柜台」。 */
.q-draft { display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  margin-top: 9px; padding: 9px 12px; border-radius: 10px;
  background: rgba(255,224,0,.09); border: 1px solid rgba(255,224,0,.3);
  font-size: 12.5px; color: var(--text-3); }
.q-draft b { color: var(--gold-ink); font-size: 14px; }
.q-draft [data-commit] { margin-left: auto; }
.q-draft [data-commit] { background: rgba(255,224,0,.16); }

/* 整单快捷 */
.q-quick { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-top: 9px; }
/* 已确认报价后结算方式锁住（2026-10-23）：不摆一排灰按钮（看着像还能点），
   只留一行说明 —— 想改去向是「改一下」回到报价确认那一步。 */
.q-locked {
  margin-top: 9px; padding: 7px 11px; border-radius: 8px;
  font-size: 11.5px; line-height: 1.7;
  color: var(--text-3); background: var(--ink-2);
  border: 1px dashed var(--ink-4);
}
.q-qk { appearance: none; cursor: pointer; font-family: inherit; font-size: 11.5px;
  padding: 4px 11px; border-radius: 8px; color: var(--text-2);
  background: var(--ink-2); border: 1px solid var(--ink-4); }
.q-qk:hover { color: var(--text); border-color: rgba(255,255,255,.22); }
.q-qk.gold { color: var(--gold-ink); border-color: rgba(255,224,0,.32); background: rgba(255,224,0,.07); }
.q-mult { font-size: 11px; color: var(--text-3); }
/* 保存中：整张单降透明度，防连点（不清空内容，失败就是原样） */
.pre-item.is-saving { opacity: .62; pointer-events: none; }
/* 金额行里的积分（金色，与「报价」现金色区分开） */
.pre-money b.pt { color: var(--gold-ink); }
.pre-money .pre-tip { font-size: 11px; color: var(--text-3); }
@media (max-width: 620px) {
  .q-tb .q-p { width: 78px; }
  .q-sg { padding: 3px 7px; font-size: 11px; }
  .q-conv { margin-left: 0; }
}

/* ══ 积分（2026-10-21 改版：1 积分 = ￥1，结算直接抵扣，不再换券）══════ */

/* 购物车结算栏的「用积分抵扣」开关 */
.pt-wrap {
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px;
  margin: 10px 0; padding: 9px 12px; border-radius: var(--r-l3);
  background: var(--ink-2); border: 1px solid var(--ink-4);
}
.pt-opt { display: flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--text-2); cursor: pointer; }
.pt-opt input { width: 15px; height: 15px; accent-color: var(--gold); cursor: pointer; margin: 0; }
.pt-opt b { color: var(--gold-ink); font-size: 13.5px; }
.pt-hint { font-size: 11px; font-style: normal; color: var(--text-3); }
.sum-points i { font-style: normal; font-size: 11px; color: var(--text-3); margin-left: 4px; }

/* 会员中心 · 积分面板（原来那屏「积分兑换」网格已删） */
.pt-big { display: flex; align-items: baseline; gap: 8px; margin: 4px 0 12px; }
.pt-big b { font-size: 30px; font-weight: 800; color: var(--gold-ink); letter-spacing: -.02em; line-height: 1.1; }
.pt-big span { font-size: 12.5px; color: var(--text-3); }
.pt-big em { margin-left: auto; font-style: normal; font-size: 12px; color: var(--text-2); }
.pt-rules { margin: 0; padding-left: 18px; font-size: 12.5px; line-height: 1.95; color: var(--text-2); }
.pt-rules b { color: var(--text); }
.pt-rules a { color: var(--gold-ink); font-weight: 700; }
.pt-rules .ok { color: var(--gold-ink); }
@media (max-width: 560px) {
  .q-tb .q-u { display: none; }
  .q-bd, .q-sheet { padding: 9px; }
  .q-img { width: 38px; margin-right: 7px; }
}

/* ── 回收流程条（2026-10-22，第 3/4 步）─────────────────────────────
   报价 → 确认 → 填快递单号 → 验收 → 打款。
   放在报价表下面，是因为它读的是「上面这张报价单」—— 顺序反过来会让人
   以为是新的一块区域。 */
.q-flow { margin-top: 11px; padding: 11px 13px; border-radius: 11px;
  border: 1px solid rgba(255, 224, 0, .30); background: rgba(255, 224, 0, .055); }
.q-flow-t { display: block; font-size: 13px; font-weight: 800; color: var(--text); }
.q-flow-s { display: block; margin-top: 4px; font-size: 12px; line-height: 1.7; color: var(--text-2); }
.q-flow-s b { color: var(--gold-ink); }
.q-flow-s i { font-style: normal; color: var(--text-3); }
.q-flow .q-qk { margin-top: 9px; }
.q-ship { display: flex; gap: 8px; margin-top: 9px; }
.q-ship input { flex: 1; min-width: 0; padding: 9px 11px; border-radius: 9px;
  border: 1px solid var(--ink-4); background: var(--ink-3); color: var(--text); font-size: 14px; }
.q-ship input::placeholder { color: var(--text-3); }
.q-ship input:focus { outline: none; border-color: var(--gold); }
.q-ship .q-qk { margin-top: 0; flex: 0 0 auto; }
@media (max-width: 560px) {
  .q-ship { flex-wrap: wrap; }
  .q-ship input { flex: 1 1 100%; }
  .q-ship .q-qk { flex: 1 1 auto; }
}

/* ── 逐项异议（2026-10-22 店主四步流程第 2 步）────────────────────────
   「这项不行 / 要加价」挂在卡名格下面，不新开列：
   手机上这张表已经 6 列，再加一列会把单价与小计挤成一堆点。
   行本身也变样 —— 不要的划掉变暗、要加价的单价转金，扫一眼就知道哪几项要谈。 */
.q-flags { display: flex; gap: 6px; margin-top: 5px; }
.q-fg { appearance: none; cursor: pointer; font: inherit; font-size: 11px; line-height: 1.6;
  padding: 2px 9px; border-radius: 999px; color: var(--text-3);
  border: 1px solid var(--ink-4); background: transparent; }
.q-fg:hover, .q-fg:focus-visible { color: var(--text); border-color: var(--text-3); }
.q-fg-on { display: inline-flex; align-items: center; gap: 6px; margin-top: 5px;
  font-size: 11px; padding: 2px 4px 2px 9px; border-radius: 999px; }
.q-fg-on.no { color: #ff9a9a; background: rgba(255,120,120,.10); border: 1px solid rgba(255,120,120,.35); }
.q-fg-on.ask { color: var(--gold-ink); background: rgba(255,224,0,.10); border: 1px solid rgba(255,224,0,.35); }
.q-fg-on b { font-weight: 700; }
.q-fg-x { appearance: none; cursor: pointer; font: inherit; font-size: 10.5px;
  padding: 1px 7px; border-radius: 999px; border: 0; background: rgba(255,255,255,.12); color: var(--text-2); }
.q-fg-x:hover { background: rgba(255,255,255,.22); }
.q-tb tr.is-no .q-nm { text-decoration: line-through; opacity: .5; }
.q-tb tr.is-no .q-u, .q-tb tr.is-no .q-s { opacity: .45; }
.q-tb tr.is-ask .q-u { color: var(--gold-ink); }

/* ── 确认须知 + 照片回显（2026-10-22 店主原话）──────────────────────
   报价单上面那三行不是"帮助文本"，是这个流程的规则：
   确认 / 不卖 / 有异议，各自会发生什么。所以给足对比色，不缩成小灰字。 */
.q-notice {
  margin: 11px 0 0;
  padding: 12px 14px;
  border-radius: 11px;
  border: 1px solid rgba(255, 224, 0, .28);
  background: rgba(255, 224, 0, .05);
}
.q-notice-hd {
  display: block;
  margin-bottom: 7px;
  font-size: 13px;
  font-weight: 800;
  color: var(--gold-ink);
}
.q-notice-li {
  display: flex;
  gap: 8px;
  margin: 0 0 6px;
  font-size: 12.5px;
  line-height: 1.7;
  color: var(--text-2);
}
.q-notice-li:last-child { margin-bottom: 0; }
.q-notice-li i {
  flex: 0 0 auto;
  width: 18px;
  text-align: center;
  font-style: normal;
  font-weight: 800;
}
.q-notice-li.ok i { color: #3ec98a; }
.q-notice-li.no i { color: #ff8b96; }
.q-notice-li.ask i { color: var(--gold-ink); }
.q-notice-li b { color: var(--text); }

/* 玩家上传的实物照片：让他自己看到传了什么（拍糊了能自查） */
.q-phs { display: flex; gap: 8px; margin: 10px 0 0; flex-wrap: wrap; }
.q-phs a {
  display: block;
  width: 76px;
  height: 76px;
  border-radius: 9px;
  overflow: hidden;
  border: 1px solid var(--ink-4);
  background: #0a0a0c;
}
.q-phs img { width: 100%; height: 100%; object-fit: cover; display: block; }
@media (max-width: 560px) {
  .q-notice { padding: 10px 12px; }
  .q-notice-li { font-size: 12px; }
  .q-phs a { width: 64px; height: 64px; }
}

/* 提交完成页的"接下来四步"（2026-10-22）：
   原来这里只有一句"把卡寄到店里"，顺序还和实际流程相反（先确认报价再寄）。
   四步要能扫读，所以每步一行、行首一个小圆号。 */
.rc-next { margin-bottom: 10px; }
.rc-next-i {
  display: flex;
  gap: 8px;
  margin-top: 6px;
  font-size: 12.5px;
  line-height: 1.75;
  color: var(--text-2);
}
.rc-next-i i {
  flex: 0 0 auto;
  width: 17px;
  height: 17px;
  margin-top: 2px;
  border-radius: 50%;
  text-align: center;
  font-style: normal;
  font-size: 10.5px;
  line-height: 17px;
  color: #1a1a1a;
  background: var(--gold);
}
.rc-next-i b { color: var(--text); }

/* ── 回收单详细进度弹窗（2026-10-22）────────────────────────────────
   店主：「客户端这里你要改成可以点击进去查看详细进度」。
   卡片负责"一眼看状态"，弹窗负责"这单走到哪一步了"。 */
.pre-detail {
  appearance: none; cursor: pointer; font: inherit;
  margin-right: 8px;
  background: rgba(255, 224, 0, .1);
  border: 1px solid rgba(255, 224, 0, .32);
  color: var(--gold-ink);
}
.pre-detail:hover { background: rgba(255, 224, 0, .18); }

.mr-dlg {
  width: min(880px, 94vw);
  max-height: 90vh;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--ink-4);
  border-radius: 16px;
  background: var(--ink-2);
  color: var(--text);
  box-shadow: 0 24px 70px rgba(0, 0, 0, .6);
}
.mr-dlg[open] { display: flex; flex-direction: column; }
.mr-dlg::backdrop { background: rgba(0, 0, 0, .74); }
.mr-dlg-hd {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 13px 18px;
  border-bottom: 1px solid var(--ink-4);
}
.mr-dlg-hd b { font-size: 15px; font-weight: 800; }
.mr-dlg-x {
  margin-left: auto;
  appearance: none; cursor: pointer; font: inherit;
  font-size: 13px; width: 30px; height: 30px;
  border-radius: 8px; color: var(--text-2);
  background: transparent; border: 1px solid var(--ink-4);
}
.mr-dlg-x:hover { color: var(--text); border-color: var(--text-3); }
.mr-dlg-bd {
  flex: 1 1 auto;
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  padding: 16px 18px 20px;
}
.mr-d-hd {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 14px;
}
.mr-d-no { font-size: 14px; font-family: ui-monospace, Consolas, monospace; }
.mr-d-st { font-size: 12px; color: var(--gold-ink); }

/* 时间线：已完成实心、当前这步高亮、未到虚化 */
.mr-tl {
  list-style: none;
  margin: 0 0 14px;
  padding: 0 0 0 18px;
  border-left: 2px solid var(--ink-4);
}
.mr-tl li {
  position: relative;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 5px 0 5px 4px;
  font-size: 12.5px;
  color: var(--text-3);
}
.mr-tl li::before {
  content: '';
  position: absolute;
  left: -24px;
  top: 11px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--ink-3);
  border: 2px solid var(--ink-4);
}
.mr-tl li.done { color: var(--text-2); }
.mr-tl li.done::before { background: var(--green); border-color: var(--green); }
.mr-tl li.doing { color: var(--gold-ink); font-weight: 700; }
.mr-tl li.doing::before { background: var(--gold); border-color: var(--gold); }
.mr-tl li b { font-weight: 700; color: inherit; }
.mr-tl li span { font-size: 11.5px; color: var(--text-3); }
@media (max-width: 560px) {
  .mr-dlg { width: 96vw; max-height: 92vh; border-radius: 13px; }
  .mr-dlg-bd { padding: 12px 12px 16px; }
}

/* 整单快捷按钮的选中态（2026-10-22 店主「点哪个哪个有黄框」）：
   原来两个按钮长得一模一样，点完没有任何反馈 —— 玩家不知道当前是整单现金还是整单积分。
   选中用金框 + 淡金底，两个都不选 = 混合（那是真实状态，不该假装选了某一个）。 */
.q-qk.on {
  border-color: var(--gold);
  color: var(--gold-ink);
  background: rgba(255, 224, 0, .16);
  box-shadow: 0 0 0 1px rgba(255, 224, 0, .45) inset;
  font-weight: 800;
}
.q-qk.on::before { content: '✓ '; }
.q-qk.gold.on { background: rgba(255, 224, 0, .2); }

/* ── 统一弹窗 SVUI（2026-10-22 店主「杜绝网页自带 UI」）──────────────
   客户端是暗色主题；尺寸与圆角跟站内卡片一致，不再用浏览器原生对话框。 */
.svui {
  /* 🔴 居中的三件套必须显式写（2026-10-22 踩过）：
     本项目全局有 `*{margin:0}`，作者样式**优先于**浏览器 UA 的 `dialog{margin:auto}`，
     于是 showModal 之后弹窗贴在左上角、遮罩也像没生效 —— 店主截图就是这样。
     inset:0 + margin:auto + height:fit-content 才能真居中，不依赖 UA 样式。 */
  position: fixed;
  inset: 0;
  margin: auto;
  height: fit-content;
  max-height: 86vh;
  overflow: auto;
  width: min(420px, 92vw);
  padding: 0;
  border: 1px solid var(--ink-4);
  border-radius: 15px;
  background: var(--ink-2);
  color: var(--text);
  box-shadow: 0 22px 60px rgba(0, 0, 0, .62);
}
.svui::backdrop { background: rgba(0, 0, 0, .72); }
.svui-box { padding: 18px 18px 14px; }
.svui-t {
  display: block;
  font-size: 15px;
  font-weight: 800;
  margin-bottom: 7px;
  color: var(--text);
}
.svui-t:empty { display: none; }
.svui-m {
  margin: 0 0 12px;
  font-size: 13px;
  line-height: 1.75;
  color: var(--text-2);
  white-space: pre-wrap;
}
.svui-in {
  width: 100%;
  box-sizing: border-box;
  padding: 10px 12px;
  margin-bottom: 4px;
  border-radius: 9px;
  border: 1px solid var(--ink-4);
  background: var(--ink-3);
  color: var(--text);
  font-size: 15px;
  font-family: inherit;
}
.svui-in:focus { outline: none; border-color: var(--gold); }
.svui-ft {
  display: flex;
  justify-content: flex-end;
  gap: 9px;
  margin-top: 12px;
}
.svui-b {
  appearance: none;
  cursor: pointer;
  font: inherit;
  font-size: 13px;
  font-weight: 700;
  padding: 9px 18px;
  border-radius: 9px;
  border: 1px solid var(--ink-4);
  background: transparent;
  color: var(--text-2);
}
.svui-b.cancel:hover { color: var(--text); border-color: var(--text-3); }
.svui-b.ok {
  border-color: transparent;
  background: var(--gold);
  color: #1a1a1a;
}
.svui-b.ok:hover { filter: brightness(1.08); }
.svui.is-danger .svui-b.ok { background: #e5484d; color: #fff; }
