/* ==========================================================================
   pages.css —— 商业化新页面的样式（landing / billing / usage / api-keys /
   security）。

   ==========================================================================
   为什么是一个新文件，而不是往 styles.css 里加
   ==========================================================================
   `styles.css` 是 11 万行量级的产品页样式，且本轮由另一个 agent 持有。两个人
   同时往一个文件尾部追加，冲突是必然的，而 CSS 冲突的表现是「界面看起来还行，
   但某一处莫名其妙」——比合并冲突难查得多。

   这里**一个颜色常量都没有**：全部走 styles.css 已经定义好的 CSS 变量
   （`--bg-primary` / `--bg-card` / `--border-card` / `--brand-500` …）。
   于是主题切换（`data-theme`）在这些页面上照样生效，而配色只有一处真源。
   本文件如果自己定义颜色，浅色主题下就会出现一块永远是深色的卡片。

   ==========================================================================
   这里也没有一个价格数字
   ==========================================================================
   金额、额度、速率上限全部来自 `GET /api/v1/plans`。CSS 里出现一个 `content:
   "$20"` 会绕过所有「前端不许硬编码价格」的检查——所以下面连 `content` 里的
   数字都没有。

   零依赖：不 @import 任何远端资源。字体由页面 <head> 引，且带系统兜底栈。
   ========================================================================== */

/* --------------------------------------------------------------------------
   共用外壳
   -------------------------------------------------------------------------- */
.pg-wrap { width: 100%; max-width: 64rem; margin: 0 auto; }
.pg-wrap-narrow { max-width: 44rem; }
.pg-wrap-wide { max-width: 76rem; }

.pg-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.pg-head h1 { font-size: clamp(1.2rem, 1.05rem + .75vw, 1.6rem); font-weight: 600; color: var(--text-heading); letter-spacing: -0.01em; }
.pg-head .pg-sub { font-size: .82rem; color: var(--text-muted); line-height: 1.6; margin-top: .35rem; }

/* 账户区各页之间的横向导航。account.html 是概览，这几页是详情。 */
.pg-subnav {
  display: flex; flex-wrap: wrap; gap: .35rem;
  margin: 1.1rem 0 1.4rem;
  border-bottom: 1px solid var(--border-primary);
  padding-bottom: .55rem;
}
.pg-subnav a {
  font-size: .8rem; text-decoration: none; color: var(--text-secondary);
  padding: .32rem .7rem; border-radius: 8px; border: 1px solid transparent;
}
.pg-subnav a:hover { background: var(--bg-input-hover); color: var(--text-heading); }
.pg-subnav a[aria-current="page"] {
  color: var(--text-heading); background: var(--bg-input);
  border-color: var(--border-primary);
}
.pg-subnav a:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 2px; }

/* --------------------------------------------------------------------------
   卡片 / 栅格
   -------------------------------------------------------------------------- */
.pg-grid { display: grid; gap: 1rem; grid-template-columns: 1fr; }
@media (min-width: 860px) { .pg-grid-2 { grid-template-columns: 1fr 1fr; } }
@media (min-width: 720px) { .pg-grid-3 { grid-template-columns: repeat(3, 1fr); } }
.pg-span { grid-column: 1 / -1; }

/* --------------------------------------------------------------------------
   宽内容的兜底：溢出只准发生在容器内部，不准发生在整页
   --------------------------------------------------------------------------
   `1fr` 的完整写法是 `minmax(auto, 1fr)` —— 最小尺寸是 **auto**，不是 0。
   于是一个不肯换行的宽子元素（一行 curl 命令、一个 48 字符的 API key、一张
   宽表）会把所在的列**顶开**，而列顶开的后果不是这个卡片自己滚，是**整页**
   横向滚动：页头、表单、按钮一起被推出屏幕，用户以为页面坏了。

   实测（真实 Chrome，注入一行 curl 命令到 security.html 的 .pg-card）：
     768px 整页横向溢出 +366px，1024px +110px；
   注入 account.html 的 .acct-card：768px +1000px，一直到 2560px 仍 +92px。

   两道防线，缺一不可：
     1) min-width:0 —— 让栅格/弹性项可以收缩到比内容更窄；
     2) 宽内容自己 overflow-x:auto —— 收缩之后总得有人来滚。
   只做 (1) 会裁掉内容，只做 (2) 在 auto 最小尺寸下根本不会触发。
   -------------------------------------------------------------------------- */
