/* ============================================================
   AIP Chat - 玻璃拟态 UI 样式表
   高级毛玻璃（backdrop-filter）+ 高斯模糊光斑 + 非线性 spring 动画
   适配桌面端与移动端，支持深/浅主题
   ============================================================ */

/* ============ 全局变量（黑白单色 · DeepMind 风格） ============ */
:root {
  --bg-body: #f5f6f7;
  --bg-body-rgb: 245, 246, 247;
  --bg-sidebar: #ffffff;
  --bg-card: #ffffff;
  --bg-input: #eef0f2;
  --bg-hover: #e7e9ec;
  --bg-user-msg: #eef0f2;
  --bg-ai-msg: #ffffff;
  --border: rgba(0, 0, 0, 0.10);
  --text-primary: #0a0b0d;
  --text-secondary: #4a4f55;
  --text-muted: #8a9099;
  --accent: #0a0b0d;
  --on-accent: #ffffff;
  --accent-soft: rgba(0, 0, 0, 0.06);
  --accent-glow: rgba(0, 0, 0, 0.12);
  --danger: #d93025;
  --success: #188038;
  --warning: #b06000;
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 6px 24px rgba(0, 0, 0, 0.08);
  --shadow-lg: 0 18px 48px rgba(0, 0, 0, 0.12);
  --radius-sm: 12px;
  --radius-md: 18px;
  --radius-lg: 26px;
  --radius-pill: 999px;
  --sidebar-width: 280px;
  --header-height: 64px;
  --content-max-width: 900px;
  --glass-blur: blur(22px) saturate(180%);
  --spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}

[data-theme="dark"] {
  /* 页面底色用【深灰】而不是纯黑（用户 2026-09-16：「页面底部的那个色，
     不要用纯黑，用灰色」）。
     原因不只是审美：纯黑下人眼对「内容到哪儿为止」没有参照 —— 用量页内容短，
     底下那半屏就是一片无边的黑，看着像没加载完。
     深灰给了一个明确的底面，卡片浮在上面才有「一层一层」的层级。
     调色是一整套往上抬，不能只改 body：
     原来卡(#0d0d10)比 body(#000)【亮】，body 一改成灰，不跟着抬就会变成
     「卡片比页面还暗」的凹坑，层级整个反过来。抬完仍保持 侧栏 < 底 < 卡 < 输入。 */
  --bg-body: #121214;
  --bg-body-rgb: 18, 18, 20;
  --bg-sidebar: #0c0c0e;
  --bg-card: #1c1c1e;
  --bg-input: #242427;
  --bg-hover: #2c2c2e;
  --bg-user-msg: #242427;
  --bg-ai-msg: #1c1c1e;
  --border: rgba(255, 255, 255, 0.10);
  --text-primary: #f5f5f7;
  --text-secondary: #a1a1a6;
  --text-muted: #6e6e73;
  --accent: #ffffff;
  --on-accent: #000000;
  --accent-soft: rgba(255, 255, 255, 0.08);
  --accent-glow: rgba(255, 255, 255, 0.14);
  --danger: #ff6369;
  --success: #3dd68c;
  --warning: #f7b955;
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.5);
  --shadow-md: 0 6px 24px rgba(0, 0, 0, 0.6);
  --shadow-lg: 0 18px 48px rgba(0, 0, 0, 0.7);
}

/* ============ 基础重置 ============ */
* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body {
  height: 100%;
  /* ── 字体（站长 2026-10-01 口径：安卓侧改用 Noto Sans SC）───────────────
     顺序是刻意的：
       ① "PingFang SC" = 苹方。苹果设备系统自带（含 Semibold，标题加粗就是它），
          命中时**不下载任何字体文件**，零成本。苹方是苹果私有字体，
          安卓/iOS 之外的平台根本没有这个文件，CSS 里写多少遍也渲染不出来。
       ② "Noto Sans SC" = 自托管兜底（css/noto-sans-sc.css + fonts/noto/）。
          用来把安卓的默认 Roboto 顶掉。按 unicode-range 切片成 404 片，
          浏览器只下载页面真正用到的那几片，不是一次性 11MB。
          ⚠️ 2026-10-01 之前这里用的是 HarmonyOS Sans SC（华为）。
             换掉的原因：站长指定用 Google 的 Noto。两者都是可免费商用的
             开源字体，Noto 的字面更饱满、字形更接近苹方。
             旧的 fonts/harmonyos/ 与 css/font-pingfang.css 已不再被任何页面
             引用，保留在磁盘上仅作回滚用，确认无误后可删（省 20MB）。
       ③ Inter / 系统字体 = 极老浏览器或字体加载失败时的最后兜底。 */
  font-family: "PingFang SC", "Noto Sans SC", 'Inter', -apple-system, BlinkMacSystemFont,
    "SF Pro Text", "Segoe UI", Roboto, "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
  background: var(--bg-body);
  color: var(--text-primary);
  overflow: hidden;
  transition: background 0.4s var(--ease-out), color 0.4s var(--ease-out);
}

/* ============ 背景（纯净底色，无光斑高光） ============ */
.bg-glow { display: none; }

/* ============ 应用主容器 ============ */
#app { position: relative; z-index: 1; display: flex; height: 100dvh; width: 100%; }

/* ============ 按钮 ============ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 18px; border-radius: var(--radius-pill);
  background: var(--bg-card); border: 1px solid var(--border);
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  color: var(--text-primary); cursor: pointer; font-size: 0.9rem; font-weight: 500;
  transition: transform 0.35s var(--spring), background 0.25s var(--ease-out), box-shadow 0.25s var(--ease-out), border-color 0.25s var(--ease-out);
  white-space: nowrap;
}
.btn:hover { background: var(--bg-hover); transform: translateY(-1px); box-shadow: var(--shadow-md); }
.btn:active { transform: scale(0.96); }
.btn-primary {
  background: var(--accent);
  border-color: transparent; color: var(--on-accent);
  box-shadow: var(--shadow-sm);
}
.btn-primary:hover { background: var(--accent); opacity: 0.9; }
.btn-danger { color: var(--danger); }
.btn-danger:hover { background: rgba(229, 72, 77, 0.1); border-color: var(--danger); }
.btn-sm { padding: 6px 12px; font-size: 0.8rem; border-radius: var(--radius-pill); }
.icon-btn {
  width: 38px; height: 38px; padding: 0; justify-content: center; border-radius: 50%;
  background: transparent; border: none; color: var(--text-secondary);
  transition: transform 0.35s var(--spring), background 0.25s var(--ease-out), color 0.25s var(--ease-out);
}
.icon-btn:hover { background: var(--bg-hover); color: var(--text-primary); transform: scale(1.06); }
.icon-btn:active { transform: scale(0.92); }
/* 欢迎区（logo）显示时主题切换按钮锁定 */
.icon-btn.locked { opacity: 0.35; cursor: not-allowed; }
.icon-btn.locked:hover { background: transparent; color: var(--text-secondary); transform: none; }
/* 非对话页面：隐藏左上角三条杠 */
.hidden-btn { display: none !important; }

/* ============ 表单 ============ */
.form-group { margin-bottom: 18px; }
.form-group label { display: block; margin-bottom: 6px; font-size: 0.85rem; font-weight: 500; color: var(--text-secondary); }
.form-input {
  width: 100%; background: var(--bg-input); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 12px 14px; color: var(--text-primary);
  outline: none; font-size: 0.95rem;
  transition: border-color 0.25s var(--ease-out), box-shadow 0.25s var(--ease-out), background 0.25s var(--ease-out);
}
.form-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.form-input::placeholder { color: var(--text-muted); }

/* ============ 认证页面 ============ */
.auth-screen { display: flex; align-items: center; justify-content: center; height: 100%; width: 100%; padding: 20px; }
.auth-card {
  width: 100%; max-width: 420px; background: var(--bg-card);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  padding: 40px 32px; box-shadow: var(--shadow-lg);
  animation: cardIn 0.5s var(--ease-out);
}
@keyframes cardIn { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: translateY(0); } }
.auth-logo { text-align: center; margin-bottom: 32px; }
.auth-logo h1 { font-size: 2rem; font-weight: 700; letter-spacing: -0.5px; }
.auth-logo p { color: var(--text-secondary); margin-top: 6px; font-size: 0.9rem; }
.auth-footer { text-align: center; margin-top: 20px; font-size: 0.85rem; color: var(--text-secondary); }
.auth-footer a { color: var(--accent); cursor: pointer; font-weight: 500; }

/* ============ 应用布局 ============ */
.app-shell { display: flex; width: 100%; height: 100%; }

/* 侧边栏（毛玻璃） */
.sidebar {
  width: var(--sidebar-width); background: var(--bg-sidebar);
  border-right: 1px solid var(--border); display: flex; flex-direction: column;
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  flex-shrink: 0; min-width: 0;
  transition: width 0.32s var(--ease-out), transform 0.3s var(--ease-out), border-color 0.3s var(--ease-out);
  z-index: 50; overflow: hidden;
}
/* PC：完全收起（不再是窄条） */
@media (min-width: 769px) {
  .sidebar.hidden { width: 0; border-right-color: transparent; }
}
.sidebar-header {
  padding: 16px; display: flex; align-items: center; justify-content: space-between;
  border-bottom: 1px solid var(--border); min-height: var(--header-height);
}
.sidebar-header h3 { font-size: 0.95rem; font-weight: 600; white-space: nowrap; opacity: 0.8; }

/* ============ MaxMind 品牌标 ============
   标记本身是内联 SVG（core.js 里的 ICONS.brandMark），跟着 currentColor 走，
   所以深浅主题、侧栏、顶栏三处都不用换图。
   侧栏收起时宽度会过渡到 0，所以字标要能跟着一起消失（overflow 已有）。 */
.brand {
  display: flex; align-items: center; gap: 8px; min-width: 0;
  text-decoration: none; color: var(--text-primary);
  border-radius: 8px; padding: 2px 4px; margin-left: -4px;
}
.brand .brand-mark { width: 25px; height: 25px; flex: none; }
/* 字标：字距收紧，字号比正文小一点 —— 品牌字要"密"才像标识，不像标题 */
.brand-word {
  font-size: 1rem; font-weight: 680; letter-spacing: -0.03em;
  white-space: nowrap;
}
.brand-tag {
  font-size: 0.62rem; font-weight: 600; letter-spacing: 0.06em;
  padding: 2px 5px; border-radius: 5px; white-space: nowrap;
  color: var(--text-secondary); background: var(--hover-bg, rgba(127,127,127,0.14));
}
/* 顶栏品牌标：常驻显示（原来靠 .top-nav.hidden-btn 兄弟选择器只在部分板块露脸，
   移动端因此完全看不到 logo）。 */
.top-brand {
  display: flex; align-items: center; gap: 9px; flex: none;
  text-decoration: none; color: var(--text-primary);
  padding: 2px 4px; margin-left: -2px; border-radius: 8px;
}
.top-brand .brand-mark { width: 26px; height: 26px; flex: none; }
.top-brand .brand-word { font-size: 1.02rem; font-weight: 680; letter-spacing: -0.03em; white-space: nowrap; }
/* 窄屏也保留字标 —— 之前 <=520px 直接把 .brand-word 设成 display:none，
   手机上就只剩一个光秃秃的小图标（你看到的就是这个）。现在图标缩一档、
   字标留小一号，宁可挤一点也不去掉品牌名。 */
@media (max-width: 560px) {
  .top-brand { gap: 7px; }
  .top-brand .brand-mark { width: 22px; height: 22px; }
  .top-brand .brand-word { font-size: 0.94rem; }
}
/* 极窄屏（<380px，老机型）才收掉字标，否则滑块会被挤到换行 */
@media (max-width: 379px) {
  .top-brand .brand-word { display: none; }
}
.sidebar-list { flex: 1; overflow-y: auto; padding: 12px 8px; }
.sidebar-item {
  display: flex; align-items: center; gap: 12px; padding: 10px 12px;
  margin-bottom: 2px; border-radius: var(--radius-sm); cursor: pointer;
  color: var(--text-secondary); transition: all 0.2s var(--ease-out);
}
.sidebar-item:hover { background: var(--bg-hover); color: var(--text-primary); transform: translateX(2px); }
.sidebar-item.active { background: var(--accent-soft); color: var(--accent); font-weight: 500; }
.sidebar-item-text { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 0.85rem; }
.sidebar-item-time { font-size: 0.7rem; color: var(--text-muted); white-space: nowrap; }
.sidebar-new-chat {
  margin: 12px; padding: 10px; border-radius: var(--radius-sm);
  background: var(--accent-soft); color: var(--accent); border: none;
  cursor: pointer; font-weight: 500; font-size: 0.85rem;
  display: flex; align-items: center; justify-content: center; gap: 6px;
  transition: all 0.3s var(--spring);
}
.sidebar-new-chat:hover { background: var(--accent); color: var(--on-accent); transform: translateY(-1px); }

