/* ============================================================
   有鱼智能体 · 账号中心 + 商城样式(面向客户的登录后区域)
   ------------------------------------------------------------
   令牌体系:shadcn/ui(baseColor: neutral),唯一真源是
   skill `visual-design-system`。

   🔴 本文件**自带完整令牌块**(:root + .dark),不再引用官网
      website/style.css 的 --text-primary / --bg-subtle 那一套,也不再
      写 var(--令牌, 字面回退) 的内联兜底 —— 令牌自给自足之后,回退值
      就是藏在组件层里的硬编码。account/base.html 与 login.html 已随之
      移除 <link href="/style.css">,官网那份样式表怎么改都影响不到这里。
      因此 .btn / .badge / .num 这三组原先借自官网的基元也一并收在本文件。

   🔴 单一样式源铁律:账号中心与商城的样式只写在本文件,
      server/templates/{account,shop}/*.html 里不许再出现内联 <style>。
      (test_shop.test_shop_templates_have_no_inline_style 守着这条。)

   🔴 组件层不写颜色原值:hex / rgb / oklch 只允许出现在下面的令牌块里。

   明暗两皮:根元素挂 .dark 类切换(shadcn 约定;旧体系那套属性选择器已整体退场),
   偏好落 localStorage['youyu.skin'](light|dark|system,默认 light),
   引导脚本与切换入口见 templates/account/_theme.html。

   UTF-8 无 BOM
   ============================================================ */

/* ── 有鱼设计系统 · shadcn 令牌(亮色,默认) ─────────────── */
:root {
  color-scheme: light;
  --radius: 0.625rem;

  --background:            oklch(1 0 0);
  --foreground:            oklch(0.145 0 0);
  --card:                  oklch(1 0 0);
  --card-foreground:       oklch(0.145 0 0);
  --popover:               oklch(1 0 0);
  --popover-foreground:    oklch(0.145 0 0);

  --primary:               oklch(0.205 0 0);
  --primary-foreground:    oklch(0.985 0 0);
  --secondary:             oklch(0.97 0 0);
  --secondary-foreground:  oklch(0.205 0 0);
  --muted:                 oklch(0.97 0 0);
  --muted-foreground:      oklch(0.545 0 0);   /* 偏差①:上游 0.556 对 muted 只有 4.34:1 */
  --accent:                oklch(0.97 0 0);
  --accent-foreground:     oklch(0.205 0 0);

  --success:               oklch(0.52 0.15 150);
  --success-foreground:    oklch(0.985 0 0);
  --warning:               oklch(0.53 0.14 70);
  --warning-foreground:    oklch(0.985 0 0);
  --info:                  oklch(0.52 0.16 255);
  --info-foreground:       oklch(0.985 0 0);
  --destructive:           oklch(0.577 0.245 27.325);
  --destructive-foreground:oklch(0.985 0 0);

  /* 实心按钮的 hover 面。规则:**离自己的字色更远一步**——亮皮变深、暗皮变浅,
     于是两张皮下 hover 都让对比度**上升**,不可能压线。理由见 .btn 那一节。
     实测(字对底 / 底对卡片面):
       primary     18.96 / 19.79      secondary   14.22 / 1.26(见下)
       destructive  6.15 / 6.42 */
  --primary-hover:         oklch(0.145 0 0);
  --secondary-hover:       oklch(0.922 0 0);
  --destructive-hover:     oklch(0.505 0.213 27.518);
  --sidebar-primary-hover: oklch(0.985 0 0);

  --border:                oklch(0.922 0 0);   /* 装饰性发丝线,有意不追 3:1 */
  --input:                 oklch(0.645 0 0);   /* 偏差②:控件边界须 ≥3:1,上游 0.922 只有 1.26 */
  --ring:                  oklch(0.645 0 0);   /* 偏差③:焦点环须 ≥3:1,上游 0.708 只有 2.59 */

  --chart-1: oklch(0.5 0.2 262);
  --chart-2: oklch(0.52 0.13 185);
  --chart-3: oklch(0.55 0.14 75);
  --chart-4: oklch(0.5 0.22 305);
  --chart-5: oklch(0.53 0.2 15);

  --sidebar:                      oklch(0.205 0 0);
  --sidebar-foreground:           oklch(0.985 0 0);
  --sidebar-primary:              oklch(0.922 0 0);
  --sidebar-primary-foreground:   oklch(0.205 0 0);
  --sidebar-accent:               oklch(0.269 0 0);
  --sidebar-accent-foreground:    oklch(0.985 0 0);
  --sidebar-border:               oklch(1 0 0 / 10%);
  --sidebar-ring:                 oklch(0.556 0 0);

  --radius-sm:  calc(var(--radius) * 0.6);
  --radius-md:  calc(var(--radius) * 0.8);
  --radius-lg:  var(--radius);
  --radius-xl:  calc(var(--radius) * 1.4);
  --radius-2xl: calc(var(--radius) * 1.8);
  --radius-full: 9999px;                      /* pill:徽标 / 标签 / 头像 */

  --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / .05);
  --shadow-md: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);
  --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);

  --space-1: 4px;  --space-2: 8px;  --space-3: 12px; --space-4: 16px;
  --space-5: 20px; --space-6: 24px; --space-7: 28px; --space-8: 32px;

  --text-xs: 12px; --text-sm: 14px; --text-base: 16px;
  --text-lg: 18px; --text-xl: 20px; --text-2xl: 24px;

  --dur: 160ms;
  --font-sans: "PingFang SC","Microsoft YaHei","Noto Sans SC","Segoe UI",system-ui,sans-serif;
  --font-mono: ui-monospace,"Cascadia Mono",Consolas,"SF Mono",monospace;
}