/* 作用域挂在 .pg-wrap 上 —— 它是 landing / pricing / billing / usage /
   api-keys / security / account 共用的那一层外壳。按卡片类名一个个列会漏：
   landing.html 用的是 .pg-hero / .pg-features / .pg-step，一个都不叫 card。 */
.pg-wrap, .pg-wrap > *, .pg-wrap section, .pg-wrap article,
.pg-grid > *, .pg-features > *, .pg-head > *, .pg-qr-wrap > *,
.pg-card, .pg-section, .pg-hero, .pg-step { min-width: 0; }

/* 代码块 / 命令行：自己横向滚 */
.pg-wrap :where(pre, .pg-code) { max-width: 100%; overflow-x: auto; }
/* 表格：没被放进 .pg-table-scroll 的也不许把页面推出去
   （.pg-table 自带 min-width:34rem，那个 min-width 只有在滚动容器里才成立，
     所以「每一处 .pg-table 都必须被 .pg-table-scroll 包住」由守门测试来钉。） */
.pg-wrap :where(table) { max-width: 100%; }
/* 长 token / 长 URL / 长哈希：这些没有可断行处，必须允许任意位置断。
   挂在外壳上靠**继承**覆盖全部后代，而不是列一串元素名：实测漏掉的正是一个
   装着 48 字符 API key 的**裸 <div>** —— 它不是 code、不是 a、不是 p，任何
   白名单都会漏掉它，而它一个人就能把整页推出 200px。
   用 anywhere 而不是 break-word：只有 anywhere 会缩小 min-content 尺寸，
   而 min-content 尺寸正是"这个盒子最窄能到多少"的那个数；break-word 让文字
   换行了，盒子该多宽还是多宽，照样把页面顶出去。 */
.pg-wrap { overflow-wrap: anywhere; }
/* 但滚动容器**里面**要恢复正常断行。容器自己会横向滚，里面的单元格不需要
   把单词劈开 —— 劈开的结果是表头变成「RAN/K」「MODE/L」，比溢出还难看。
   overflow-wrap 会继承，所以在容器上写一次 normal 就覆盖了整棵子树。 */
.pg-table-scroll { overflow-wrap: normal; }

.pg-card {
  background: var(--bg-card);
  border: 1px solid var(--border-card);
  border-radius: 14px;
  /* 内边距随视口连续变化，而不是在 560px 上突然跳一档：断点式的间距在
     561px 和 559px 上看起来是两个不同的产品，而两者之间只差 2px。 */
  padding: clamp(1rem, .85rem + .6vw, 1.35rem);
  box-shadow: var(--shadow-card);
}
.pg-card > h2 {
  font-size: .95rem; font-weight: 600; color: var(--text-heading);
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
}
.pg-card > h3 { font-size: .85rem; font-weight: 600; color: var(--text-heading); }

.pg-figure {
  font-size: 2rem; font-weight: 600; color: var(--text-heading);
  font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
  margin-top: .5rem; line-height: 1.15;
}
.pg-figure-small { font-size: 1.15rem; }
.pg-hint { margin-top: .7rem; font-size: .73rem; color: var(--text-muted); line-height: 1.65; }
.pg-hint code { font-size: .72rem; }