/* 主内容区 */
.main-content { flex: 1; display: flex; flex-direction: column; min-width: 0; background: transparent; }

/* 顶部栏（毛玻璃） */
.top-bar {
  height: var(--header-height); display: flex; align-items: center;
  justify-content: space-between; padding: 0 16px;
  background: var(--bg-sidebar); border-bottom: 1px solid var(--border);
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
}
.top-bar-left, .top-bar-right { display: flex; align-items: center; gap: 8px; }
/* 滑块被隐藏（用量 / 设置 / 后台 / 升级会员页）时，左上角只剩三条杠，
   gap 会留下一段多余的空白。:has 支持度已经够（Chrome 105+/Safari 15.4+），
   不支持也只是间距略大，不影响功能。 */
.top-bar-left:not(:has(.top-nav:not(.hidden-btn))) { gap: 0; }
.top-bar-title { font-size: 1.1rem; font-weight: 700; letter-spacing: -0.3px; }
.model-switch {
  display: inline-flex; align-items: center; gap: 7px;
  flex-shrink: 0; max-width: 55%;
  padding: 6px 12px; border-radius: 999px;
  background: #2a2a2a; border: 1px solid #3a3a3a;
  color: #b8b8b8; font-size: 0.8rem; font-weight: 500;
  cursor: pointer; white-space: nowrap; overflow: hidden;
  transition: all 0.25s ease;
}
.model-switch:hover { border-color: #555; color: #fff; }
.model-switch:active { transform: scale(0.97); }
.ms-dot { flex-shrink: 0; width: 8px; height: 8px; border-radius: 50%; background: var(--success); }
.model-switch .ms-name { overflow: hidden; text-overflow: ellipsis; }
.model-switch svg { flex-shrink: 0; opacity: 0.7; }

/* 页面内容 */
.page-content { flex: 1; overflow-y: auto; padding: 36px 24px 48px; display: flex; justify-content: center; }
.content-inner { width: 100%; max-width: var(--content-max-width); }

/* 玻璃卡片 */
.glass-card {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--radius-md); padding: 26px;
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  box-shadow: var(--shadow-sm);
  animation: uiIn 0.5s var(--ease-out);
}

/* 克制版非线性入场动画：淡入 + 轻微上浮（卡片/用量卡逐张浮现） */
/* ⚠️ uiIn 带 transform + fill:both —— 不要用在任何依赖 transform（例如
   translateX(-50%) 居中）或 position:fixed 的元素上，它会盖掉你的 transform。 */
@keyframes uiIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.u-card { animation: uiIn 0.5s var(--ease-out) both; }
.u-card:nth-child(2) { animation-delay: 0.04s; }
.u-card:nth-child(3) { animation-delay: 0.08s; }
.u-card:nth-child(4) { animation-delay: 0.12s; }
.u-card:nth-child(5) { animation-delay: 0.16s; }
.u-card:nth-child(6) { animation-delay: 0.2s; }
.u-card:nth-child(7) { animation-delay: 0.24s; }

/* ============ 聊天消息 ============ */
.chat-messages { display: flex; flex-direction: column; gap: 26px; padding-bottom: 26px; }
.message { display: flex; gap: 12px; animation: msgIn 0.4s var(--ease-out); }
@keyframes msgIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.message-avatar {
  flex-shrink: 0; width: 36px; height: 36px; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent);
  display: flex; align-items: center; justify-content: center;
  font-size: 0.8rem; font-weight: 600;
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
}
.message-body { flex: 1; min-width: 0; }
.message-content {
  line-height: 1.75; font-size: 0.95rem; word-wrap: break-word;
}

/* 用户消息：气泡托着（右上角小尾巴贴头像） */
.message-user { flex-direction: row-reverse; }
.message-user .message-avatar { background: var(--accent); color: var(--on-accent); }
/* 气泡要贴着右侧头像，不能因为 max-width 而漂到中间 */
.message-user .message-body { display: flex; flex-direction: column; align-items: flex-end; }
.message-bubble {
  background: var(--bg-user-msg);
  border: 1px solid var(--border);
  border-radius: 18px 6px 18px 18px;
  padding: 12px 16px;
  max-width: min(80%, 640px);
  line-height: 1.7; font-size: 0.95rem; word-wrap: break-word;
  box-shadow: var(--shadow-sm);
}

/* AI 回复（Codex 式）：无气泡，思考块在上、正式回答小方框在下 */
.message-assistant .message-content {
  background: none; border: none; box-shadow: none; backdrop-filter: none;
  padding: 0;
}
/* 回复紧接在用户气泡下面（读作一问一答的一对） */
.message-user + .message-assistant { margin-top: -12px; }
.ai-reply { display: flex; flex-direction: column; gap: 12px; }

/* 思考过程块：计时（往上跑）+ 横杠 + 灰色小字，可收起/展开 */
.thinking-block {
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  background: var(--bg-input);
}
.thinking-toggle {
  width: 100%; background: none; border: none; padding: 10px 14px;
  display: flex; align-items: center; gap: 8px; cursor: pointer;
  color: var(--text-secondary); font-size: 0.85rem; font-weight: 500;
  font-family: inherit; text-align: left;
  transition: background 0.2s var(--ease-out);
}
.thinking-toggle:hover { background: var(--bg-hover); }
.thinking-label { opacity: 0.95; }
.thinking-time {
  margin-left: auto;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted); font-size: 0.8rem;
}
.thinking-chevron { color: var(--text-muted); transition: transform 0.25s var(--ease-out); }
.thinking-block.collapsed .thinking-chevron { transform: rotate(-90deg); }
.thinking-divider { border-top: 1px solid var(--border); }
.thinking-content {
  padding: 12px 14px;
  font-size: 0.82rem; line-height: 1.7;
  color: var(--text-muted);
  white-space: pre-wrap; word-wrap: break-word;
  max-height: 280px; overflow-y: auto;
}
.thinking-block.collapsed .thinking-divider,
.thinking-block.collapsed .thinking-content { display: none; }

/* AI 正式回答：小方框（无气泡） */
.ai-answer-frame {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px 18px;
  background: var(--bg-card);
  box-shadow: var(--shadow-sm);
  animation: msgIn 0.4s var(--ease-out);
}

/* 额度限制气泡：近似方形的矩形，最左侧仪表盘指针 */
.quota-card {
  display: flex; align-items: center; gap: 16px;
  width: min(340px, 100%);
  aspect-ratio: 1.15;
  padding: 20px 22px;
  border: 1px solid var(--border);
  border-radius: 18px;
  background: var(--bg-card);
  box-shadow: var(--shadow-sm);
  animation: msgIn 0.4s var(--ease-out);
}
.quota-gauge {
  flex: none; width: 56px; height: 56px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--warning);
}
.quota-text { min-width: 0; }
.quota-title { font-size: 0.92rem; font-weight: 600; color: var(--text-primary); line-height: 1.5; }
.quota-sub { margin-top: 4px; font-size: 0.82rem; color: var(--text-secondary); }

@media (prefers-reduced-motion: reduce) {
  .thinking-block, .ai-answer-frame, .quota-card { animation: none; }
  .thinking-chevron { transition: none; }
}

/* ============ 聊天欢迎区（未开始对话：logo + 问候语，对齐 example 设计） ============ */
.chat-welcome {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center;
  min-height: calc(100dvh - var(--header-height) - 210px);
  padding: 32px 20px 16px;
}
/* 欢迎区品牌标识：矢量、透明底、currentColor —— 深浅主题都直接可用。
   原来这里是一张黑底 PNG + mix-blend-mode: screen，只能活在深色背景上。 */
.welcome-brand {
  display: flex; align-items: center; gap: clamp(14px, 2.4vw, 22px);
  margin-bottom: 34px;
  user-select: none; -webkit-user-select: none;
  animation: uiIn 0.55s var(--ease-out) both;
}
.welcome-brand .brand-mark { width: clamp(56px, 9vw, 88px); height: auto; flex: none; }
.welcome-word {
  font-size: clamp(2.4rem, 6.4vw, 4.6rem);
  font-weight: 650; letter-spacing: -0.045em; line-height: 1;
  color: var(--text-primary);
}
/* 极窄屏只留图标，免得字标被压成一团 */
@media (max-width: 420px) { .welcome-word { display: none; } }
.chat-welcome-greeting {
  /* 原来这里写死了一套系统字体栈，把 body 的字体覆盖掉了，导致同一页字体不统一。
     现在统一继承全站字体栈（自托管 Inter + 系统字体）。 */
  font-family: inherit;
  font-size: clamp(1.7rem, 4vw, 2.5rem);
  font-weight: 600; letter-spacing: -0.015em;
  color: var(--text-primary); margin: 0;
  animation: uiIn 0.55s var(--ease-out) 0.08s both;
}
.chat-welcome-sub {
  margin-top: 16px; color: var(--text-secondary); font-size: 0.98rem;
  letter-spacing: 0.02em;
  animation: uiIn 0.55s var(--ease-out) 0.16s both;
}
.chat-welcome.welcome-hide {
  opacity: 0; transform: translateY(-10px);
  height: 0; min-height: 0; overflow: hidden; padding: 0; margin: 0;
  transition: opacity 0.32s ease, transform 0.32s ease;
}

@media (max-width: 768px) {
  .chat-welcome { min-height: calc(100dvh - var(--header-height) - 180px); padding: 20px 8px 8px; }
  .chat-welcome-sub { font-size: 0.88rem; }
}

/* 打字指示器 */
.typing-indicator { display: flex; gap: 4px; padding: 8px 0; }
.typing-indicator span {
  width: 8px; height: 8px; border-radius: 50%; background: var(--text-muted);
  animation: typingBounce 1.2s var(--spring) infinite;
}
.typing-indicator span:nth-child(2) { animation-delay: 0.18s; }
.typing-indicator span:nth-child(3) { animation-delay: 0.36s; }
@keyframes typingBounce { 0%, 60%, 100% { transform: translateY(0); opacity: 0.4; } 30% { transform: translateY(-6px); opacity: 1; } }