/* ── 暗色:覆盖同一批令牌 ─────────────────────────────────── */
.dark {
  color-scheme: dark;

  --background:            oklch(0.145 0 0);
  --foreground:            oklch(0.985 0 0);
  --card:                  oklch(0.205 0 0);
  --card-foreground:       oklch(0.985 0 0);
  --popover:               oklch(0.205 0 0);
  --popover-foreground:    oklch(0.985 0 0);

  --primary:               oklch(0.922 0 0);
  --primary-foreground:    oklch(0.205 0 0);
  --secondary:             oklch(0.269 0 0);
  --secondary-foreground:  oklch(0.985 0 0);
  --muted:                 oklch(0.269 0 0);
  --muted-foreground:      oklch(0.708 0 0);
  --accent:                oklch(0.371 0 0);
  --accent-foreground:     oklch(0.985 0 0);

  --success:               oklch(0.77 0.16 155);
  --success-foreground:    oklch(0.205 0 0);
  --warning:               oklch(0.82 0.15 85);
  --warning-foreground:    oklch(0.205 0 0);
  --info:                  oklch(0.78 0.13 235);
  --info-foreground:       oklch(0.205 0 0);
  --destructive:           oklch(0.704 0.191 22.216);
  --destructive-foreground:oklch(0.205 0 0);

  /* 暗皮同理,方向相反(变亮)。实测:primary 17.16 / 17.16、
     secondary 9.95、destructive 7.70 / 7.70 */
  --primary-hover:         oklch(0.985 0 0);
  --secondary-hover:       oklch(0.371 0 0);
  --destructive-hover:     oklch(0.77 0.16 22.216);

  --border:                oklch(1 0 0 / 10%);
  --input:                 oklch(1 0 0 / 35%);   /* 偏差②暗色侧 */
  --ring:                  oklch(0.556 0 0);

  --chart-1: oklch(0.72 0.2 262);
  --chart-2: oklch(0.75 0.13 185);
  --chart-3: oklch(0.78 0.14 75);
  --chart-4: oklch(0.72 0.22 305);
  --chart-5: oklch(0.7 0.2 15);
}
/* ── 令牌块到此为止;以下只许出现 var(--令牌),不许出现颜色原值 ── */

*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

body {
  font-family: var(--font-sans);
  color: var(--foreground);
  background: var(--background);
  font-size: var(--text-sm);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }

/* 数字列对齐:等宽数字,金额与积分上下对得齐 */
.num, .mono { font-variant-numeric: tabular-nums; }
.mono { font-family: var(--font-mono); font-size: var(--text-xs); }

/* 统一焦点环(SKILL.md §4:一律 --ring,2px + 2px offset) */
a:focus-visible,
button:focus-visible,
input:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* 跳到主内容:侧边栏导航项较多,键盘用户需要 */
.skip-link { position: absolute; left: -9999px; top: 0; }
.skip-link:focus {
  left: 12px; top: 12px; z-index: 200;
  background: var(--popover); color: var(--popover-foreground);
  padding: 10px 18px; border-radius: var(--radius-md);
  border: 1px solid var(--input);
  font-size: var(--text-sm);
}