.pg-kv { margin-top: .9rem; display: flex; flex-direction: column; gap: .5rem; font-size: .82rem; }
.pg-kv > div { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.pg-kv .k { color: var(--text-muted); }
.pg-kv .v { color: var(--text-heading); font-variant-numeric: tabular-nums; text-align: right; }

/* 状态徽标。语义色借用 auth-msg 已有的那三档，不新造一套。 */
.pg-badge {
  display: inline-flex; align-items: center; gap: .3rem;
  font-size: .68rem; font-weight: 600; letter-spacing: .02em;
  padding: .12rem .45rem; border-radius: 999px;
  border: 1px solid var(--border-primary); color: var(--text-muted);
}
.pg-badge.is-ok { border-color: rgba(34,197,94,.45); color: #86EFAC; }
.pg-badge.is-warn { border-color: rgba(234,179,8,.45); color: #FDE68A; }
.pg-badge.is-off { border-color: var(--border-primary); color: var(--text-muted); }
[data-theme="light"] .pg-badge.is-ok { color: #15803D; }
[data-theme="light"] .pg-badge.is-warn { color: #A16207; }

/* --------------------------------------------------------------------------
   骨架屏
   --------------------------------------------------------------------------
   刻意不是「转圈」：转圈只说明「在等」，骨架屏还顺带说明「等来的东西长什么样」，
   于是布局不会在数据到达的一瞬间跳一下。
   -------------------------------------------------------------------------- */
.pg-skel {
  border-radius: 6px;
  background: linear-gradient(90deg,
    var(--bg-input) 0%, var(--bg-input-hover) 50%, var(--bg-input) 100%);
  background-size: 200% 100%;
  animation: pgShimmer 1.4s ease-in-out infinite;
}
.pg-skel-line { height: .85rem; margin-top: .55rem; }
.pg-skel-figure { height: 2rem; width: 8rem; margin-top: .5rem; }
.pg-skel-row { height: 1.6rem; margin-top: .5rem; }
@keyframes pgShimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .pg-skel { animation: none; }
}

/* --------------------------------------------------------------------------
   表格
   -------------------------------------------------------------------------- */
.pg-table-scroll { width: 100%; overflow-x: auto; margin-top: .9rem; }
.pg-table { width: 100%; border-collapse: collapse; font-size: .78rem; min-width: 34rem; }
.pg-table caption { text-align: left; font-size: .73rem; color: var(--text-muted); padding-bottom: .5rem; }
.pg-table th {
  text-align: left; font-weight: 600; color: var(--text-muted);
  padding: .45rem .55rem; border-bottom: 1px solid var(--border-primary);
  white-space: nowrap;
}
.pg-table td {
  padding: .5rem .55rem; border-bottom: 1px solid var(--border-primary);
  color: var(--text-secondary); vertical-align: top;
}
.pg-table td.num { text-align: right; font-variant-numeric: tabular-nums; color: var(--text-heading); }
.pg-table td.mono, .pg-mono {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: .72rem; word-break: break-all;
}
.pg-table tr:last-child td { border-bottom: none; }

.pg-pager {
  margin-top: .9rem; display: flex; align-items: center; gap: .6rem;
  flex-wrap: wrap; font-size: .76rem; color: var(--text-muted);
}
.pg-pager .btn-ghost { padding: .25rem .65rem; font-size: .76rem; }

/* 空状态 / 错误状态 —— 两者长得不一样，因为它们是两件事 */
.pg-empty {
  margin-top: .9rem; padding: 1.4rem 1rem; text-align: center;
  border: 1px dashed var(--border-primary); border-radius: 12px;
  color: var(--text-muted); font-size: .8rem; line-height: 1.7;
}
.pg-empty .pg-empty-title { color: var(--text-heading); font-weight: 600; font-size: .85rem; }
.pg-empty a { color: var(--text-link); }

.pg-reqid {
  margin-top: .5rem; font-size: .7rem; color: var(--text-muted);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  word-break: break-all;
}

/* --------------------------------------------------------------------------
   表单
   -------------------------------------------------------------------------- */
.pg-form { display: flex; flex-direction: column; gap: .9rem; margin-top: 1rem; }
.pg-row { display: flex; gap: .6rem; flex-wrap: wrap; align-items: center; }
.pg-actions { display: flex; gap: .6rem; flex-wrap: wrap; margin-top: .3rem; }

.pg-chipset { display: flex; flex-wrap: wrap; gap: .45rem; margin-top: .6rem; }
.pg-chip {
  font-size: .8rem; padding: .38rem .8rem; border-radius: 999px;
  border: 1px solid var(--border-primary); background: var(--bg-input);
  color: var(--text-secondary); cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.pg-chip:hover { border-color: var(--brand-500); color: var(--text-heading); }
.pg-chip[aria-pressed="true"] {
  border-color: var(--brand-500); color: var(--text-heading);
  background: var(--bg-input-focus);
}
.pg-chip:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 2px; }
/* 单选态的 chip（支付方式 / 充值面额）。用 aria-checked 而不是一个 class：
   状态只有一处真源，读屏器读到的和眼睛看到的不会分叉。 */
.pg-chip[aria-checked="true"] {
  border-color: var(--brand-500); color: var(--text-heading);
  background: var(--bg-input-focus);
}
/* 面额 chip 有两行：上面是要付的钱，下面是到账额度。两个数都来自服务端。 */
.pg-chip-sku { display: inline-flex; flex-direction: column; align-items: flex-start;
  gap: .1rem; padding: .45rem .9rem; border-radius: .6rem; text-align: left; }
.pg-chip-main { font-size: .86rem; color: var(--text-heading); font-weight: 600; }
.pg-chip-sub { font-size: .7rem; color: var(--text-secondary); }

/* 档位变更面（订阅卡）。一行 = 一个订阅档：左边名字 + 价格 + 变更语义，
   右边一个 CTA。行由 billing.js::planChangeRows 算出来，价格全部来自
   /api/v1/plans —— 这份样式表里没有任何金额。 */
.pg-tier-heading { font-weight: 600; color: var(--text-heading); margin-top: .9rem; }
.pg-tiers { display: flex; flex-direction: column; margin-top: .35rem; }
.pg-tier-row { display: flex; align-items: center; justify-content: space-between;
  gap: .9rem; flex-wrap: wrap; padding: .55rem 0;
  border-top: 1px solid var(--border-primary); }
.pg-tier-row:first-child { border-top: 0; }
.pg-tier-info { min-width: 0; }
.pg-tier-name { font-size: .88rem; font-weight: 600; color: var(--text-heading); }
.pg-tier-price { font-size: .78rem; color: var(--text-secondary); margin-top: .15rem; }
.pg-tier-effect { font-size: .7rem; color: var(--text-muted); margin-top: .2rem;
  max-width: 26rem; }
.pg-tier-action { flex: 0 0 auto; text-align: right; }
.pg-tier-action .btn-ghost, .pg-tier-action .btn-primary { white-space: nowrap; }

/* 扫码支付。二维码本身**固定黑白**（在 billing.html 里写死），因为扫码器认的
   是对比度，不是主题；这里只管排版。 */
.pg-qr-wrap { display: flex; flex-wrap: wrap; gap: 1.1rem; align-items: flex-start;
  margin-top: .8rem; }
.pg-qr { flex: 0 0 auto; line-height: 0; border-radius: .5rem; overflow: hidden;
  border: 1px solid var(--border-primary); }
.pg-qr svg { display: block; }
.pg-qr-hint { font-size: .9rem; font-weight: 600; color: var(--text-heading); }

/* 字段级错误：必须和字段绑在一起（aria-describedby），不是页面顶部一条泛泛的红字 */
.pg-field-error { font-size: .74rem; color: #F87171; margin-top: .3rem; }
[data-theme="light"] .pg-field-error { color: #B91C1C; }
.input[aria-invalid="true"] { border-color: rgba(239,68,68,.55); }

/* 密码显隐 */
.pg-pw { position: relative; display: block; }
.pg-pw .input { padding-right: 4.2rem; width: 100%; }
/* 密码显隐键在手指上只有 22px 高 —— 放大到 44 见 styles.css 里的
   `@media (pointer: coarse)` 段；这里保持视觉尺寸不变。 */
.pg-pw-toggle {
  position: absolute; right: .35rem; top: 50%; transform: translateY(-50%);
  font-size: .7rem; padding: .22rem .5rem; border-radius: 6px;
  border: 1px solid var(--border-primary); background: var(--bg-input);
  color: var(--text-secondary); cursor: pointer;
}
.pg-pw-toggle:hover { color: var(--text-heading); }
.pg-pw-toggle:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 1px; }

button:disabled, .btn-primary:disabled, .btn-ghost:disabled { cursor: not-allowed; opacity: .55; }

/* --------------------------------------------------------------------------
   「暂不可用」区块
   --------------------------------------------------------------------------
   后端没有对应端点的功能长这样：说明白它不存在，而不是画一个点了没反应的按钮，
   更不是在前端拼一个第三方 URL 假装它通。
   -------------------------------------------------------------------------- */
.pg-unavailable {
  margin-top: .9rem; padding: .8rem .9rem;
  border: 1px dashed var(--border-primary); border-radius: 10px;
  background: var(--bg-input); color: var(--text-muted);
  font-size: .78rem; line-height: 1.65;
}
.pg-unavailable strong { color: var(--text-secondary); display: block; margin-bottom: .25rem; }

/* --------------------------------------------------------------------------
   到账确认（充值回跳）
   -------------------------------------------------------------------------- */
.pg-confirm { display: flex; align-items: flex-start; gap: .7rem; }
.pg-spinner {
  width: 1rem; height: 1rem; margin-top: .15rem; flex: none;
  border: 2px solid var(--border-primary); border-top-color: var(--brand-500);
  border-radius: 50%; animation: pgSpin .9s linear infinite;
}
@keyframes pgSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .pg-spinner { animation-duration: 3s; } }

/* --------------------------------------------------------------------------
   一次性秘密（API key 原文）
   -------------------------------------------------------------------------- */
.pg-modal-veil {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(0,0,0,.55);
  display: flex; align-items: center; justify-content: center;
  padding: 1.25rem;
}
.pg-modal-veil[hidden] { display: none; }
.pg-modal {
  width: 100%; max-width: 34rem;
  background: var(--bg-card); border: 1px solid var(--border-card);
  border-radius: 14px; padding: 1.4rem; box-shadow: var(--shadow-card);
  max-height: 90vh; overflow-y: auto;
}
.pg-modal h2 { font-size: 1rem; font-weight: 600; color: var(--text-heading); }
.pg-secret-warn {
  margin-top: .8rem; padding: .7rem .8rem; border-radius: 10px;
  border: 1px solid rgba(234,179,8,.45); background: rgba(234,179,8,.08);
  color: #FDE68A; font-size: .78rem; line-height: 1.65; font-weight: 600;
}
[data-theme="light"] .pg-secret-warn { color: #A16207; }
.pg-secret-value {
  margin-top: .8rem; padding: .7rem .8rem; border-radius: 10px;
  border: 1px solid var(--border-primary); background: var(--bg-input);
  color: var(--text-heading); word-break: break-all;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .8rem; line-height: 1.6;
}

/* --------------------------------------------------------------------------
   用量图表 —— 原生 CSS 柱状，不引任何图表库
   --------------------------------------------------------------------------
   高度由 JS 写 inline style（唯一的数据入口），其余全在这里。柱子上必须有可读的
   文本（`title` + 屏读器专用行），否则它对读屏用户等于不存在。
   -------------------------------------------------------------------------- */
.pg-chart {
  margin-top: 1rem; display: flex; align-items: flex-end; gap: .3rem;
  height: 8rem; padding: .5rem .2rem 0;
  border-bottom: 1px solid var(--border-primary);
  overflow-x: auto;
}
.pg-bar { flex: 1 1 0; min-width: .6rem; display: flex; flex-direction: column; justify-content: flex-end; height: 100%; }
.pg-bar-fill {
  background: var(--brand-500); border-radius: 4px 4px 0 0; min-height: 2px;
  transition: height .18s ease;
}
.pg-bar:hover .pg-bar-fill { background: var(--brand-600); }
.pg-chart-axis {
  display: flex; justify-content: space-between; gap: .5rem;
  font-size: .68rem; color: var(--text-muted); margin-top: .35rem;
}
.pg-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --------------------------------------------------------------------------
   落地页
   -------------------------------------------------------------------------- */
.pg-hero { padding: 3.5rem 0 2.5rem; text-align: left; }
.pg-hero h1 {
  font-size: clamp(1.75rem, 4.5vw, 2.6rem); font-weight: 600;
  color: var(--text-heading); letter-spacing: -0.025em; line-height: 1.2;
  max-width: 22ch;
}
.pg-hero p {
  margin-top: 1rem; font-size: clamp(.9rem, 2vw, 1rem); color: var(--text-secondary);
  line-height: 1.75; max-width: 46rem;
}
.pg-hero-actions { margin-top: 1.75rem; display: flex; gap: .7rem; flex-wrap: wrap; }
.pg-hero-actions .btn-primary, .pg-hero-actions .btn-ghost {
  text-decoration: none; padding: .6rem 1.3rem; font-size: .88rem;
}
.pg-hero-note { margin-top: 1rem; font-size: .75rem; color: var(--text-muted); line-height: 1.7; }

.pg-section { padding: 2.5rem 0; border-top: 1px solid var(--border-primary); }
.pg-section > h2 {
  font-size: 1.15rem; font-weight: 600; color: var(--text-heading);
  letter-spacing: -0.01em;
}
.pg-section > p.pg-sub { margin-top: .5rem; font-size: .84rem; color: var(--text-muted); line-height: 1.7; max-width: 46rem; }

.pg-features { margin-top: 1.6rem; display: grid; gap: 1rem; grid-template-columns: 1fr; }
@media (min-width: 700px) { .pg-features { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1040px) { .pg-features { grid-template-columns: repeat(3, 1fr); } }
.pg-feature {
  background: var(--bg-card); border: 1px solid var(--border-card);
  border-radius: 14px; padding: 1.2rem;
}
.pg-feature .pg-step {
  font-size: .68rem; font-weight: 600; letter-spacing: .08em;
  color: var(--brand-500);
}
.pg-feature h3 { margin-top: .5rem; font-size: .92rem; font-weight: 600; color: var(--text-heading); }
.pg-feature p { margin-top: .5rem; font-size: .8rem; color: var(--text-secondary); line-height: 1.75; }
.pg-feature ul { margin-top: .6rem; padding-left: 1rem; }
.pg-feature li { font-size: .76rem; color: var(--text-muted); line-height: 1.75; }

.pg-footer {
  border-top: 1px solid var(--border-primary);
  padding: 2rem 1.25rem 3rem; margin-top: 1rem;
  font-size: .78rem; color: var(--text-muted);
}
.pg-footer-inner {
  max-width: 76rem; margin: 0 auto;
  display: flex; gap: 1.2rem; flex-wrap: wrap; justify-content: space-between;
}
.pg-footer nav { display: flex; gap: 1rem; flex-wrap: wrap; }
.pg-footer a { color: var(--text-secondary); text-decoration: none; }
.pg-footer a:hover { color: var(--text-link); text-decoration: underline; }
.pg-footer-note { max-width: 40rem; line-height: 1.7; }

/* --------------------------------------------------------------------------
   小屏
   --------------------------------------------------------------------------
   登录 / 账户 / 充值 / 套餐在手机上必须可用 —— 表格横向滚动（见 .pg-table-scroll），
   卡片单列，按钮撑满一行。
   -------------------------------------------------------------------------- */
@media (max-width: 560px) {
  .pg-card { padding: 1rem; border-radius: 12px; }
  .pg-figure { font-size: 1.7rem; }
  .pg-hero { padding: 2.25rem 0 1.75rem; }
  .pg-hero-actions .btn-primary, .pg-hero-actions .btn-ghost {
    width: 100%; justify-content: center;
  }
  .pg-kv > div { flex-direction: column; gap: .1rem; align-items: flex-start; }
  .pg-kv .v { text-align: left; }
  .pg-subnav { gap: .25rem; }
  .pg-subnav a { padding: .3rem .55rem; font-size: .75rem; }
}