/* ============ 输入区（对齐 example：深色卡片 + 列式布局 + 圆形发送钮） ============ */
.chat-input-area { padding: 4px 24px calc(20px + env(safe-area-inset-bottom)); display: flex; justify-content: center; }
.input-wrapper {
  width: 100%;
  max-width: var(--content-max-width);
  background: #1c1c1c;
  border: 1px solid #333;
  border-radius: 24px;
  padding: 16px;
  display: flex; flex-direction: column; gap: 10px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
  transition: border-color 0.3s ease;
}
.input-wrapper:focus-within { border-color: #555; }
.chat-textarea {
  flex: 1; background: transparent; border: none; outline: none;
  color: #e0e0e0; font-size: 16px; line-height: 1.5; resize: none;
  max-height: 200px; min-height: 48px; padding: 6px 2px; margin: 0;
  font-family: inherit;
}
.chat-textarea::placeholder { color: #555; }
.ai-actions { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.ai-actions-right { display: flex; align-items: center; gap: 8px; }
.send-btn {
  width: 32px; height: 32px; padding: 0; border-radius: 50%;
  background: #333; border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  color: #888; transition: all 0.2s ease;
}
.send-btn.active { background: #fff; color: #000; }
.send-btn:hover { background: #444; }
.send-btn.active:hover { background: #eee; }
.send-btn:active { transform: scale(0.92); }
.stop-btn {
  width: 32px; height: 32px; padding: 0; border-radius: 50%;
  background: #333; border: none; color: #ccc;
  display: flex; align-items: center; justify-content: center;
  font-size: 0.8rem; cursor: pointer; transition: all 0.2s ease;
}
.stop-btn:hover { background: #444; }
.stop-btn:active { transform: scale(0.92); }

/* ============ 弹窗（毛玻璃 + spring） ============ */
.modal-overlay {
  position: fixed; inset: 0; background: rgba(0, 0, 0, 0.35); z-index: 100;
  display: flex; align-items: center; justify-content: center;
  animation: fadeIn 0.25s var(--ease-out);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
.modal-sheet {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--radius-lg); width: min(92vw, 520px); max-height: 85vh;
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  overflow-y: auto; padding: 24px; box-shadow: var(--shadow-lg);
  animation: sheetIn 0.38s var(--ease-out);
}
@keyframes sheetIn { from { transform: translateY(18px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
.modal-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 20px; }
.modal-header h3 { font-size: 1.15rem; font-weight: 600; }

/* 服务错误弹窗：刻意「什么都没有」——一句话 + 一个出口，不做任何解释 */
.svc-err-text { color: var(--text-secondary); font-size: 0.92rem; line-height: 1.8; margin: 0; }
.svc-err-actions { display: flex; justify-content: flex-end; margin-top: 20px; }
.svc-err-actions .btn { min-width: 96px; }

/* ============ Toast 通知 ============ */
.toast-container { position: fixed; top: 20px; right: 20px; z-index: 200; display: flex; flex-direction: column; gap: 8px; }
.toast {
  padding: 12px 18px; border-radius: var(--radius-sm); background: var(--bg-card);
  border: 1px solid var(--border); box-shadow: var(--shadow-md); font-size: 0.85rem;
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  animation: toastIn 0.32s var(--ease-out); max-width: 320px;
}
@keyframes toastIn { from { transform: translateX(40px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
.toast.success { border-left: 4px solid var(--success); }
.toast.error { border-left: 4px solid var(--danger); }
.toast.info { border-left: 4px solid var(--accent); }

/* ============ 用量统计 ============ */
.usage-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 24px; }
.usage-card { padding: 20px; }
.usage-card-label { font-size: 0.8rem; color: var(--text-muted); margin-bottom: 8px; }
.usage-card-value { font-size: 1.5rem; font-weight: 700; }
.usage-bar { height: 8px; background: var(--bg-input); border-radius: 4px; margin-top: 12px; overflow: hidden; }
.usage-bar-fill { height: 100%; border-radius: 4px; transition: width 0.6s var(--ease-out); background: var(--success); }
.usage-bar-fill.warning { background: var(--warning); }
.usage-bar-fill.danger { background: var(--danger); }

/* ============ 后台管理 ============ */
.admin-section { margin-bottom: 20px; }
.admin-section h3 { font-size: 1rem; font-weight: 600; margin-bottom: 12px; }
.model-item, .user-item {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 0; border-bottom: 1px solid var(--border);
}
.model-item:last-child, .user-item:last-child { border-bottom: none; }
.model-item-info, .user-item-info { flex: 1; min-width: 0; margin-right: 12px; }
.model-item-name, .user-item-name { font-weight: 500; font-size: 0.9rem; }
.model-item-meta, .user-item-meta { font-size: 0.75rem; color: var(--text-muted); margin-top: 2px; word-break: break-all; }

/* ============ 通用辅助类 ============ */
.subtitle { color: var(--text-secondary); font-size: 0.9rem; }
.muted-text { color: var(--text-muted); }
.muted-text.empty { text-align: center; padding: 16px; }
.error-text { color: var(--danger); }
.sidebar-empty { padding: 20px; text-align: center; color: var(--text-muted); font-size: 0.85rem; }
.hint { color: var(--text-muted); font-size: 0.75rem; }
.form-actions { display: flex; gap: 8px; }

/* ============ 模型选择列表 ============ */
.model-picker-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.model-option-id { font-size: 0.8rem; color: var(--text-muted); }
.reasoning-label { font-size: 0.85rem; color: var(--text-secondary); }

/* ============ 主菜单 ============ */
.menu-list { display: flex; flex-direction: column; gap: 8px; }

/* ============ 用量行 ============ */
.usage-row { display: flex; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid var(--border); }
.usage-row:last-child { border-bottom: none; }
.usage-row-meta { color: var(--text-secondary); }

/* ============ 后台管理辅助 ============ */
.section-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
.multiplier { color: var(--text-muted); font-weight: 400; }
.admin-badge { color: var(--accent); }
.item-actions { display: flex; gap: 8px; flex-shrink: 0; }
.help-list { color: var(--text-secondary); font-size: 0.85rem; line-height: 1.8; padding-left: 20px; }

/* ============ 模型选择项 ============ */
.model-option {
  padding: 12px; border-radius: 10px; cursor: pointer;
  background: var(--bg-input); border: 1px solid var(--border);
  transition: all 0.25s var(--ease-out);
}
.model-option:hover { background: var(--bg-hover); transform: translateY(-1px); }
.model-option.active { border-color: var(--accent); background: var(--accent-soft); }

/* ============ 滚动条 ============ */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 10px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }

/* ============ 移动端适配 ============ */
@media (max-width: 768px) {
  :root { --header-height: 56px; --content-max-width: 100%; }
  .sidebar {
    position: absolute; left: 0; top: 0; bottom: 0; width: 80vw; max-width: 320px;
    transform: translateX(-100%); box-shadow: var(--shadow-lg);
  }
  .sidebar.open { transform: translateX(0); }
  .page-content { padding: 20px 14px 32px; }
  .chat-input-area { padding: 2px 12px calc(18px + env(safe-area-inset-bottom)); }
  .input-wrapper { padding: 13px 14px; border-radius: 20px; }
  .chat-textarea { min-height: 44px; }
  .chat-welcome { min-height: calc(100dvh - var(--header-height) - 190px); padding: 20px 8px 8px; }
  .chat-welcome-sub { font-size: 0.88rem; }
  .message-avatar { width: 32px; height: 32px; font-size: 0.75rem; }
  .auth-card { padding: 28px 20px; }
  .modal-sheet {
    width: 100%; max-width: 100%; border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    margin-top: auto; margin-bottom: 0; max-height: 90vh; align-self: flex-end;
  }
  .modal-overlay { align-items: flex-end; }
  .usage-cards { grid-template-columns: 1fr; }
  .top-bar { padding: 0 10px; }
  .top-nav { margin-left: 2px; }
  .top-nav-btn { padding: 5px 12px; font-size: 0.82rem; }
}

/* ============ 认证分栏页（PC：左介绍 + 右表单） ============ */
.auth-screen {
  display: grid; grid-template-columns: 1.15fr 1fr;
  height: 100%; width: 100%; padding: 0; align-items: stretch;
}
.auth-hero {
  display: flex; align-items: center; justify-content: center;
  padding: 48px clamp(24px, 5vw, 72px);
  background: var(--bg-body);
  border-right: 1px solid var(--border);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.hero-inner { max-width: 480px; }
.hero-brand { display: flex; align-items: baseline; gap: 10px; margin-bottom: 26px; }
.hero-mark {
  font-size: 2rem; font-weight: 800; letter-spacing: -1px; color: var(--accent);
  font-family: ui-monospace, 'SF Mono', Consolas, monospace;
}
.hero-mark-sub { font-size: 2rem; font-weight: 300; letter-spacing: -1px; }
.hero-title { font-size: clamp(1.8rem, 3.2vw, 2.7rem); line-height: 1.22; font-weight: 700; letter-spacing: -1px; margin-bottom: 16px; }
.hero-desc { color: var(--text-secondary); line-height: 1.75; margin-bottom: 32px; font-size: 0.98rem; max-width: 420px; }
.hero-features { display: flex; flex-direction: column; gap: 18px; }
.hero-feature { display: flex; gap: 14px; align-items: flex-start; }
.hf-icon {
  flex-shrink: 0; width: 42px; height: 42px; border-radius: 12px;
  background: var(--accent-soft); color: var(--accent);
  display: flex; align-items: center; justify-content: center;
}
.hf-text h4 { font-size: 0.96rem; font-weight: 600; margin-bottom: 3px; }
.hf-text p { font-size: 0.82rem; color: var(--text-secondary); line-height: 1.55; }
.hero-foot { margin-top: 32px; font-size: 0.78rem; color: var(--text-muted); letter-spacing: 0.02em; }

.auth-panel { display: flex; align-items: center; justify-content: center; padding: 40px 24px; }
.auth-card { max-width: 400px; padding: 36px 32px; border: 1px solid var(--border); box-shadow: var(--shadow-lg); }
.auth-card-head { margin-bottom: 26px; }
.auth-card-head h2 { font-size: 1.5rem; letter-spacing: -0.4px; }
.auth-card-head p { color: var(--text-secondary); font-size: 0.88rem; margin-top: 5px; }
.btn-block { width: 100%; }

/* ============ 设置页 ============ */
.settings-card { margin-bottom: 22px; }
.settings-card-head { display: flex; align-items: center; gap: 16px; }
.settings-avatar {
  width: 54px; height: 54px; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.35rem; font-weight: 700;
}
.settings-id { flex: 1; min-width: 0; }
.settings-name { font-weight: 600; font-size: 1.05rem; }
.settings-meta { font-size: 0.8rem; color: var(--text-muted); margin-top: 2px; }
.settings-section-title {
  font-size: 0.8rem; color: var(--text-muted); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 12px;
}
.settings-nav { display: flex; flex-direction: column; gap: 2px; }
.settings-nav-item {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px;
  background: none; border: none; border-radius: var(--radius-sm); width: 100%;
  color: var(--text-primary); font-size: 0.93rem; cursor: pointer; text-align: left;
  transition: background 0.2s var(--ease-out), transform 0.2s var(--spring);
}
.settings-nav-item:hover { background: var(--bg-hover); }
.settings-nav-item:active { transform: scale(0.99); }
.sn-icon { color: var(--text-secondary); display: flex; align-items: center; }
.sn-arrow { margin-left: auto; color: var(--text-muted); font-size: 1.15rem; }
.settings-row { display: flex; align-items: center; justify-content: space-between; gap: 18px; padding: 8px 0; }
.settings-row-title { font-size: 0.93rem; font-weight: 500; }
.settings-row-desc { font-size: 0.8rem; color: var(--text-secondary); margin-top: 3px; max-width: 520px; }
.theme-seg { display: inline-flex; background: var(--bg-input); border-radius: var(--radius-pill); padding: 3px; border: 1px solid var(--border); flex-shrink: 0; }
.theme-seg-btn {
  border: none; background: transparent; padding: 6px 16px; border-radius: var(--radius-pill);
  cursor: pointer; color: var(--text-secondary); font-size: 0.85rem; font-weight: 500;
  transition: all 0.25s var(--spring);
}
.theme-seg-btn.active { background: var(--accent); color: var(--on-accent); }
.pw-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 14px; }
.settings-pw-form { margin-top: 4px; }

/* ============ 后台管理（Tab 化） ============ */
.admin-head {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  flex-wrap: wrap; margin-bottom: 16px; padding: 18px 20px;
}
.admin-tabs {
  display: inline-flex; gap: 3px; background: var(--bg-input);
  border-radius: var(--radius-pill); padding: 4px; border: 1px solid var(--border);
}
.admin-tab {
  border: none; background: transparent; padding: 8px 18px; border-radius: var(--radius-pill);
  color: var(--text-secondary); font-size: 0.88rem; font-weight: 500; cursor: pointer;
  white-space: nowrap; transition: all 0.25s var(--spring);
}
.admin-tab:hover { color: var(--text-primary); }
.admin-tab.active { background: var(--accent); color: var(--on-accent); }
.loading-hint { color: var(--text-muted); text-align: center; padding: 48px; }
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(165px, 1fr)); gap: 14px; }
.stat-card { padding: 18px; animation: cardIn 0.45s var(--ease-out); }
.stat-icon {
  width: 38px; height: 38px; border-radius: 10px; margin-bottom: 12px;
  background: var(--accent-soft); color: var(--accent);
  display: flex; align-items: center; justify-content: center;
}
.stat-value { font-size: 1.6rem; font-weight: 700; letter-spacing: -0.5px; font-variant-numeric: tabular-nums; }
.stat-label { font-size: 0.78rem; color: var(--text-muted); margin-top: 2px; }
.table-wrap { overflow-x: auto; }
.data-table { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
.data-table th {
  text-align: left; padding: 10px 12px; color: var(--text-muted); font-weight: 500;
  font-size: 0.76rem; border-bottom: 1px solid var(--border); white-space: nowrap;
}
.data-table td { padding: 10px 12px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.data-table tbody tr { transition: background 0.15s var(--ease-out); }
.data-table tbody tr:hover { background: var(--bg-hover); }
.data-table tbody tr:last-child td { border-bottom: none; }
.count-pill {
  background: var(--accent-soft); color: var(--accent); border-radius: 20px;
  padding: 2px 10px; font-size: 0.75rem; font-weight: 600; vertical-align: middle;
}
.status-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; vertical-align: middle; }
.status-dot.ok { background: var(--success); }
.status-dot.off { background: var(--danger); }
.lim-vals { font-variant-numeric: tabular-nums; font-size: 0.8rem; white-space: nowrap; }
.save-ok { color: var(--success); font-size: 0.85rem; font-weight: 500; }
.settings-divider { height: 1px; background: var(--border); margin: 18px 0; }
.run-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
.run-item {
  padding: 12px 14px; border-radius: var(--radius-sm);
  background: var(--bg-input); border: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 4px;
}
.run-k { font-size: 0.75rem; color: var(--text-muted); }
.run-v { font-size: 0.95rem; font-weight: 600; }
.log-tools { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.log-total td { background: var(--bg-input); font-variant-numeric: tabular-nums; }
.default-limits-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; max-width: 520px; }

/* 开关 */
.switch { position: relative; display: inline-block; width: 50px; height: 28px; flex-shrink: 0; }
.switch input { opacity: 0; width: 0; height: 0; }
.switch-slider {
  position: absolute; inset: 0; background: var(--bg-input); border: 1px solid var(--border);
  border-radius: 30px; cursor: pointer;
  transition: background 0.25s var(--ease-out), border-color 0.25s var(--ease-out);
}
.switch-slider::before {
  content: ''; position: absolute; width: 20px; height: 20px; left: 3px; top: 3px;
  background: var(--text-muted); border-radius: 50%;
  transition: transform 0.3s var(--spring), background 0.25s var(--ease-out);
}
.switch input:checked + .switch-slider { background: var(--accent); border-color: transparent; }
.switch input:checked + .switch-slider::before { transform: translateX(22px); background: var(--on-accent); }

/* ============ 移动端补充 ============ */
@media (max-width: 768px) {
  .auth-screen { display: flex; align-items: center; justify-content: center; padding: 16px; }
  .auth-hero { display: none; }
  .auth-panel { padding: 0; width: 100%; }
  .auth-card { padding: 28px 20px; }
  .pw-grid { grid-template-columns: 1fr; }
  .settings-row { flex-direction: column; align-items: flex-start; }
  .admin-head { flex-direction: column; align-items: flex-start; }
  .admin-tabs { width: 100%; overflow-x: auto; }
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
  .model-switch { max-width: 50%; padding: 6px 10px; font-size: 0.8rem; }
  .input-wrapper { gap: 6px; }
}

/* ============ 用量统计（Apple 风格） ============ */
:root {
  --u-card: #ffffff;
  --u-border: rgba(0, 0, 0, 0.10);
  --u-border-soft: rgba(0, 0, 0, 0.06);
  --u-shadow: 0 6px 24px rgba(0, 0, 0, 0.06);
  --u-head: #0a0b0d;
  --u-muted: #4a4f55;
  --u-faint: #8a9099;
  --u-track: #e7e9ec;
  --u-hover: rgba(0, 0, 0, 0.05);
}
[data-theme="dark"] {
  --u-card: #15171b;
  --u-border: rgba(255, 255, 255, 0.10);
  --u-border-soft: rgba(255, 255, 255, 0.07);
  --u-shadow: 0 10px 32px rgba(0, 0, 0, 0.4);
  --u-head: #f5f5f7;
  --u-muted: #a1a1a6;
  --u-faint: #6e6e73;
  --u-track: #2c2c2e;
  --u-hover: rgba(255, 255, 255, 0.08);
}
.u-page { display: flex; flex-direction: column; gap: 18px; }
.u-header { display: flex; justify-content: space-between; align-items: flex-end; gap: 14px; flex-wrap: wrap; padding: 2px 4px 0; }
.u-title { font-size: 27px; font-weight: 700; letter-spacing: -0.6px; color: var(--u-head); }
.u-sub { font-size: 13px; color: var(--u-faint); margin-top: 3px; }

/* ---- 标题不换行 / 溢出修复 ----
   症状：像「API 接入」这种页的大标题和长副标题在窄屏（平板/手机）显示不全、直接溢出。
   原因：.u-header 是 flex 容器，里面包标题的 <div> 没写 min-width:0，
        flex 子项默认 min-width:auto 不允许收缩到内容宽度以下，长中文串就不换行了。 */
.u-header > * { min-width: 0; }
.u-title, .u-sub { overflow-wrap: break-word; word-break: break-word; }
.u-sub { line-height: 1.55; }
/* 设置页 / 后台等大标题同理，避免长中文被截 */
.settings-section-title, .admin-head h2, .admin-head h3 { overflow-wrap: break-word; }
/* 聊天页问候语：长用户名不要撑破容器 */
.chat-welcome-greeting { overflow-wrap: break-word; }
.u-total { font-size: 13px; color: var(--u-muted); padding-bottom: 4px; }
.u-total strong { color: var(--u-head); font-variant-numeric: tabular-nums; font-size: 15px; }
.usage-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 16px; }

.u-card {
  background: var(--u-card);
  border: 1px solid var(--u-border);
  border-radius: 18px;
  padding: 22px 22px 18px;
  box-shadow: var(--u-shadow);
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
}
.u-card-head { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; }
.u-card-title { font-size: 15px; font-weight: 600; color: var(--u-head); letter-spacing: -0.2px; }
.u-count { margin-left: auto; font-size: 12px; color: var(--u-faint); }
/* 窗口说明按钮（「这个额度怎么算」）。
   ⚠️ 原来这里是拿字体画的一个 "i"：font: 700 9px/1 ui-serif, Georgia, serif。
   用户 2026-09-16 反馈「那个灰色圆圈中间的 i 去哪了」—— 圆圈在、字形没了。
   原因是这种画法把「看得见」这件事押在三个都不受控的东西上：
     · 9px 的衬线 "i" 本来就是一根头发丝，字重 700 也救不回来；
     · 字体回退链 `ui-serif → Georgia → serif` 在 Android 上落到 Noto Serif，
       不同设备落到的字体不一样，粗细和点的大小都不一样；
     · 字号小于浏览器的最小字号设置时，圆点可能被四舍五入掉。
   换成内联 SVG：几何图形由 viewBox 定义，跟字体、字号、设备全部无关，
   在任何 DPR 下都是同一条线。
   颜色一律走 currentColor，所以 hover / 主题切换只需要改 color。 */
.u-info {
  width: 15px; height: 15px; margin-left: 7px; padding: 0;
  border: 0; background: none; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--u-faint); cursor: pointer; user-select: none;
  transition: color 0.2s ease, background-color 0.2s ease;
  flex: 0 0 auto;
}
.u-info svg { width: 15px; height: 15px; display: block; overflow: visible; }
.u-info svg circle:first-child { fill: none; stroke: currentColor; stroke-width: 1.25; }
.u-info svg path { fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; }
/* 图形本身只有 15px，但手指不是鼠标 —— 用一层透明的伪元素把可点区域撑到 44px。
   只扩命中区，不改视觉尺寸（Apple HIG 的最小可点边长是 44pt）。
   伪元素参与布局会把行撑高，所以走 absolute + 负偏移，完全脱离文档流。 */
.u-info { position: relative; }
.u-info::after {
  content: ''; position: absolute; left: 50%; top: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
}
.u-info:hover { color: var(--u-muted); background: var(--u-hover); }
.u-body { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 16px; }
.u-percent { font-size: 34px; font-weight: 700; letter-spacing: -1px; line-height: 1; color: var(--u-head); display: flex; align-items: baseline; font-variant-numeric: tabular-nums; }
.u-sym { font-size: 20px; font-weight: 600; color: var(--u-muted); margin-left: 2px; margin-right: 4px; }
.u-label { font-size: 13px; font-weight: 400; color: var(--u-faint); }
.u-progress { height: 9px; border-radius: 5px; background: var(--u-track); overflow: hidden; margin-bottom: 14px; }
.u-progress-fill { height: 100%; border-radius: 5px; background: var(--accent); transition: width 0.6s var(--ease-out); }
.u-progress-fill.mid { background: var(--accent); opacity: 0.65; }
.u-progress-fill.low { background: var(--accent); opacity: 0.4; }
.u-meta { font-size: 12.5px; color: var(--u-muted); font-variant-numeric: tabular-nums; }
.u-meta b { color: var(--u-head); }
.u-meta + .u-meta { margin-top: 3px; }
.u-faint { color: var(--u-faint); }

/* ── 高速接入卡片（API Key 页最下面那块，2026-09-16 第七轮新增）────────────
   只用本文件已有的 u-* / accent 变量，不引入新配色，跟上面几张卡片同族。 */
.speed-rows { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
.speed-line {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  font-size: 13px; line-height: 1.6;
  padding-bottom: 8px; border-bottom: 1px solid var(--u-border);
}
.speed-line:last-child { border-bottom: 0; padding-bottom: 0; }
.speed-k { color: var(--u-faint); flex: 0 0 auto; }
.speed-v { color: var(--u-head); font-weight: 600; text-align: right; font-variant-numeric: tabular-nums; }
.speed-v code { font-size: 12px; }
.speed-v.is-on { color: var(--accent); }
.speed-note {
  border: 1px solid var(--u-border); border-radius: 12px;
  padding: 10px 12px; font-size: 13px; line-height: 1.7; color: var(--u-muted);
  background: var(--u-hover);
}
.speed-note b { color: var(--u-head); }
.speed-actions { display: flex; gap: 10px; }
.speed-actions .btn { flex: 1; }

/* ============ 额度区（ChatGPT 风：无卡片、极简、大留白） ============
   条 = 当前可用额度，满额 100% → 用光 0%
   配色按「已用」分档：绿 <60% / 黄 60-79% / 橙 80-94% / 红 95%+（取自 ai-gauge，MIT）
   浅色用 Apple 可访问性变体，深色用 Apple 深色模式系统色 */
:root {
  --u-ok: #248a3d;
  --u-warn: #b25000;
  --u-risk: #c93400;
  --u-crit: #d70015;
}
[data-theme="dark"] {
  --u-ok: #30d158;
  --u-warn: #ffd60a;
  --u-risk: #ff9f0a;
  --u-crit: #ff453a;
}
/* ============ 字体：自托管 Inter（西文与数字） ============
   背景：body 里声明的 'Inter' 从来加载不到（无 @font-face、无字体文件），
   苹果回落到苹方、安卓回落到 Roboto，两套字体栈在安卓上解析结果完全一样。
   这里改为自托管，只影响用量页（.u-page）：数字/英文用 Inter，中文仍用系统中文字体。
   字体文件：public/fonts/，SIL Open Font License 1.1（见 fonts/OFL.txt）。
   注意路径用 ../fonts/：样式表在 /aip-console/css/ 下，字体在 /aip-console/fonts/。
   同源加载，符合 index.html 现有 CSP（无 font-src，回落 default-src 'self'）。 */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../fonts/inter-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
    U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* 全站已统一字体栈，用量页无需再单独声明 */
/* ---- 三条额度条 ----
   版式参考 CodexMeter（macOS 菜单栏额度工具，github.com/raycalrui/CodexMeter）
   里两处值得抄的做法：
   1) 状态不靠颜色单独表达 —— 节奏快慢都带图标 + 文字，色觉障碍也读得出来；
   2) 同一块里的多项用「分隔线 + 留白」分组，不要每一项各套一张卡片，
      嵌套卡片会把层级压平，看起来又碎又挤。 */
:root {
  --u-ok-bg: rgba(36, 138, 61, 0.10);
  --u-warn-bg: rgba(178, 80, 0, 0.10);
  --u-risk-bg: rgba(201, 52, 0, 0.10);
  --u-crit-bg: rgba(215, 0, 21, 0.10);
}
[data-theme="dark"] {
  --u-ok-bg: rgba(48, 209, 88, 0.14);
  --u-warn-bg: rgba(255, 214, 10, 0.14);
  --u-risk-bg: rgba(255, 159, 10, 0.14);
  --u-crit-bg: rgba(255, 69, 58, 0.14);
}
.q-list { display: flex; flex-direction: column; }
.q-item { padding: 21px 0; }
.q-item:first-child { padding-top: 2px; }
.q-item:last-child { padding-bottom: 2px; }
.q-item + .q-item { border-top: 1px solid var(--u-border-soft); }

/* 名称行：单独一行、字号小、颜色次要。
   它只是「这一行是谁」的标签，整屏扫读时眼睛落在下面的数字上，
   所以标签必须让位 —— 标签和数字一样粗一样大，就没有主角了。 */
.q-name {
  display: flex; align-items: center; gap: 6px;
  font-size: 13px; font-weight: 500; color: var(--u-muted);
  letter-spacing: -0.1px; margin-bottom: 6px;
}
.q-pct {
  font-size: 25px; font-weight: 650;
  /* 字距用 em 而不是 px：字号一变（pages.css 会放大）字距要跟着缩放。
     固定 px 在小字号上过紧、大字号上过松 —— Apple 的字距表本来就是按字号给的。 */
  letter-spacing: -0.02em; line-height: 1;
  color: var(--u-head); font-variant-numeric: tabular-nums;
}
/* ---- 数字滚动 ----
   由 NumberFlow 渲染（MIT）· https://github.com/barvian/number-flow
   它把数字渲染在 shadow DOM 里，字体/颜色从 .q-pct 继承，这里不用管。

   滚动时数字会在库自带的软遮罩里淡入淡出（遮罩高度 = --number-flow-mask-height，
   默认 0.25em）。默认值只够盖住字形的上下内边距，滚动时几乎看不出来，
   所以放宽到 0.6em。想调手感就改这一个数：0.25em ≈ 几乎看不见，1em 更夸张。

   ---- 滚动时的模糊 ----
   模糊本身不在这里，而在 app.js 的 attachRollBlur()：
   它读 Web Animations 的真实进度，逐帧把模糊值写进 --roll-blur，
   再由注入 shadow root 的一条规则消费：
       .digit.is-spinning { filter: blur(var(--roll-blur, 0px)); }
   所以这里不需要（也不能）写死一个模糊动画 —— 写死了就又变成
   「模糊和动画各跑各的」，快慢对不齐。详见 app.js 里那段注释。 */
.q-pct number-flow {
  display: inline-block; vertical-align: baseline;
  --number-flow-mask-height: 0.6em;
}

/* 颜色策略：默认中性，只有需要用户注意时才上色。
   四个档位全上色（绿/黄/橙/红）看着很"仪表盘"，但 96% 也涂成绿色，
   颜色就不再是信号，只是装饰 —— 用户会对它免疫。所以：
     充足(is-ok) → 和正文同色；偏紧/紧张/即将用尽 才染成对应色。 */
.q-pct.is-warn { color: var(--u-warn); }
.q-pct.is-risk { color: var(--u-risk); }
.q-pct.is-crit { color: var(--u-crit); }

/* ---- 进度条 ----
   画的是【剩余】：满格 = 满额度，和右边的百分比同向，不会看反。
   用 transform:scaleX 而不是 width —— scaleX 只走合成层，不触发 layout；
   width 每秒改一次会让整条链路重排，手机上直接白掉电。
   因此圆角必须留在轨道上（overflow:hidden），填充本身不能带圆角：
   scaleX 会把圆角横向压扁，值越低两端越尖，看着像被啃过。
   --q-ratio 是无单位比值（0~1），由 app.js 写进 style（首次渲染即内联，避免闪一条满格）。 */
.q-bar {
  height: 8px; border-radius: 4px; overflow: hidden;
  /* 条和上面的数字是【一个整体】：条是数字的图形化，不是它下面的一段新内容。
     7px 还是被读成「两段」，再收到 4px —— 视觉上贴着数字下沿。
     上限就到这里：再小（0~2px）条会和大号数字的负半行距打架，字母底边
     会压到条上，看着像贴纸没贴正。 */
  background: var(--u-track); margin-top: 4px;
}
.q-fill {
  height: 100%; width: 100%; transform-origin: left center;
  transform: scaleX(var(--q-ratio, 1));
  background: var(--u-ok);
  transition: transform 480ms var(--ease-out), background-color 200ms ease;
}
/* 条和数字共用同一套分档配色。绿色只在充足时出现 ——
   还剩 5% 却still是绿的，那条绿线就是在骗人。 */
/* 前缀用 is-*，和紧挨着的 .q-pct 保持同一套 —— 它们显示的是同一个值，
   类名再分两族（is-/lv-）就只是给下一个人埋坑。
   .q-tag.lv-* 不在此列：它讲的是「进度快慢」，和额度健康度不是一回事。 */
.q-fill.is-warn { background: var(--u-warn); }
.q-fill.is-risk { background: var(--u-risk); }
.q-fill.is-crit { background: var(--u-crit); }

.q-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 6px; flex-wrap: wrap; }
.q-sub {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; color: var(--u-faint); font-variant-numeric: tabular-nums;
}
/* 图标一律内联 SVG（跟着 currentColor 与字号走），不漏 emoji：
   emoji 在不同系统上字形/颜色/基线都不一样，一混进来就显廉价。 */
.q-ic { display: inline-flex; align-items: center; flex: none; }
.q-ic svg { display: block; }
.q-sub .q-ic svg { width: 13px; height: 13px; }
.q-tag {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3.5px 9px 3.5px 7px; border-radius: 999px;
  font-size: 12px; font-weight: 600; letter-spacing: -0.1px; white-space: nowrap;
}
.q-tag .q-ic svg { width: 11px; height: 11px; }
.q-tag.lv-ok { color: var(--u-ok); background: var(--u-ok-bg); }
.q-tag.lv-warn { color: var(--u-warn); background: var(--u-warn-bg); }
.q-tag.lv-risk { color: var(--u-risk); background: var(--u-risk-bg); }
.q-tag.lv-crit { color: var(--u-crit); background: var(--u-crit-bg); }

/* 百分比：颜色变化要走过渡，否则「充足 → 偏紧」那一刻数字会生硬地跳色。
   颜色过渡用 ease（不是 ease-out）—— 它没有位移，不需要起步的冲劲。 */
.q-pct { transition: color 200ms ease; }

/* ---- 额度区：直接铺在页面上 ----
   三条窗口只用「分隔线 + 留白」分组，不套卡片。
   额度是这一页的主体内容，它不需要一个框来托住 —— 直接站在页面上层级更清楚。 */
.u-quota { display: flex; flex-direction: column; }

/* ---- 当前套餐 ----
   与额度行同族的一条行（同一条分隔线 + 同样的留白），右侧一个动作按钮。
   不单独套卡片：它和上面三条是同一份数据的不同切面，视觉上应当是连续的。 */
.u-plan {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; padding-top: 18px;
  border-top: 1px solid var(--u-border-soft);
}
.u-plan-main { min-width: 0; }
.u-plan-k { font-size: 12.5px; color: var(--u-faint); }
.u-plan-name {
  font-size: 17px; font-weight: 600; color: var(--u-head);
  letter-spacing: -0.3px; margin-top: 2px;
}
.u-plan-sub {
  font-size: 12.5px; color: var(--u-muted); margin-top: 3px;
  font-variant-numeric: tabular-nums;
}
.u-plan .btn { flex: none; }

/* ---- 按钥匙 ----
   和额度行、当前套餐同一族：分隔线 + 留白，不套卡片。
   这里的百分比【不做色彩分档】—— 占比是「谁在吃额度」的结构信息，
   不是「你还有多少余量」的健康信号。给它上色会和上面三个数混成一类，
   用户会以为 62% 也代表「用了 62% 的额度」。 */
.u-keys { display: flex; flex-direction: column; }
.u-keys-head { padding-bottom: 10px; }
.u-keys-title {
  font-size: 13px; font-weight: 600; color: var(--u-head);
  letter-spacing: 0.1px;
}
.u-keys-sub { font-size: 12px; color: var(--u-faint); margin-top: 2px; }
.u-keys-list { display: flex; flex-direction: column; }

.uk-item {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 13px 0;
  border-top: 1px solid var(--u-border-soft);
}
.uk-main { min-width: 0; }
.uk-name {
  font-size: 0.9375rem; color: var(--u-head); font-weight: 500;
  letter-spacing: -0.1px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.uk-sub {
  font-size: 12px; color: var(--u-faint); margin-top: 3px;
  font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.uk-pct {
  flex: none; display: flex; align-items: baseline; gap: 1px;
  font-variant-numeric: tabular-nums; color: var(--u-muted);
}
.uk-num { font-size: 1.0625rem; font-weight: 600; letter-spacing: -0.02em; }
.uk-sign { font-size: 0.75rem; font-weight: 500; }
.uk-rest .uk-name, .uk-rest .uk-num { color: var(--u-faint); font-weight: 500; }
.uk-empty {
  font-size: 12.5px; color: var(--u-faint); line-height: 1.65;
  padding: 13px 0; border-top: 1px solid var(--u-border-soft);
}

/* ---- 额度说明 ---- */
.u-help { display: flex; flex-direction: column; gap: 9px; }
.u-help-title {
  font-size: 12.5px; font-weight: 600; color: var(--u-faint);
  letter-spacing: 0.2px;
}
.u-help-list { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 7px; }
/* 用 <li> 自带的小圆点做列表符（不用 list-style 的默认符号：
   默认符号的字形、大小、缩进由浏览器决定，四家浏览器四个样）。
   圆点用绝对定位钉在行首，跟首行文字的视觉中线对齐。 */
.u-help-list li {
  position: relative; padding-left: 15px;
  font-size: 12.5px; line-height: 1.65; color: var(--u-muted);
}
.u-help-list li::before {
  content: ''; position: absolute; left: 3px; top: 0.62em;
  width: 3px; height: 3px; border-radius: 50%; background: var(--u-faint);
}

/* ---- 用量页入场 ----
   只在用量页（#usage-details）生效，不去动别的 .u-page（API 接入页那几张
   .u-card 有自己的 uiIn + 延迟，两条规则撞在同一个元素上会把延迟搞乱）。
   时长 260ms：UI 动画不过 300ms；stagger 45ms：落在 30~80ms 区间。
   只用 opacity + transform —— 两个都是合成器属性，不进 layout / paint。 */
#usage-details .u-page > * {
  animation: uIn 0.26s var(--ease-out) both;
}
#usage-details .u-page > *:nth-child(1) { animation-delay: 0ms; }
#usage-details .u-page > *:nth-child(2) { animation-delay: 45ms; }
#usage-details .u-page > *:nth-child(3) { animation-delay: 90ms; }
#usage-details .u-page > *:nth-child(4) { animation-delay: 135ms; }
#usage-details .u-page > *:nth-child(5) { animation-delay: 180ms; }
#usage-details .u-page > *:nth-child(6) { animation-delay: 225ms; }
@keyframes uIn {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}
/* 减少动态：保留透明度（帮助理解"内容变了"），去掉位移。
   注意是【减弱】不是【全关】—— 直接全关会让淡入也没了，内容会硬邦邦地出现。 */
@media (prefers-reduced-motion: reduce) {
  #usage-details .u-page > * {
    animation: uFade 0.2s ease both;
  }
  .q-pct { transition: none; }
  /* 条也要一起关。只关数字不关条，等于「数字立刻到、条慢慢爬」——
     两处显示的是同一个值，动效偏好下它们必须同时到位。 */
  .q-fill { transition: none; }
}
@keyframes uFade { from { opacity: 0; } to { opacity: 1; } }

.u-row { padding: 12px 0; border-bottom: 1px solid var(--u-border-soft); display: flex; flex-direction: column; gap: 7px; }
.u-row:last-child { border-bottom: none; }
.u-row-top { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; }
.u-row-name { font-size: 14px; font-weight: 500; color: var(--u-head); }
.u-row-val { font-size: 12.5px; color: var(--u-muted); font-variant-numeric: tabular-nums; }
.u-row-bar { height: 5px; border-radius: 3px; background: var(--u-track); overflow: hidden; }
.u-row-fill { height: 100%; border-radius: 3px; background: var(--accent); transition: width 0.6s var(--ease-out); }

.u-rec { display: flex; justify-content: space-between; align-items: center; gap: 14px; padding: 10px 0; border-bottom: 1px solid var(--u-border-soft); }
.u-rec:last-child { border-bottom: none; }
.u-rec-left { min-width: 0; }
.u-rec-model { font-size: 13px; font-weight: 500; color: var(--u-head); }
.u-rec-time { font-size: 12px; color: var(--u-faint); margin-top: 2px; font-variant-numeric: tabular-nums; }
.u-rec-tok { font-size: 13px; color: var(--u-muted); flex-shrink: 0; font-variant-numeric: tabular-nums; }
.u-empty { padding: 20px 0; text-align: center; color: var(--u-faint); font-size: 13px; }

@media (max-width: 768px) {
  .u-header { flex-direction: column; align-items: flex-start; }
  .u-title { font-size: 23px; line-height: 1.25; }
  .u-sub { font-size: 12.5px; }
  .chat-welcome-greeting { font-size: 1.5rem; line-height: 1.3; }
  .usage-cards { grid-template-columns: 1fr; }
  .u-percent { font-size: 30px; }
}

/* ============ 顶部板块导航 ============ */
.top-nav {
  display: inline-flex; gap: 2px; margin-left: 4px;
  background: var(--bg-input); border: 1px solid var(--border);
  border-radius: var(--radius-pill); padding: 3px;
}
.top-nav-btn {
  border: none; background: transparent; padding: 6px 16px;
  border-radius: var(--radius-pill); color: var(--text-secondary);
  font-size: 0.85rem; font-weight: 500; cursor: pointer;
  white-space: nowrap; transition: all 0.25s var(--spring);
}
.top-nav-btn:hover { color: var(--text-primary); }
.top-nav-btn.active { background: var(--accent); color: var(--on-accent); }

/* ============ API 接入面板 ============ */
.mono { font-family: ui-monospace, 'SF Mono', Consolas, 'Courier New', monospace; }
.code-box {
  background: var(--bg-input); border: 1px solid var(--border);
  border-radius: 12px; padding: 12px 14px;
  font-family: ui-monospace, 'SF Mono', Consolas, monospace;
  font-size: 0.85rem; line-height: 1.7; overflow-x: auto;
  color: var(--text-primary); word-break: break-all;
}
.code-small { font-size: 0.8rem; margin-top: 8px; }
.chip-wrap { display: flex; flex-wrap: wrap; gap: 8px; }
.model-chip {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--bg-input); border: 1px solid var(--border);
  border-radius: 18px; padding: 6px 12px;
  font-size: 0.83rem; cursor: pointer;
  transition: all 0.25s var(--spring);
}
.model-chip:hover { border-color: var(--accent); background: var(--accent-soft); transform: translateY(-1px); }
.chip-copy { font-size: 0.72rem; color: var(--text-muted); }
.api-key-row {
  display: flex; justify-content: space-between; align-items: center;
  gap: 14px; padding: 12px 2px; border-bottom: 1px solid var(--u-border-soft);
  flex-wrap: wrap;
}
.api-key-row:last-child { border-bottom: none; }
.ak-left { min-width: 0; }
.ak-name { font-size: 0.92rem; font-weight: 600; color: var(--u-head); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ak-meta { font-size: 0.78rem; color: var(--u-faint); margin-top: 3px; }
.key-badge { font-size: 0.72rem; font-weight: 600; padding: 2px 9px; border-radius: 20px; }
.key-badge.ok { background: rgba(48, 164, 108, 0.14); color: var(--success); }
.key-badge.warn { background: rgba(245, 166, 35, 0.14); color: var(--warning); }
.key-badge.bad { background: rgba(229, 72, 77, 0.14); color: var(--danger); }
.ex-block { margin-bottom: 14px; }
.ex-head {
  display: flex; justify-content: space-between; align-items: center;
  font-size: 0.86rem; font-weight: 600; color: var(--u-head); gap: 10px;
}
.copy-btn {
  border: 1px solid var(--border); background: var(--bg-input);
  color: var(--text-secondary); border-radius: 8px;
  padding: 3px 12px; font-size: 0.75rem; cursor: pointer;
  transition: all 0.2s var(--ease-out); flex-shrink: 0;
}
.copy-btn:hover { border-color: var(--accent); color: var(--accent); }

@media (max-width: 768px) {
  .top-nav { margin-left: 8px; }
  .top-nav-btn { padding: 5px 10px; font-size: 0.8rem; }
}

/* ── 全局公告（强制阅读） ── */
.ann-sheet { padding: 22px; }
.ann-sheet .modal-header { margin-bottom: 12px; }
.ann-body {
  color: var(--text-primary);
  line-height: 1.85;
  font-size: 0.95rem;
  max-height: 46vh;
  overflow-y: auto;
  margin-bottom: 14px;
  word-break: break-word;
}
.ann-body p { margin: 0 0 10px; }
.ann-body h1, .ann-body h2, .ann-body h3 { margin: 14px 0 8px; }
.ann-body ul, .ann-body ol { padding-left: 1.4em; margin: 0 0 10px; }
.ann-body a { color: var(--accent); }
.ann-body code {
  background: var(--bg-input); border-radius: 4px; padding: 1px 5px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.86em;
}
.ann-body pre {
  background: var(--bg-input); border: 1px solid var(--border);
  border-radius: 8px; padding: 10px 12px; overflow-x: auto; margin: 0 0 10px;
}
.ann-timer {
  color: var(--text-tertiary, var(--text-secondary));
  font-size: 0.8rem; margin-bottom: 12px;
}
#ann-confirm:disabled { opacity: 0.55; cursor: not-allowed; }

/* 公告状态条（后台设置页） */
.ann-state {
  margin: 4px 0 0;
  padding: 9px 12px;
  border-radius: 10px;
  font-size: 0.8rem;
  line-height: 1.5;
}
.ann-state.on {
  background: rgba(48, 164, 108, 0.10);
  color: var(--success);
  border: 1px solid rgba(48, 164, 108, 0.22);
}
.ann-state.off {
  background: rgba(180, 190, 205, 0.08);
  color: var(--text-secondary);
  border: 1px solid var(--border);
}



/* ============================================================
   MaxMind 登录/注册页 — 左侧黑白极简（与官网风格一致，跟随主题变量）
   ============================================================ */
.auth-screen.mx-auth {
  background: var(--bg-body);
}
.auth-screen.mx-auth .auth-hero {
  background: var(--bg-body);
  border-right: 1px solid var(--border);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.auth-screen.mx-auth .auth-panel { background: transparent; }

.mx-inner {
  max-width: 500px;
  display: flex; flex-direction: column;
  align-items: flex-start;
  text-align: left;
}
.mx-brand { display: flex; align-items: center; gap: 12px; margin-bottom: 34px; }
.mx-word { color: var(--text-primary); font-size: 1.2rem; font-weight: 600; letter-spacing: -0.01em; }
.mx-tag {
  color: var(--text-muted); font-size: 0.62rem; letter-spacing: 0.3em;
  text-transform: uppercase; margin-left: 6px; padding-top: 2px;
}
.mx-title {
  color: var(--text-primary);
  font-size: clamp(1.9rem, 3.4vw, 2.9rem);
  font-weight: 600; letter-spacing: -0.03em; line-height: 1.18;
  margin-bottom: 24px;
}
.mx-desc {
  color: var(--text-secondary); font-size: 0.98rem; line-height: 1.9;
  margin-bottom: 42px; max-width: 420px;
}
.mx-list {
  list-style: none; margin: 0 0 44px; padding: 26px 0 0;
  border-top: 1px solid var(--border);
  width: 100%;
  display: flex; flex-direction: column; gap: 18px;
}
.mx-list li {
  display: flex; align-items: baseline; gap: 16px;
  color: var(--text-secondary); font-size: 0.9rem;
}
.mx-list li span {
  flex-shrink: 0; width: 70px;
  color: var(--text-primary); font-size: 0.78rem; letter-spacing: 0.02em;
  font-family: ui-monospace, 'SF Mono', Consolas, monospace;
}
.mx-back {
  color: var(--text-muted); font-size: 0.84rem;
  display: inline-flex; align-items: center; gap: 6px;
  transition: color 0.2s ease;
}
.mx-back:hover { color: var(--text-primary); }

@media (max-width: 768px) {
  .auth-screen.mx-auth { display: flex; }
  .auth-screen.mx-auth .auth-hero { display: none; }
  .auth-screen.mx-auth .auth-panel { width: 100%; }
}

/* ============ 模型实时状态（API 接入页 / 后台） ============ */
.status-dot.disabled { background: var(--text-muted); opacity: 0.6; box-shadow: none; }
.status-dot.check { background: var(--warning); }
.model-status-list { display: flex; flex-direction: column; }
.model-status-row {
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
  padding: 10px 2px; border-bottom: 1px solid var(--u-border-soft); flex-wrap: wrap;
}
.model-status-row:last-child { border-bottom: none; }
.model-status-row:hover { background: var(--u-border-soft); }
.msr-left { display: flex; align-items: center; gap: 8px; min-width: 0; flex: 1 1 200px; }
.msr-id { font-weight: 600; color: var(--u-head); cursor: pointer; font-size: 0.85rem; }
.msr-name {
  font-size: 0.78rem; color: var(--u-faint); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; max-width: 240px;
}
.msr-right { display: flex; align-items: center; gap: 10px; }
.msr-state { font-size: 0.76rem; font-weight: 600; max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msr-state.ok { color: var(--success); }
.msr-state.err { color: var(--danger); }
.msr-state.warn { color: var(--warning); }
.msr-state.off { color: var(--text-muted); }
.disabled-note { color: var(--warning); }

/* ============ 后台管理 · 手机端适配 ============ */
@media (max-width: 768px) {
  /* 模型/用户行：信息区占满整行，按钮下移一行并允许换行，
     避免按钮把文字区挤到只剩几个像素宽 → 一字一行 */
  .model-item, .user-item {
    flex-direction: column;
    align-items: flex-start;
  }
  .model-item-info, .user-item-info {
    width: 100%;
    margin-right: 0;
  }
  .model-item-meta, .user-item-meta {
    overflow-wrap: anywhere; /* 长 ID/URL 正常断行，而不是一字一行 */
  }
  .item-actions {
    width: 100%;
    flex-wrap: wrap;
    justify-content: flex-end;
    margin-top: 10px;
  }
  .default-limits-grid { grid-template-columns: 1fr; }   /* 三格限额在手机上变一列 */
  .admin-body-scroll { overflow-x: hidden; }
}

/* ============ 很窄的竖屏手机（放在最后确保覆盖前面的通用规则） ============ */
@media (max-width: 400px) {
  .top-nav-btn { padding: 5px 9px; font-size: 0.78rem; }
  .page-content { padding: 14px 10px 26px; }
  .chat-welcome { min-height: calc(100dvh - var(--header-height) - 170px); }
  .model-switch { max-width: 62%; padding: 5px 10px; font-size: 0.75rem; }
  .chat-welcome-greeting { font-size: 1.5rem; }
}

/* ============ 浅色模式适配：输入区/按钮/模型选择等原硬编码深色组件跟随白色主题 ============ */
[data-theme="light"] .model-switch {
  background: #eef0f2; border: 1px solid rgba(0, 0, 0, 0.12); color: #4a4f55;
}
[data-theme="light"] .model-switch:hover { border-color: rgba(0, 0, 0, 0.28); color: #0a0b0d; }
[data-theme="light"] .input-wrapper {
  background: #ffffff; border: 1px solid rgba(0, 0, 0, 0.10);
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
}
[data-theme="light"] .input-wrapper:focus-within { border-color: rgba(0, 0, 0, 0.35); }
[data-theme="light"] .chat-textarea { color: #1a1d21; }
[data-theme="light"] .chat-textarea::placeholder { color: #9aa0a6; }
[data-theme="light"] .send-btn,
[data-theme="light"] .stop-btn { background: #e7e9ec; color: #4a4f55; }
[data-theme="light"] .send-btn:hover,
[data-theme="light"] .stop-btn:hover { background: #d9dce0; }
[data-theme="light"] .send-btn.active { background: #0a0b0d; color: #ffffff; }
[data-theme="light"] .send-btn.active:hover { background: #2a2d31; }

/* ============================================================
   升级会员页（.up-*）—— 全 iOS 风（apple-ui ultra 档）
   三条约束，和站内其它页有意区分：
     1. 内容面一律【实心】，不用 backdrop-filter。
        Liquid Glass 只属于导航/浮层（底部悬浮条用了，卡片没用）。
     2. 全页只有一个强调色（系统蓝），只出现在「推荐」标记和主按钮上。
     3. 一个档位一张卡，卡间留 14px，卡内 26px —— 靠留白分层，不靠分割线。
   ============================================================ */
:root {
  --up-accent: #007aff;
  --up-accent-soft: rgba(0, 122, 255, 0.10);
  --up-accent-line: rgba(0, 122, 255, 0.32);
  /* 卡片面：实心但带一点透明，让背后的光斑隐约透出来（高级感来源）。
     刻意【不】加 backdrop-filter —— 卡片多又在滚动，逐帧模糊会卡；
     而且 Liquid Glass 本来也不该用在内容面上。 */
  --up-surface: rgba(255, 255, 255, 0.75);
  /* 吸左首列必须完全不透明，否则横滑时下面的字会透上来；这个色是把上面的
     半透面叠在页面底色上取的等效实色，肉眼看和卡片一致。 */
  --up-surface-solid: #fcfcfd;
  --up-hairline: rgba(60, 60, 67, 0.16);
  --up-dim: #6b6f76;
}
[data-theme="dark"] {
  --up-accent: #0a84ff;                 /* 深色下的强调色更亮、略降饱和 */
  --up-accent-soft: rgba(10, 132, 255, 0.16);
  --up-accent-line: rgba(10, 132, 255, 0.42);
  --up-surface: rgba(24, 24, 29, 0.72);
  --up-surface-solid: #0f0f13;          /* 叠在黑底上的等效实色 */
  --up-hairline: rgba(235, 235, 245, 0.14);
  --up-dim: #8e8e93;
}

.up-page { display: flex; flex-direction: column; gap: 42px; padding-bottom: 112px; }

/* ---- 标题区 ---- */
.up-hero { padding: 4px 4px 0; }
.up-hero-top { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
/* 34pt 大标题：只有定价页用（站内其它页是 27px）。
   定价页是准 landing 页，标题大一号是刻意的，不是漏改。 */
.up-hero-title { font-size: 2.125rem; line-height: 1.25; font-weight: 700; letter-spacing: 0.02em; color: var(--text-primary); }
.up-hero-sub { font-size: 1.0625rem; line-height: 1.7; color: var(--u-muted); margin-top: 12px; max-width: 44ch; }

.up-pill {
  display: inline-flex; align-items: center; height: 32px; padding: 0 14px;
  border-radius: var(--radius-pill); font-size: 0.8125rem; font-weight: 600;
  background: var(--up-accent-soft); color: var(--up-accent);
  border: 1px solid var(--up-accent-line); white-space: nowrap;
}

/* ---- 计费周期：胶囊分段控件 ---- */
.up-cycle {
  display: inline-flex; gap: 2px; align-self: flex-start;
  background: var(--bg-input); border: 1px solid var(--border);
  border-radius: var(--radius-pill); padding: 4px;
}
.up-cycle-btn {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 42px; padding: 0 22px; border-radius: var(--radius-pill);
  background: none; border: none; cursor: pointer;
  color: var(--u-muted); font-size: 0.9375rem; font-weight: 500;
  transition: background 0.25s var(--ease-out), color 0.25s var(--ease-out), transform 0.3s var(--spring);
}
.up-cycle-btn:hover { color: var(--text-primary); }
.up-cycle-btn:active { transform: scale(0.97); }
.up-cycle-btn.active { background: var(--bg-card); color: var(--text-primary); font-weight: 600; box-shadow: var(--shadow-sm); }
.up-cycle-save {
  font-size: 0.6875rem; font-weight: 600; padding: 2px 8px; border-radius: var(--radius-pill);
  background: var(--up-accent-soft); color: var(--up-accent);
}
.up-cycle-note { font-size: 0.8125rem; color: var(--up-dim); padding: 0 6px; }

/* ---- 板块：板块之间才是主要留白 ---- */
/* 入场只用透明度：uiIn 带 transform，fill:both 会把每个板块长期留在
   独立合成层上，滚动时层与层之间差一帧 → 文字和它的卡片看着不同步。 */
@keyframes upFadeIn { from { opacity: 0; } to { opacity: 1; } }
.up-block { display: flex; flex-direction: column; gap: 16px; animation: upFadeIn 0.45s var(--ease-out) backwards; }
.up-block:nth-of-type(2) { animation-delay: 0.04s; }
.up-block:nth-of-type(3) { animation-delay: 0.08s; }
.up-block:nth-of-type(4) { animation-delay: 0.12s; }
.up-block:nth-of-type(5) { animation-delay: 0.16s; }
.up-block-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; padding: 0 6px; }
.up-block-title { font-size: 1.375rem; font-weight: 600; letter-spacing: -0.02em; color: var(--text-primary); }
.up-block-desc { font-size: 0.9375rem; color: var(--up-dim); }
.up-block-note { font-size: 0.8125rem; line-height: 1.75; color: var(--up-dim); padding: 0 6px; }

/* ---- 档位卡片：一张卡一个档位，靠卡间距分层 ---- */
.up-tiers { display: flex; flex-direction: column; gap: 14px; }
.up-tier {
  position: relative; width: 100%; display: grid; align-items: start;
  grid-template-columns: auto minmax(0, 1fr) auto; gap: 18px;
  min-height: 44px; padding: 26px 24px;
  background: var(--up-surface); border: 1px solid var(--border);
  border-radius: 20px; box-shadow: var(--u-shadow);
  cursor: pointer; text-align: left; color: inherit;
  transition: background 0.22s var(--ease-out), border-color 0.22s var(--ease-out), transform 0.3s var(--spring);
}
.up-tier:active { transform: scale(0.99); }
.up-tier:hover { border-color: var(--up-hairline); }
.up-tier.is-selected {
  background: var(--up-surface);
  background-image: linear-gradient(var(--up-accent-soft), var(--up-accent-soft));
  border-color: var(--up-accent-line);
}

/* 单选圆点 */
.up-radio {
  width: 22px; height: 22px; border-radius: 50%; flex: none; margin-top: 2px;
  border: 1.5px solid var(--up-hairline); position: relative;
  transition: border-color 0.22s var(--ease-out), background 0.22s var(--ease-out);
}
.up-tier.is-selected .up-radio { border-color: var(--up-accent); background: var(--up-accent); }
.up-tier.is-selected .up-radio::after {
  content: ''; position: absolute; inset: 0; margin: auto;
  width: 8px; height: 8px; border-radius: 50%; background: #fff;
}

.up-tier-body { display: flex; flex-direction: column; gap: 9px; min-width: 0; }
.up-tier-head { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.up-tier-name { font-size: 1.125rem; font-weight: 600; letter-spacing: -0.01em; color: var(--text-primary); }
.up-tier-name b { font-weight: 700; color: var(--up-accent); margin-left: 4px; letter-spacing: 0; }
.up-hot {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 0.6875rem; font-weight: 600; padding: 3px 9px; border-radius: var(--radius-pill);
  background: var(--up-accent); color: #fff;
}
.up-cur {
  font-size: 0.6875rem; font-weight: 600; padding: 3px 9px; border-radius: var(--radius-pill);
  background: var(--bg-hover); color: var(--u-muted); border: 1px solid var(--border);
}
/* 额度那行是这个档位的主角，给它字号和颜色权重 */
.up-tier-quota { font-size: 1.0625rem; line-height: 1.5; color: var(--text-primary); }
.up-tier-quota em { font-style: normal; color: var(--up-dim); font-size: 0.9375rem; }
.up-tier-caps { font-size: 0.875rem; line-height: 1.7; color: var(--up-dim); overflow-wrap: break-word; }

.up-tier-price { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; text-align: right; padding-top: 2px; }
.up-price-num { font-size: 1.5rem; font-weight: 650; letter-spacing: -0.02em; color: var(--text-primary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.up-price-per { font-size: 0.8125rem; color: var(--up-dim); white-space: nowrap; }

/* ---- 「所有档位均已包含」：这里才是真正的分组列表 ---- */
.up-list {
  background: var(--up-surface); border: 1px solid var(--border);
  border-radius: 20px; box-shadow: var(--u-shadow); padding: 6px;
}
.up-common-row {
  display: flex; align-items: flex-start; gap: 13px; padding: 19px 18px;
  font-size: 1.0625rem; line-height: 1.65; color: var(--text-primary);
}
.up-common-row + .up-common-row { border-top: 1px solid var(--up-hairline); }
.up-check { flex: none; color: var(--up-accent); margin-top: 5px; display: inline-flex; }

/* ---- 详细对比表 ---- */
.up-matrix-wrap {
  background: var(--up-surface); border: 1px solid var(--border);
  border-radius: 20px; box-shadow: var(--u-shadow);
  overflow-x: auto; padding: 6px;
}
.up-matrix { border-collapse: separate; border-spacing: 0; width: 100%; min-width: 720px; }
.up-matrix th, .up-matrix td {
  padding: 17px 20px; font-size: 0.9375rem; text-align: center; white-space: nowrap;
  border-bottom: 1px solid var(--up-hairline); font-weight: 400; color: var(--text-primary);
}
.up-matrix thead th { font-weight: 600; color: var(--text-primary); font-size: 1rem; padding-top: 22px; }
.up-matrix tbody tr:last-child th, .up-matrix tbody tr:last-child td { border-bottom: none; }
/* 首列吸左，横向滚动时行名不跑掉 */
/* 吸左的首列：要显式提升到合成层，否则横向滑动时它的底色会晚一帧跟上
   文字，看起来像文字浮出了自己的框；分割线用 border 而不是 box-shadow，
   阴影会强制重绘，更卡。 */
.up-matrix .up-mx-rowhead {
  position: sticky; left: 0; z-index: 2; text-align: left;
  background: var(--up-surface-solid); color: var(--up-dim); font-size: 0.9375rem;
  border-right: 1px solid var(--up-hairline);
  will-change: transform;
}
.up-matrix .up-mx-bool { color: var(--up-accent); font-weight: 600; }

.up-note { font-size: 0.8125rem; line-height: 1.7; color: var(--up-dim); text-align: center; padding: 0 12px; }

/* ---- 底部悬浮条（这里是「导航层」，用玻璃；内容卡片没用） ----
   ⚠️ 这里的入场动画只能是「纯透明度」，不能复用 uiIn。
   悬浮条靠 transform: translateX(-50%) 做水平居中，而 uiIn 的关键帧里带
   transform —— animation-fill-mode: both 会让最终帧的 `transform: none`
   永久盖掉那句居中，于是 left:50% 变成「左边缘落在屏幕中央」，
   整条往右偏半个宽度，手机上右半边的购买按钮直接被推出屏幕外。 */
@keyframes upDockIn { from { opacity: 0; } to { opacity: 1; } }
.up-dock {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: max(18px, env(safe-area-inset-bottom, 0px));
  width: min(calc(100% - 32px), var(--content-max-width));
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 12px 12px 12px 24px; border-radius: var(--radius-pill);
  /* 全页唯一的毛玻璃：它属于「导航 / 浮层」层，正是 Liquid Glass 该用的地方。
     代价是它 position:fixed，滚动时每帧都要重算背景模糊；哪天在低端机上
     觉得它拖后腿，把下面两行 backdrop-filter 删掉即可退回不透明。 */
  background: var(--bg-card);
  border: 1px solid var(--border);
  backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
  box-shadow: var(--shadow-lg);
  animation: upDockIn 0.4s var(--ease-out) both;
  z-index: 40;
}
.up-dock-info { min-width: 0; }
.up-dock-name { font-size: 1rem; font-weight: 600; color: var(--text-primary); }
.up-dock-price { font-size: 0.8125rem; color: var(--up-dim); font-variant-numeric: tabular-nums; margin-top: 2px; }
.up-dock-cta {
  flex: none; min-height: 46px; padding: 0 30px; border: none; cursor: pointer;
  border-radius: var(--radius-pill); background: var(--up-accent); color: #fff;
  font-size: 1rem; font-weight: 600;
  transition: transform 0.3s var(--spring), opacity 0.2s var(--ease-out);
}
.up-dock-cta:hover { opacity: 0.9; }
.up-dock-cta:active { transform: scale(0.96); }
.up-dock-cta.is-quiet { background: var(--bg-input); color: var(--text-primary); border: 1px solid var(--border); }
.up-dock-cta.is-disabled { background: var(--bg-input); color: var(--up-dim); cursor: default; }
.up-dock-cta.is-disabled:hover { opacity: 1; }
.up-dock-cta.is-disabled:active { transform: none; }

/* ---- 下单成功弹层 ---- */
.up-done { text-align: center; padding: 14px 6px 4px; }
.up-done-mark {
  width: 64px; height: 64px; margin: 0 auto 18px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--up-accent-soft); color: var(--up-accent);
}
.up-done-mark svg { width: 30px; height: 30px; }
.up-done h3 { font-size: 1.25rem; font-weight: 600; margin-bottom: 8px; }
.up-done-price { font-size: 1rem; color: var(--up-accent); font-weight: 600; margin-bottom: 16px; }
.up-done-desc { font-size: 0.9375rem; line-height: 1.8; color: var(--u-muted); margin-bottom: 24px; }
.up-done-desc b { color: var(--text-primary); }
.up-done-btn { width: 100%; min-height: 46px; }
/* 审核未通过：同一套版式换个语义色，别让用户以为「通过」了 */
.up-done-mark.is-fail { background: rgba(220, 90, 70, 0.12); color: #d9574a; }

/* ---- 购买申请：待审状态条 ----------------------------------------
   审核是异步的，用户点完就没下文了 —— 这条常驻在 hero 下面，
   告诉他「已经交上去了、正在审」，顺便把「撤销」放在同一个位置。 */
.up-req {
  display: flex; align-items: center; gap: 12px;
  margin-top: 18px; padding: 13px 16px;
  border: 1px solid var(--border); border-radius: 14px;
  background: var(--up-card, transparent);
}
.up-req-icon {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--up-accent-soft); color: var(--up-accent);
}
.up-req-icon svg { width: 16px; height: 16px; }
.up-req-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
.up-req-title { font-size: 0.9375rem; font-weight: 600; color: var(--text-primary); }
.up-req-desc { font-size: 0.8125rem; line-height: 1.55; color: var(--u-muted); }
.up-req-cancel {
  flex: 0 0 auto; padding: 8px 14px; border-radius: 9px; cursor: pointer;
  border: 1px solid var(--border); background: transparent;
  color: var(--u-muted); font-size: 0.8125rem; font-family: inherit;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.up-req-cancel:hover { color: var(--text-primary); border-color: var(--u-muted); }

/* ---- 订阅到期状态条 --------------------------------------------------
   只有两种时刻会出现：已到期、3 天内到期（见 upgrade.js subBannerHtml）。
   复用 .up-req 的骨架，只换语义色 —— 布局永远一致，用户不必重新学一个组件。
   无入场动画：它随页面首帧一起出现，给一个已经在那儿的东西加淡入只会显得迟滞。 */
.up-sub .up-req-icon { background: rgba(176, 96, 0, 0.14); color: var(--warning); }
.up-sub .up-req-title { color: var(--warning); }
.up-sub.is-expired { border-color: rgba(217, 48, 37, 0.35); }
.up-sub.is-expired .up-req-icon { background: rgba(217, 48, 37, 0.14); color: var(--danger); }
.up-sub.is-expired .up-req-title { color: var(--danger); }

/* ---- 购买申请弹窗 ---- */
.up-req-summary {
  border: 1px solid var(--border); border-radius: 12px;
  padding: 4px 14px; margin-bottom: 16px;
}
.up-req-row {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 10px 0; font-size: 0.875rem; color: var(--u-muted);
  border-bottom: 1px solid var(--border);
}
.up-req-row:last-child { border-bottom: none; }
.up-req-row b { color: var(--text-primary); font-weight: 600; text-align: right; }
.up-req-tip { font-size: 0.8125rem; line-height: 1.65; color: var(--up-dim, var(--u-muted)); margin-bottom: 16px; }
.up-req-warn {
  font-size: 0.8125rem; line-height: 1.7; color: #c8901f;
  background: rgba(200, 144, 31, 0.1); border-radius: 10px;
  padding: 10px 12px; margin-bottom: 14px;
}
.up-req-warn b { color: var(--text-primary); }

/* ---- 后台：购买申请审核 ---- */
.admin-tab-badge {
  display: inline-block; margin-left: 6px; padding: 1px 6px;
  border-radius: 999px; font-size: 0.6875rem; font-weight: 600; line-height: 1.5;
  background: var(--danger, #d9574a); color: #fff;
}
.admin-tab.active .admin-tab-badge { background: rgba(255, 255, 255, 0.28); }
.pr-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.pr-tabs { display: flex; gap: 8px; flex-wrap: wrap; }
.pr-filter {
  padding: 7px 14px; border-radius: 9px; cursor: pointer; font-family: inherit;
  border: 1px solid var(--border); background: transparent;
  color: var(--u-muted, var(--text-muted)); font-size: 0.8125rem; transition: all 0.15s ease;
}
.pr-filter:hover { color: var(--text-primary); }
.pr-filter.active { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.pr-filter em { font-style: normal; font-weight: 700; }
.pr-poll { font-size: 0.75rem; color: var(--text-muted); }
.pr-list { display: grid; gap: 14px; }
.pr-card { border: 1px solid var(--border); border-radius: 14px; padding: 16px 18px; }
.pr-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.pr-user { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 0.9375rem; }
.pr-user b { color: var(--text-primary); }
.pr-curplan { font-size: 0.75rem; color: var(--text-muted); }
.pr-flag { font-size: 0.6875rem; padding: 1px 7px; border-radius: 999px; }
.pr-flag.is-warn { background: rgba(200, 144, 31, 0.14); color: #c8901f; }
.pr-pill { font-size: 0.75rem; padding: 3px 10px; border-radius: 999px; white-space: nowrap; }
.pr-pill.is-pending { background: rgba(200, 144, 31, 0.14); color: #c8901f; }
.pr-pill.is-approved { background: rgba(24, 128, 56, 0.14); color: #1f8b4c; }
.pr-pill.is-rejected { background: rgba(217, 87, 74, 0.14); color: #d9574a; }
.pr-pill.is-cancelled { background: rgba(128, 128, 128, 0.14); color: var(--text-muted); }
.pr-want { display: flex; align-items: baseline; gap: 10px; margin: 12px 0 4px; flex-wrap: wrap; }
.pr-want-plan { font-size: 1.125rem; font-weight: 700; color: var(--text-primary); }
.pr-want-meta { font-size: 0.8125rem; color: var(--text-muted); }
.pr-note { font-size: 0.8125rem; line-height: 1.65; color: var(--u-muted, var(--text-muted)); margin-top: 8px; }
.pr-limits { margin-top: 12px; border-top: 1px solid var(--border); padding-top: 10px; }
.pr-lim-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 3px 0; font-size: 0.8125rem; color: var(--text-muted); }
.pr-lim-row b { color: var(--text-primary); font-weight: 600; font-variant-numeric: tabular-nums; }
.pr-warn { margin-top: 10px; font-size: 0.8125rem; line-height: 1.7; color: #c8901f; background: rgba(200, 144, 31, 0.1); border-radius: 10px; padding: 9px 12px; }
.pr-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-top: 14px; }
.pr-time, .pr-reviewnote { font-size: 0.75rem; color: var(--text-muted); }
.pr-modal-sub { font-size: 0.875rem; color: var(--u-muted, var(--text-muted)); margin-bottom: 16px; }
.pr-modal-sub b { color: var(--text-primary); }
.pr-radio { display: flex; align-items: flex-start; gap: 9px; padding: 9px 0; font-size: 0.8125rem; line-height: 1.6; color: var(--text-muted); cursor: pointer; }
.pr-radio input { margin-top: 3px; flex: 0 0 auto; }
.pr-radio b { color: var(--text-primary); font-weight: 600; }
.pr-radio span { min-width: 0; }

/* ---- 窄屏：价格挪到正文下面，正文拿满宽度 ---- */
@media (max-width: 520px) {
  .up-hero-title { font-size: 1.75rem; }
  .up-hero-sub { font-size: 1rem; }
  .up-page { gap: 34px; }
  .up-tier { grid-template-columns: auto minmax(0, 1fr); gap: 15px; padding: 22px 18px; }
  .up-tier-price {
    grid-column: 2; flex-direction: row; align-items: baseline; gap: 8px;
    text-align: left; padding-top: 0;
  }
  .up-dock { padding-left: 18px; }
  .up-dock-cta { padding: 0 22px; }
  /* 手机：状态条改竖排，撤销按钮自己占一行，别把文字挤成一列字 */
  .up-req { flex-wrap: wrap; padding: 12px 14px; }
  .up-req-body { flex: 1 1 100%; order: 2; }
  .up-req-icon { order: 1; }
  .up-req-cancel { order: 3; flex: 1 1 100%; margin-top: 4px; }
  .pr-card { padding: 14px; }
  .pr-lim-row { flex-direction: column; align-items: flex-start; gap: 2px; }
  .pr-foot .item-actions { width: 100%; }
}

/* ---- 无障碍：跟随系统开关，不硬编码透明度糊弄 ---- */
@media (prefers-reduced-motion: reduce) {
  .up-block, .up-dock { animation: none; }
  .up-tier, .up-cycle-btn, .up-dock-cta { transition: none; }
  .up-tier:active, .up-cycle-btn:active, .up-dock-cta:active { transform: none; }
}
/* 系统开了「降低透明度」就全部退回实色 —— 不硬编码透明度糊弄用户 */
@media (prefers-reduced-transparency: reduce) {
  .up-tier, .up-list, .up-matrix-wrap { background: var(--up-surface-solid); }
  .up-tier.is-selected { background-image: none; }
  .up-dock { background: var(--bg-card); -webkit-backdrop-filter: none; backdrop-filter: none; }
}
@media (prefers-contrast: more) {
  .up-tier, .up-list, .up-matrix-wrap { border-color: currentColor; }
  .up-tier-caps, .up-block-desc, .up-dock-price, .up-cycle-note { color: var(--text-primary); }
}

/* ---- 设置页里的档位小徽标 ---- */
.plan-badge {
  display: inline-flex; align-items: center; height: 22px; padding: 0 9px;
  border-radius: var(--radius-pill); font-size: 0.6875rem; font-weight: 600;
  background: var(--up-accent-soft); color: var(--up-accent);
  border: 1px solid var(--up-accent-line); vertical-align: middle;
}


/* ── API Key 页顶部的两个跳转卡（文档 / 快速上手） ────────────────────── */
.api-jump {
  display: grid;
  /* 用 min() 兜住窄屏：320px 老机型也不会溢出。
     auto-fit + minmax 保证宽屏两列、窄屏自动堆成一列。 */
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
  gap: 10px;
  margin-bottom: 16px;
}
.api-jump-card {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 15px;
  border-radius: 14px;
  border: 1px solid var(--border, rgba(120, 120, 128, .28));
  background: var(--bg-card, rgba(120, 120, 128, .08));
  color: inherit; text-decoration: none;
  transition: transform .18s cubic-bezier(.23, 1, .32, 1),
              background .18s cubic-bezier(.23, 1, .32, 1),
              border-color .18s cubic-bezier(.23, 1, .32, 1);
}
.api-jump-card:hover { transform: translateY(-1px); }
.api-jump-card:active { transform: scale(.985); }
.api-jump-icon {
  flex: none; width: 38px; height: 38px; border-radius: 11px;
  display: grid; place-items: center;
  background: rgba(120, 120, 128, .16);
  color: var(--text-primary, inherit);
}
.api-jump-main { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 2px; }
/* 标题不许被压成两行：用省略号收尾，宁可截断也不要「一行变两行」 */
.api-jump-title {
  font-size: .9375rem; font-weight: 620; letter-spacing: -.015rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.api-jump-desc {
  font-size: .75rem; line-height: 1.45;
  color: var(--text-secondary, rgba(235, 235, 245, .6));
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.api-jump-go {
  flex: none; font-size: 1.25rem; line-height: 1;
  color: var(--text-tertiary, rgba(235, 235, 245, .3));
}

/* ============================================================================
   ★ 说明句里的 <b>：不加粗、跟正文同色（2026-09-16 用户要求，别再改回去）
   ----------------------------------------------------------------------------
   用户原话：「我是说这种解释词，[开启后本账号的 API 调用不再受下行限速约束…]，
             像这种词，这里面就有加粗的文字，它不需要加粗，然后把它变成灰色就行了。
             并不是网站里的所有东西的加粗都给我取消」。

   所以这里**只针对「说明/解释性文字」这一个语境**：
     · 里面的 <b> / <strong> 既不加粗，也不再用高亮色，直接继承所在段落的颜色
       （这些段落本来就是灰的：.u-meta 用 --u-muted、.adm-hint 用 --adm-label-2…）；
     · 标题、卡片标题、按钮、数据值（.adm-kv 的右列）、徽标……**一律照旧**，不受影响。

   ⚠️ 曾经误做过一次「全站压平所有 font-weight」（css/no-bold.css），
      那是理解错了 —— 标题也跟着塌掉，整个界面失去层次。已删除，别再复活。
      判据很简单：**这个 <b> 是在一句话里当语气强调用的，还是在展示一个值？**
      是前者 → 归到下面这份名单里；是后者 → 不要动。
   ============================================================================ */
.u-meta b, .u-meta strong,
.u-sub b, .u-sub strong,
.u-count b, .u-count strong,
.speed-note b, .speed-note strong,
.up-done-desc b, .up-done-desc strong,
.up-req-warn b, .up-req-warn strong,
.pr-modal-sub b, .pr-modal-sub strong,
.adm-hint b, .adm-hint strong,
.adm-group-note b, .adm-group-note strong,
.adm-card-sub b, .adm-card-sub strong,
.adm-empty b, .adm-empty strong,
.adm-banner-body b, .adm-banner-body strong,
.adm-field-hint b, .adm-field-hint strong,
.cx-quota-meta b, .cx-quota-meta strong {
  font-weight: 400;
  color: inherit;
}