/* ---------------- 基元:按钮(原借自官网 style.css,现自持) ---------------- */
/* SKILL.md §4 的五个变体。主操作恒为中性实心(--primary 是近黑/近白),
   语义色与图表色不做常规按钮底。 */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 20px;
  border: 1px solid transparent; border-radius: var(--radius-md);
  font-family: inherit; font-size: var(--text-sm); font-weight: 500;
  cursor: pointer; white-space: nowrap;
  transition: background-color var(--dur) ease,
              border-color var(--dur) ease, color var(--dur) ease;
}
/* 🔴 hover 绝不用 opacity —— 这跟 §6.7 对 disabled 的要求是同一条道理,
   而且更隐蔽:opacity 把「面」和「字」一起淡向父面,对比度只会下降。
   实心 danger 本就只有 4.56(AA 线上 0.06 的余量),原先那条
   `.btn:not(:disabled):hover { opacity: .9 }` 一压就是**亮皮 4.34 不过 AA**
   (暗皮 5.22 侥幸过,所以只看暗皮会漏掉)。
   改为逐变体换面色:每个 hover 面都「离自己的字色更远一步」——亮皮变深、
   暗皮变浅,两张皮下 hover 都是对比度上升,结构上不可能再压线。 */
.btn-primary   { background: var(--primary);   color: var(--primary-foreground); }
.btn-primary:not(:disabled):hover   { background: var(--primary-hover); }
.btn-secondary { background: var(--secondary); color: var(--secondary-foreground); }
.btn-secondary:not(:disabled):hover { background: var(--secondary-hover); }
.btn-outline   { background: transparent; color: var(--foreground); border-color: var(--input); }
.btn-outline:not(:disabled):hover {
  background: var(--accent); color: var(--accent-foreground);
}
.btn-danger    { background: var(--destructive); color: var(--destructive-foreground); }
.btn-danger:not(:disabled):hover    { background: var(--destructive-hover); }
.btn-sm { padding: 6px 14px; font-size: var(--text-xs); }
.btn-lg { padding: 14px 32px; font-size: var(--text-base); }
.btn-block { width: 100%; display: flex; }
/* 🔴 不可用状态换颜色不换透明度(SKILL.md §6.7):压 opacity 是给亮底调的,
   暗底上会把文字推到 3:1 以下。改用 muted 面 + muted 字(实测 4.54:1)。 */
.btn[disabled], .btn:disabled {
  background: var(--muted); color: var(--muted-foreground);
  border-color: transparent; cursor: default;
}

/* ---------------- 基元:徽章(原借自官网 style.css,现自持) ---------------- */
/* 语义面 + 对应 -foreground 字;徽章一律带文字,不靠颜色单独表意(§6.6)。 */
.badge {
  display: inline-flex; align-items: center; padding: 3px 10px;
  border-radius: var(--radius-full); font-size: var(--text-xs); font-weight: 600;
  background: var(--muted); color: var(--muted-foreground);
}
.badge-ai    { background: var(--info);    color: var(--info-foreground); }
.badge-green { background: var(--success); color: var(--success-foreground); }

/* ---------------- 外壳:侧边栏 + 内容区 ---------------- */
/* 侧边栏与内容区作为**一个整体**居中。
   别改回「侧边栏 flex 靠左 + .main-inner 自己 margin:0 auto」——那样两者是各自
   独立定位的:侧边栏钉在视口最左,内容在剩余空间里再居中,2000px 宽屏下中间会
   空出三百多像素,看着像两块不相干的东西。 */
.shell {
  display: flex;
  min-height: 100vh; min-height: 100dvh;
  max-width: 1440px;            /* 240 侧边栏 + 1200 内容区 */
  margin: 0 auto;
}

/* 侧边栏走 --sidebar-* 族:两皮恒定深色,作为稳定的空间锚点(SKILL.md §1.7)。
   🔴 这里面不许借用会随皮反转的令牌(--warning/--destructive 之类):侧栏底恒定
      深色,而语义面在暗皮下会变深,深底配深色 = 看不见。要状态色就用 --sidebar-* 族。 */
.sidebar {
  width: 240px; flex: none;
  background: var(--sidebar); color: var(--sidebar-foreground);
  border-right: 1px solid var(--sidebar-border);
  display: flex; flex-direction: column;
  position: sticky; top: 0;
  height: 100vh; height: 100dvh;
  overflow-y: auto;
}

/* 品牌区:与官网导航同一个 logo 与字重,从官网点「登录」进来不断层。
   侧栏恒为深色,所以 logo 用白色版(logo-light.png),由模板按皮选图。 */
.sidebar-brand {
  display: flex; align-items: center; gap: 10px;
  padding: 20px 20px 18px;
}
.sidebar-brand img { height: 26px; width: auto; display: block; object-fit: contain; }
.sidebar-brand-text { display: flex; flex-direction: column; line-height: 1.25; }
.sidebar-brand-name { font-size: var(--text-base); font-weight: 700; }
/* 次级说明文字:侧栏没有更暗的一档字色令牌,用 .7 不透明度拉开层级
   (实测 --sidebar-foreground @70% 压在 --sidebar 上仍有 8.82:1,远高于 4.5)。 */
.sidebar-brand-sub { font-size: var(--text-xs); opacity: .7; }

.sidebar-nav { padding: 4px 12px; display: flex; flex-direction: column; gap: 2px; }

.nav-item {
  position: relative;
  display: flex; align-items: center; gap: 11px;
  min-height: 44px;                       /* 触达区不小于 44px */
  padding: 10px 14px;
  border-radius: var(--radius-md);
  font-size: var(--text-sm); font-weight: 500;
  color: var(--sidebar-foreground);
  transition: background-color var(--dur) ease, color var(--dur) ease;
}
.nav-item svg { flex: none; width: 18px; height: 18px; }
.nav-item:hover,
.nav-item.is-active {
  background: var(--sidebar-accent);
  color: var(--sidebar-accent-foreground);
}
.nav-item.is-active { font-weight: 600; }
/* 当前项指示条:旧版这里是全站唯一的蓝紫渐变,品牌色随新体系整体退场,
   改用侧栏自己的强调色(--sidebar-primary)。 */
.nav-item.is-active::before {
  content: "";
  position: absolute; left: 0; top: 9px; bottom: 9px; width: 3px;
  border-radius: 3px;
  background: var(--sidebar-primary);
}

.sidebar-foot {
  margin-top: auto;
  padding: 16px 20px 20px;
  border-top: 1px solid var(--sidebar-border);
}
.sidebar-phone {
  display: block; font-size: var(--text-sm); font-weight: 500;
  color: var(--sidebar-foreground); margin-bottom: 4px;
}
.sidebar-phone-label { font-size: var(--text-xs); opacity: .7; }
/* 退出登录与导航项在视觉与间距上拉开,避免误点 */
.logout-btn {
  margin-top: 14px;
  display: flex; align-items: center; gap: 8px;
  width: 100%; min-height: 40px; padding: 8px 10px;
  background: none; border: 0; border-radius: var(--radius-md); cursor: pointer;
  font-family: inherit; font-size: var(--text-sm);
  color: var(--sidebar-foreground);
  transition: background-color var(--dur) ease;
}
/* hover 不用 --destructive:它在侧栏恒定深底上只有 3.79:1(暗皮更低),
   不过 AA。侧栏内的强调一律走 --sidebar-accent 对(§1.7)。 */
.logout-btn:hover {
  background: var(--sidebar-accent); color: var(--sidebar-accent-foreground);
}
.logout-btn svg { width: 16px; height: 16px; flex: none; }

/* ---------------- 主题切换(亮 / 暗 / 跟随系统) ---------------- */
/* 三档分段控件。默认按页面令牌配色(登录页用);进了侧栏则整体换成
   --sidebar-* 族,否则亮皮下一块浅色药丸压在深色侧栏上非常突兀。 */
.theme-switch {
  display: flex; gap: 2px; padding: 3px;
  background: var(--muted);
  border: 1px solid var(--input);         /* 控件边界须能被找到 → --input 而非 --border */
  border-radius: var(--radius-md);
}
.theme-btn {
  flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  min-height: 30px; padding: 0 8px;
  background: none; border: 0; cursor: pointer;
  border-radius: var(--radius-sm);
  font-family: inherit; font-size: var(--text-xs);
  color: var(--muted-foreground);
  transition: background-color var(--dur) ease, color var(--dur) ease;
}
.theme-btn svg { width: 15px; height: 15px; flex: none; }
.theme-btn[aria-pressed="true"] {
  background: var(--background); color: var(--foreground);
  box-shadow: var(--shadow-sm);
}
.sidebar-foot .theme-switch {
  margin-top: 14px;
  background: var(--sidebar-accent);
  border-color: var(--sidebar-border);
}
.sidebar-foot .theme-btn { color: var(--sidebar-accent-foreground); }
.sidebar-foot .theme-btn[aria-pressed="true"] {
  background: var(--sidebar-primary); color: var(--sidebar-primary-foreground);
  box-shadow: none;
}

.main { flex: 1; min-width: 0; }
/* 不再自己 margin:0 auto —— 宽度已由 .shell 的 max-width 兜住,
   这里再居中就会把内容从侧边栏旁边推开。 */
.main-inner { padding: 36px 40px 72px; }

/* ---------------- 页头 / 卡片 ---------------- */
.page-head { margin-bottom: 22px; }
.page-head h1 { font-size: var(--text-2xl); font-weight: 700; line-height: 1.3; margin: 0; }
.page-head p {
  margin: 8px 0 0; font-size: var(--text-sm);
  color: var(--muted-foreground);
}

.card {
  background: var(--card); color: var(--card-foreground);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-sm);
  padding: 24px 26px;
}
.card + .card { margin-top: 18px; }
.card-title { font-size: var(--text-base); font-weight: 700; margin: 0 0 16px; }
.card-note {
  margin: 16px 0 0; font-size: var(--text-sm);
  color: var(--muted-foreground);
}

/* ---------------- 总览:积分主视觉 ---------------- */
.bal { display: flex; align-items: center; gap: 28px; flex-wrap: wrap; }
.bal-label {
  font-size: var(--text-sm); color: var(--muted-foreground);
  margin-bottom: 2px;
}
/* 展示型数字尺寸超出 --text-* 阶(阶到 24 为止),这一族保留字面 px */
.bal-num {
  font-size: clamp(40px, 6vw, 56px);
  font-weight: 700; line-height: 1.05; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.bal-meta {
  margin-top: 10px; font-size: var(--text-sm);
  color: var(--muted-foreground);
}
.bal-meta b { font-weight: 600; color: var(--card-foreground); }
/* 旧版这根竖线用 --border-strong 画得比正文淡。新体系里对应的 --input 是**控件
   边界**令牌(3.30:1,非文字门槛),拿它当字形会被文字口径判成不过 AA;而这根线
   本身是行内文本节点。直接跟随同段落的次级字色,层级交给字号与措辞。 */
.bal-meta .sep { color: var(--muted-foreground); margin: 0 8px; }
.bal-actions { margin-left: auto; display: flex; gap: 12px; flex-wrap: wrap; }

/* ---------------- 总览:能力网格(模块 + 单价合一) ---------------- */
.cap-grid {
  display: grid; gap: 14px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.cap-item {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 16px 18px;
  background: var(--card); color: var(--card-foreground);
}
/* 未开通:换颜色不换透明度(§6.7);徽章带文字,不靠颜色单独表意 */
.cap-item.is-off { background: var(--muted); color: var(--muted-foreground); }
.cap-item.is-off .cap-name { color: var(--muted-foreground); }
.cap-item-top {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 10px;
}
.cap-name { font-size: var(--text-base); font-weight: 600; line-height: 1.4; }
.cap-price {
  margin-top: 12px; font-size: var(--text-sm);
  color: var(--muted-foreground);
}
.cap-price b {
  font-size: var(--text-base); font-weight: 700;
  color: var(--card-foreground);
  font-variant-numeric: tabular-nums;
}
.cap-item.is-off .cap-price b { color: var(--muted-foreground); }
/* 「未开通」徽章默认就是 muted 面,而未开通的格子本身也被压成 muted 面
   —— 两皮下都是同色贴同色,徽章会整个消失。格子里换成卡片面托底。 */
.cap-item.is-off .badge { background: var(--card); color: var(--muted-foreground); }

/* ---------------- 总览:设备状态条 ---------------- */
.dev-strip { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.dev-strip-num {
  font-size: var(--text-2xl); font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.dev-strip-text { font-size: var(--text-sm); color: var(--muted-foreground); margin-top: 2px; }
.dev-strip .btn { margin-left: auto; }

/* ---------------- 表格 ---------------- */
.table-wrap { overflow-x: auto; }           /* 窄屏横向滚动,不撑破布局 */
.table-wrap table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.table-wrap th {
  text-align: left; white-space: nowrap;
  font-size: var(--text-xs); font-weight: 600;
  color: var(--muted-foreground);
  padding: 0 12px 10px;
  border-bottom: 1px solid var(--border);
}
.table-wrap td {
  padding: 13px 12px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
.table-wrap tbody tr:last-child td { border-bottom: 0; }
.table-wrap tbody tr:hover { background: var(--accent); color: var(--accent-foreground); }
.table-wrap th:first-child, .table-wrap td:first-child { padding-left: 4px; }
.table-wrap th:last-child,  .table-wrap td:last-child  { padding-right: 4px; text-align: right; }

/* 积分增减:语义色在新体系里是**面**不是字(旧的 --success/--danger 是字色)。
   直接拿面当字色会得到浅绿字压白底,所以做成「面 + 对应 -foreground」的小药丸;
   正负号本身仍在,不靠颜色单独表意(§6.6)。 */
.delta {
  display: inline-block; min-width: 58px; padding: 2px 9px;
  border-radius: var(--radius-full);
  font-weight: 600; font-variant-numeric: tabular-nums;
}
.delta.pos { background: var(--success);     color: var(--success-foreground); }
.delta.neg { background: var(--destructive); color: var(--destructive-foreground); }

.tag-self {
  display: inline-block; margin-left: 8px; padding: 2px 8px;
  border-radius: var(--radius-full);
  font-size: var(--text-xs); font-weight: 600;
  background: var(--secondary);
  color: var(--secondary-foreground);
}

/* ---------------- 按钮补充 ---------------- */
.btn-quiet {
  background: none; border: 0; padding: 0;
  font-family: inherit; font-size: var(--text-sm); font-weight: 500;
  color: var(--muted-foreground); cursor: pointer;
}
.btn-quiet:hover { color: var(--foreground); }

/* ---------------- 表单 ---------------- */
.form-narrow { max-width: 460px; }          /* 表单不拉满宽,保持可读行长 */
.field { margin-bottom: 16px; }
.field > label, .label {
  display: block; font-size: var(--text-sm); font-weight: 500;
  margin-bottom: 6px; color: var(--card-foreground);
}
.input {
  width: 100%; min-height: 44px; padding: 11px 13px;
  font-family: inherit; font-size: var(--text-sm);
  color: var(--foreground);
  background: var(--background);
  border: 1px solid var(--input);           /* 控件边界:--input,不是 --border */
  border-radius: var(--radius-md);
  transition: border-color var(--dur) ease;
}
.input::placeholder { color: var(--muted-foreground); }
.input:focus { border-color: var(--ring); }
.help { margin: 6px 0 0; font-size: var(--text-xs); color: var(--muted-foreground); }
.row { display: flex; gap: 10px; align-items: flex-start; }
.row .input { flex: 1; min-width: 0; }
/* 图形验证码:图片容器 → 下沉面 --muted + --input 承重描边(§4) */
.cap-img {
  height: 44px; width: auto; display: block;
  background: var(--muted);
  border: 1px solid var(--input);
  border-radius: var(--radius-md);
  cursor: pointer; flex: none;
}
.sms-btn {
  white-space: nowrap; flex: none;
  min-height: 44px; padding: 0 16px;
  font-family: inherit; font-size: var(--text-sm); font-weight: 500;
  color: var(--foreground);
  background: transparent;
  border: 1px solid var(--input);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background-color var(--dur) ease, color var(--dur) ease;
}
.sms-btn:hover:not(:disabled) { background: var(--accent); color: var(--accent-foreground); }
.sms-btn:disabled { background: var(--muted); color: var(--muted-foreground); cursor: default; }

/* form-block = 卡片内的一段表单(标题 + 字段);form-section 额外加一条分隔线。
   标题样式挂在 form-block 上而非 form-section,否则卡片里**第一段**表单
   (不需要分隔线、因而没有 form-section)的 h2 会掉回浏览器默认样式。 */
.form-block h2 { font-size: var(--text-base); font-weight: 700; margin: 0 0 16px; }
.form-block .form-intro { margin: -8px 0 18px; }
.form-section { border-top: 1px solid var(--border); padding-top: 22px; margin-top: 22px; }
/* 必须排在 .help 之后:两者同为 (0,1,0) 特指度,靠书写顺序取胜 */
.pwd-err {
  display: inline-block; margin-top: 8px; padding: 4px 10px;
  border-radius: var(--radius-sm);
  background: var(--destructive); color: var(--destructive-foreground);
  font-weight: 500;
}

/* ---------------- 空态 / 分页 / flash ---------------- */
.empty { text-align: center; padding: 44px 20px; }
.empty-title { font-size: var(--text-base); font-weight: 600; margin-bottom: 6px; }
.empty p { margin: 0; font-size: var(--text-sm); color: var(--muted-foreground); }

.pager { display: flex; align-items: center; gap: 14px; margin-top: 18px; }
.pager-info { font-size: var(--text-sm); color: var(--muted-foreground); margin-right: auto; }

/* 语义面 + 对应字色。旧体系是「浅底 + 深色语义字 + 更浅的边」三件套,
   新体系一对令牌就够,边框与底同色反而多余,直接去掉。 */
.flash {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 16px; margin-bottom: 18px;
  border-radius: var(--radius-lg);
  font-size: var(--text-sm);
  background: var(--success); color: var(--success-foreground);
}
.alert-err {
  padding: 12px 16px; margin-bottom: 18px;
  border-radius: var(--radius-lg);
  font-size: var(--text-sm);
  background: var(--destructive); color: var(--destructive-foreground);
}

/* ---------------- 登录页(未登录,无侧边栏) ---------------- */
.auth-wrap {
  min-height: 100vh; min-height: 100dvh;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 40px 20px;
}
.auth-brand {
  display: flex; align-items: center; gap: 10px;
  font-size: var(--text-base); font-weight: 700; margin-bottom: 24px;
}
.auth-brand img { height: 28px; width: auto; display: block; }
/* logo 一律用真实资产,两版同形同尺寸(纯黑 / 纯白),按皮显隐 —— 页面底会随皮
   翻转,而 logo 是不透明位图,单放一版必然在另一张皮下糊掉。侧栏那份不需要这套:
   侧栏两皮恒定深色,恒用白版即可。
   🔴 选择器必须写成 img.xxx:上面那条 `.auth-brand img` 是 (0,1,1),裸类名
      `.brand-logo-dark` 只有 (0,1,0),特指度低就赢不了 —— 写在后面也没用,
      结果是亮色皮下**两版 logo 同时显示**。实测踩过。 */
img.brand-logo-dark { display: none; }
.dark img.brand-logo-light { display: none; }
.dark img.brand-logo-dark { display: block; }
.auth-card {
  width: 100%; max-width: 400px;
  background: var(--card); color: var(--card-foreground);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  padding: 28px;
}
.auth-tabs {
  display: flex; gap: 4px; margin-bottom: 22px;
  background: var(--muted);
  border-radius: var(--radius-md);
  padding: 4px;
}
.auth-card h1 { font-size: var(--text-xl); font-weight: 700; margin: 0 0 6px; }
.auth-sub {
  margin: 0 0 20px; font-size: var(--text-sm);
  color: var(--muted-foreground);
}
.auth-tab {
  flex: 1; min-height: 38px; border: 0; cursor: pointer;
  background: none; border-radius: var(--radius-sm);
  font-family: inherit; font-size: var(--text-sm); font-weight: 500;
  color: var(--muted-foreground);
}
/* 选中态类名是 .on 而非 .is-active:login.html 的 showPanel() 用
   classList.toggle("on", ...) 同时切 Tab 与面板,两边必须对齐。 */
.auth-tab.on {
  background: var(--background);
  color: var(--foreground);
  font-weight: 600;
  box-shadow: var(--shadow-sm);
}
.panel { display: none; }
.panel.on { display: block; }

.remember {
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 16px;
  font-size: var(--text-sm); color: var(--muted-foreground);
  cursor: pointer;
}
.remember input { width: 16px; height: 16px; accent-color: var(--primary); }
.auth-aux { margin: 14px 0 0; text-align: center; }

.auth-foot {
  display: flex; flex-direction: column; align-items: center; gap: 16px;
  margin-top: 22px;
}
.auth-foot .theme-switch { width: 220px; }
.auth-back { font-size: var(--text-sm); color: var(--muted-foreground); }
.auth-back:hover { color: var(--foreground); }

/* ---------------- 商城:积分包卡片 ---------------- */
/* 用卡片而不是表格:表格是拿来横向扫描比较数据的,而「买哪个包」是一次选择。 */
.pack-grid {
  display: grid; gap: 16px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.pack-card {
  display: flex; flex-direction: column;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 20px 22px;
  background: var(--card); color: var(--card-foreground);
}
.pack-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.pack-name { font-size: var(--text-sm); font-weight: 600; color: var(--muted-foreground); }
.pack-points {
  margin-top: 8px;
  font-size: 34px; font-weight: 700; line-height: 1.1;   /* 展示型数字,超出 --text-* 阶 */
  font-variant-numeric: tabular-nums;
}
.pack-points i { font-style: normal; font-size: var(--text-sm); font-weight: 500;
                 color: var(--muted-foreground); margin-left: 5px; }
.pack-price {
  margin-top: 14px;
  font-size: var(--text-xl); font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.pack-price s {
  margin-left: 8px; font-size: var(--text-sm); font-weight: 400;
  color: var(--muted-foreground);
}
/* 每积分单价:原先没有,买家得自己拿计算器比哪个包划算 */
.pack-unit { margin-top: 6px; font-size: var(--text-xs); color: var(--muted-foreground); }
.pack-buy { margin-top: auto; padding-top: 18px; }
.pack-buy .btn { width: 100%; }

/* ---------------- 收银台 ---------------- */
.order-summary { display: flex; align-items: center; gap: 28px; flex-wrap: wrap; }
.order-amount {
  font-size: 40px; font-weight: 700; line-height: 1.05;   /* 展示型数字 */
  font-variant-numeric: tabular-nums;
}
.order-amount-label { font-size: var(--text-sm); color: var(--muted-foreground); margin-bottom: 2px; }
.order-meta { margin-left: auto; text-align: right; font-size: var(--text-sm);
              color: var(--muted-foreground); line-height: 1.9; }

.pay-box { display: flex; flex-direction: column; align-items: center; text-align: center; }
/* 二维码 / 内嵌收银台都是「图片容器」:下沉面 --muted + --input 承重描边(§4)。
   🔴 这里绝不能用 --border:亮皮下白底二维码与卡片面几乎同色,1.26:1 等于没描边。 */
.pay-qr, .pay-frame {
  border: 1px solid var(--input);
  border-radius: var(--radius-lg);
  background: var(--muted);
  padding: 12px; line-height: 0;
}
.pay-frame { padding: 0; overflow: hidden; }
.pay-hint { margin: 16px 0 0; font-size: var(--text-sm); color: var(--muted-foreground); }

/* 等待支付:原先页面在后台每 3 秒轮询却毫无反馈,用户不知道它会自动跳转。
   呼吸点原是品牌蓝,品牌色随新体系退场 → 强调图形改用 --primary。 */
.pay-waiting {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 16px; font-size: var(--text-sm); color: var(--muted-foreground);
}
.pay-waiting::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%;
  background: var(--primary);
  animation: pay-pulse 1.4s ease-in-out infinite;
}
@keyframes pay-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
@media (prefers-reduced-motion: reduce) {
  .pay-waiting::before { animation: none; }
}

/* 渠道选择:做成可点的卡片,而不是并排两个裸表单按钮。
   🔴 平台不用品牌色:微信绿 / 支付宝蓝都不进 UI,只有文字 + 中性描边。 */
.chan-grid {
  display: grid; gap: 12px; grid-template-columns: repeat(2, minmax(0, 1fr));
  max-width: 420px; margin: 0 auto;
}
.chan-grid form { display: block; }
.chan-card {
  width: 100%; min-height: 64px;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 16px; cursor: pointer;
  font-family: inherit; font-size: var(--text-base); font-weight: 600;
  color: var(--foreground);
  background: transparent;
  border: 1px solid var(--input);
  border-radius: var(--radius-lg);
  transition: border-color var(--dur) ease, background-color var(--dur) ease,
              color var(--dur) ease;
}
.chan-card:hover {
  border-color: var(--ring);
  background: var(--accent); color: var(--accent-foreground);
}

.pay-switch {
  display: flex; align-items: center; justify-content: center;
  gap: 12px; flex-wrap: wrap;
  margin-top: 22px; padding-top: 18px;
  border-top: 1px solid var(--border);
  font-size: var(--text-sm); color: var(--muted-foreground);
}
.pay-switch form { display: inline-block; }

.pay-ok { text-align: center; padding: 12px 0; }
.pay-ok-icon {
  width: 56px; height: 56px; margin: 0 auto 16px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--success); color: var(--success-foreground);
}
.pay-ok-icon svg { width: 28px; height: 28px; }
.pay-ok-title { font-size: var(--text-lg); font-weight: 700; }
.pay-ok-points {
  margin: 12px 0 2px;
  font-size: 36px; font-weight: 700; line-height: 1.1;    /* 展示型数字 */
  font-variant-numeric: tabular-nums;
}
.pay-actions { display: flex; gap: 12px; justify-content: center;
               flex-wrap: wrap; margin-top: 24px; }

/* 替代内联 style="display:none"(模板里不写内联样式) */
.is-hidden { display: none !important; }

/* ---------------- 响应式 ---------------- */
@media (max-width: 1180px) {
  .cap-grid, .pack-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 900px) {
  /* 侧边栏收为顶部横向导航条 */
  .shell { flex-direction: column; }
  .sidebar {
    width: 100%; height: auto; position: static;
    border-right: 0; border-bottom: 1px solid var(--sidebar-border);
  }
  .sidebar-brand { padding: 14px 20px 12px; }
  .sidebar-nav {
    flex-direction: row; gap: 4px;
    overflow-x: auto; padding: 0 12px 8px;
    -webkit-overflow-scrolling: touch;
  }
  /* 触达区仍保持 44px:横排后每项更窄,手指更容易点偏,不能在这里放松 */
  .nav-item { white-space: nowrap; padding: 8px 12px; min-height: 44px; }
  .nav-item.is-active::before { top: auto; bottom: 0; left: 12px; right: 12px; width: auto; height: 2px; }
  .sidebar-foot {
    margin-top: 0; display: flex; align-items: center; gap: 16px;
    padding: 12px 20px;
  }
  .logout-btn { margin-top: 0; width: auto; margin-left: auto; }
  .sidebar-foot .theme-switch { margin-top: 0; flex: none; width: 150px; }
}
@media (max-width: 760px) {
  .cap-grid, .pack-grid, .chan-grid { grid-template-columns: minmax(0, 1fr); }
  .bal-actions { margin-left: 0; width: 100%; }
  .bal-actions .btn { flex: 1; }
  .dev-strip .btn { margin-left: 0; width: 100%; }
  .page-head h1 { font-size: var(--text-xl); }
  /* 金额与订单信息在窄屏改为上下堆叠,别把 meta 推到右边挤成一条 */
  .order-meta { margin-left: 0; text-align: left; }
  .order-summary { gap: 16px; }
  .pay-actions .btn { width: 100%; }
}
