/* =============================================================================
   链桥 ChainBridge —— 用户中心（控制台）布局
   =============================================================================
   【这一层解决什么问题】
   官网（未登录）和用户中心（已登录）是两套完全不同的信息架构：
     · 官网：顶部导航 + 长滚动介绍，目标是「让人看懂我们在卖什么」；
     · 用户中心：左侧固定菜单 + 内容区，目标是「让人快速干完一件事」。
   以前两者共用同一套顶部导航，用户登录后仍停在营销页的视觉里，
   找不到「我的密钥在哪、这条链的地址怎么复制」。本文件把用户中心单独拆出来。

   【布局方式为什么用 body 上的 grid】
   42 个页面各自有 <main> 与页脚，若每个页面再包一层 wrapper，
   改动面大且容易漏。直接让 body 变成两列 grid：
     第 1 列 = 侧栏（[data-cs-shell] 渲染出来的 <aside>）
     第 2 列 = <main> 与页脚
   页面本身无需改结构，只换导航占位符即可，风险最小。

   【硬规矩】所有色值只能引用 tokens.css 的变量，禁止硬编码十六进制色值。
   ============================================================================= */

/* ============================ ① 整体骨架 ============================== */

/* 【为什么用 padding-left + fixed，而不是 grid 两列】
   侧栏要在任何滚动位置都固定，而内容区高度不确定（有的页面一屏，有的几十屏）。
   fixed + 给 body 留出左侧空位是最不容易出错的写法：
   不需要关心 grid 行数、sticky 的包含块、以及页面里偶然出现的绝对定位元素。 */
body.cs-console {
  min-height: 100vh;
  padding-left: var(--cs-sidebar-w);
  background: var(--background);
}

body.cs-console > .cs-side {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: var(--cs-sidebar-w);
  z-index: 120;
  display: flex;
  flex-direction: column;
  background: var(--backgroundTertiary);
  border-right: 1px solid var(--divider);
  overflow: hidden;
}

/* 用户中心里内容区不再受营销页 1280px 限宽约束：
   dRPC 的控制台是满宽铺开的，限宽会让长表格被压缩到需要横向滚动。 */
body.cs-console .cs-container {
  max-width: none;
  padding: 0 28px;
}

body.cs-console main { padding: 0 0 72px; }

/* 页面顶部与底部的留白由控制台自己掌握，覆盖营销页的 56px 区块间距 */
body.cs-console .cs-section,
body.cs-console .cs-section--tight { padding-top: 20px; padding-bottom: 0; }

/* ============================ ② 侧栏 ============================== */

.cs-side__brand {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--divider);
  flex: none;
}
.cs-side__brand .cs-logo__mark { width: 28px; height: 28px; border-radius: var(--Radius-200); }
.cs-side__brand .cs-logo__text { font-size: var(--Font-size-text-200); line-height: 1.2; }
.cs-side__brand .cs-logo__text small { font-size: var(--Font-size-text-50); }

/* 账号/团队切换器：dRPC 在侧栏顶部放团队下拉，用户一眼知道「我现在在哪个组织里」 */
.cs-side__org {
  margin: 10px 12px 6px;
  padding: 8px 10px;
  display: flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--border);
  border-radius: var(--Radius-300);
  background: var(--backgroundSecondary);
  font-size: var(--Font-size-text-200);
  color: var(--textPrimary);
  cursor: pointer;
  text-align: left;
  width: calc(100% - 24px);
  font-family: inherit;
}
.cs-side__org:hover { border-color: var(--borderSecondaryWhite); }
.cs-side__org > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cs-side__org svg:last-child { margin-left: auto; flex: none; color: var(--textSecondary); }
.cs-side__org-dot {
  width: 20px; height: 20px; border-radius: var(--Radius-200); flex: none;
  display: grid; place-items: center;
  background: var(--primaryLight); color: var(--primary);
  font-family: var(--font-display); font-size: var(--Font-size-text-50); font-weight: 600;
}

.cs-side__nav {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 6px 12px 16px;
  overscroll-behavior: contain;
}

.cs-side__group {
  margin: 11px 0 3px;
  padding: 0 10px;
  font-size: var(--Font-size-text-100);
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--textSecondary);
}
.cs-side__group:first-child { margin-top: 4px; }

.cs-side__link {
  display: flex;
  align-items: center;
  gap: 9px;
  /* 侧栏一共四组十六项，加上顶部切换器与底部入口，900px 高的窗口里
     每一项都要省几像素才能一屏放下；放不下时 nav 仍可滚动，但默认不该需要滚。 */
  padding: 6px 10px;
  margin-bottom: 2px;
  border-radius: var(--Radius-300);
  color: var(--textSecondaryBright);
  font-size: var(--Font-size-text-200);
  line-height: 1.3;
  text-decoration: none;
  border: 1px solid transparent;
  transition: background .15s ease, color .15s ease;
}
.cs-side__link svg { flex: none; opacity: .85; }
.cs-side__link span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cs-side__link:hover { background: var(--backgroundSecondary); color: var(--textPrimary); }
.cs-side__link.is-active {
  background: var(--primary08);
  color: var(--primary);
  border-color: var(--primaryLight);
}
.cs-side__link.is-active svg { opacity: 1; }
/* 外链项右侧给一个小箭头，提示「点了会离开用户中心」 */
.cs-side__link--out::after {
  content: '';
  margin-left: auto;
  width: 10px; height: 10px;
  flex: none;
  background: currentColor;
  opacity: .5;
  -webkit-mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17 17 7M7 7h10v10'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17 17 7M7 7h10v10'/%3E%3C/svg%3E") center / contain no-repeat;
}

.cs-side__foot { flex: none; padding: 8px 12px 10px; border-top: 1px solid var(--divider); }

/* 侧栏底部的推广卡：dRPC 放了 "Recommend Us"，我们换成「邀请得额度」。
   没有真实活动时不要摆假的倒计时，这里给的是可验证的入口。 */
.cs-side__promo {
  display: block;
  padding: 10px 12px;
  border-radius: var(--Radius-300);
  background: var(--primary08);
  border: 1px solid var(--primaryLight);
  font-size: var(--Font-size-text-100);
  color: var(--textPrimary);
  line-height: 1.45;
}
.cs-side__promo strong { display: block; font-size: var(--Font-size-text-200); margin-bottom: 2px; }
.cs-side__promo small { color: var(--textSecondary); display: block; font-size: var(--Font-size-text-100); }

/* ============================ ③ 顶条 ============================== */

.cs-topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: var(--cs-topbar-h);
  padding: 0 28px;
  background: var(--background);
  border-bottom: 1px solid var(--divider);
}
.cs-topbar__crumb {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--Font-size-text-200);
  color: var(--textSecondary);
  min-width: 0;
}
.cs-topbar__crumb a { color: var(--textSecondary); }
.cs-topbar__crumb a:hover { color: var(--textPrimary); }
.cs-topbar__crumb strong {
  color: var(--textPrimary);
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cs-topbar__right { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.cs-topbar__right .cs-locale { margin-right: 2px; }

/* 侧栏在窄屏收起时，顶条里出现菜单按钮 */
.cs-topbar__burger {
  display: none;
  align-items: center;
  justify-content: center;
  width: 36px; height: 36px;
  border-radius: var(--Radius-300);
  border: 1px solid var(--border);
  background: transparent;
  color: var(--textPrimary);
  cursor: pointer;
  flex: none;
}

/* 顶部余额/额度提示条：dRPC 用整条黄底。我们只在真的需要提醒时出现，
   平时不占位（没有数据就不渲染这一条，避免摆一条空横幅）。 */
.cs-topbar-alert {
  position: sticky;
  top: var(--cs-topbar-h);
  z-index: 29;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 28px;
  background: var(--lightYellow);
  color: var(--textNegative);
  font-size: var(--Font-size-text-200);
  font-weight: 500;
}
/* 顶条在窄屏会变成两行（高度 52px 的假设不成立），黄条若继续按固定 top 吸附，
   会直接压在顶条上、两行字叠在一起。窄屏改为跟随文档流。 */
@media (max-width: 480px) {
  .cs-topbar-alert { position: static; top: auto; }
}
.cs-topbar-alert .cs-topbar-alert__spacer { margin-left: auto; }
.cs-topbar-alert a,
.cs-topbar-alert button {
  font-size: var(--Font-size-text-100);
  font-weight: 500;
  color: var(--textNegative);
  background: color-mix(in srgb, var(--black) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--black) 15%, transparent);
  border-radius: var(--Radius-200);
  padding: 4px 10px;
  cursor: pointer;
  text-decoration: none;
  font-family: inherit;
  white-space: nowrap;
}
.cs-topbar-alert a:hover,
.cs-topbar-alert button:hover { background: color-mix(in srgb, var(--black) 15%, transparent); }

/* 页面标题统一用 app.css 的 .cs-appbar（h1 = 24px，符合设计规范），
   这里不再另造一套页头，避免同一层级出现两种标题尺寸。 */

/* ============================ ⑤ 概览统计卡 ============================== */

/* 图2 的三张卡：左上小标签 / 大数字 / 下方小字 / 右上圆形图标 */
.cs-stat-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
  margin-bottom: 28px;
}
.cs-stat {
  position: relative;
  padding: 18px 20px;
  border-radius: var(--Radius-500);   /* G-06：卡级容器统一 16px */
  background: var(--backgroundSecondary);
  border: 1px solid var(--border);
  min-width: 0;
}
.cs-stat__label {
  display: block;
  /* G-07：指标名是要读的字，10px 只允许装饰用途（规范 §1.2） */
  font-size: var(--Font-size-text-100);
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--textSecondary);
  margin-bottom: 8px;
}
.cs-stat__value {
  display: block;
  font-family: var(--font-display);
  /* G-07：三处「大数字」原来 26/28/30px 各不相同，统一为 24→28 的 clamp */
  font-size: clamp(var(--Font-size-header-100), 2.2vw, var(--Font-size-header-200));
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  overflow-wrap: anywhere;
}
.cs-stat__sub { display: block; margin-top: 6px; font-size: var(--Font-size-text-100); color: var(--textSecondary); line-height: 1.45; }
.cs-stat__icon {
  position: absolute;
  top: 16px; right: 16px;
  width: 34px; height: 34px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--backgroundTertiary);
  color: var(--textSecondaryBright);
}
.cs-stat--primary .cs-stat__icon { background: var(--primaryLight); color: var(--primary); }
.cs-stat--warn .cs-stat__icon { background: var(--warningTertiary); color: var(--warning); }
.cs-stat--danger .cs-stat__icon { background: var(--errorTertiary); color: var(--error); }

/* ============================ ⑥ 区块标题 ============================== */

.cs-panel-head {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin: 0 0 14px;
}
.cs-panel-head h2 {
  font-family: var(--font-display);
  font-size: var(--Font-size-text-500);
  font-weight: 500;
  letter-spacing: 0;
}
.cs-panel-head p { color: var(--textSecondary); font-size: var(--Font-size-text-100); margin-top: 2px; }
.cs-panel-head__actions { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }

/* 工具条：搜索框 + 筛选 + 计数，排成一行（图3 的搜索行） */
.cs-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.cs-toolbar .cs-search { flex: 1; min-width: 220px; max-width: 520px; }
.cs-toolbar__meta {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: var(--Font-size-text-100);
  color: var(--textSecondary);
  flex-wrap: wrap;
}
.cs-toolbar__dot { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.cs-toolbar__dot::before {
  content: '';
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--primary);
  flex: none;
}
.cs-toolbar__dot--off::before { background: var(--textSecondary); }

/* ============================ ⑦ 端点卡片（密钥详情页主体） ==================
   一张卡片 = 一条链的可用 RPC 地址。用户在这页只做三件事：
   ① 认出这是哪条链（真实链图标 + 链名）；② 看清能不能用（探针健康 + 区块高度）；
   ③ 把地址复制走（复制按钮必须一眼可见，不能藏成一个小图标）。
   ========================================================================= */

.cs-ep-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}
.cs-ep {
  position: relative;
  border: 1px solid var(--border);
  border-radius: var(--Radius-500);   /* G-06：卡级容器统一 16px */
  background: var(--backgroundSecondary);
  padding: 18px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
  transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
.cs-ep:hover {
  border-color: var(--borderSecondaryWhite);
  box-shadow: 0 14px 30px color-mix(in srgb, var(--black) 30%, transparent);
}
.cs-ep__head { display: flex; align-items: center; gap: 12px; min-width: 0; }

/* 只有「可能有问题」的链才在卡片左侧挂一条色条：正常链不挂，避免满屏都是颜色 */
.cs-ep--warn::before,
.cs-ep--danger::before {
  content: '';
  position: absolute;
  left: 0;
  top: 16px;
  bottom: 16px;
  width: 2px;
  border-radius: 0 2px 2px 0;
}
.cs-ep--warn::before { background: var(--lightYellow); }
.cs-ep--danger::before { background: var(--coral); }

/* 真实链图标：白底圆角方块，jpg（白底）与 png（透明）在这里看起来一致 */
.cs-ep__logo {
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: var(--Radius-300);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  /* G-17：链图标的白底是「让浅色 logo 也能看清」的功能底，取 tokens 的浅色底，
     不再写 rgba 字面量 */
  background: var(--backgroundNegative);
  border: 1px solid color-mix(in srgb, var(--black) 8%, transparent);
}
.cs-ep__logo img { width: 100%; height: 100%; object-fit: contain; display: block; }
/* 兜底：没有官方图标的链用「品牌色 + 名称首字母」，绝不显示成别的链 */
.cs-ep__logo--fallback {
  background: var(--backgroundSurface);
  color: var(--textPrimary);
  border-color: var(--border);
  font-family: var(--font-display);
  font-size: var(--Font-size-text-300);
  font-weight: 600;
  letter-spacing: 0;
}
@supports (background: color-mix(in srgb, red 10%, blue)) {
  .cs-ep__logo--fallback {
    background: color-mix(in srgb, var(--cs-brand) 22%, var(--background));
    color: color-mix(in srgb, var(--cs-brand) 72%, var(--textPrimary));
    border-color: color-mix(in srgb, var(--cs-brand) 42%, transparent);
  }
}

.cs-ep__id { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.cs-ep__name {
  font-family: var(--font-display);
  font-size: var(--Font-size-text-300);
  font-weight: 500;
  line-height: 1.25;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cs-ep__meta {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  font-size: var(--Font-size-text-100);   /* G-07：链 ID / 代币名要能认，不用 10px */
  color: var(--textSecondary);
}
.cs-ep__health {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--textSecondary);
}
.cs-ep__health--ok { background: var(--primary); box-shadow: 0 0 0 3px var(--primaryTransparent); }
.cs-ep__health--warn { background: var(--lightYellow); }
.cs-ep__health--danger { background: var(--coral); }
.cs-ep__badges { margin-left: auto; display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.cs-ep__badges .cs-badge { font-size: var(--Font-size-text-100); padding: 2px 7px; }

/* Chain ID / 原生代币 / 最新区块：窄卡片自动折行，不硬挤（118px 保证 10 位 chain_id 不被省略） */
.cs-ep__fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); gap: 10px; }
.cs-ep__field label {
  display: block;
  font-size: var(--Font-size-text-100);   /* G-07：CHAIN ID / 原生代币 / 最新区块 要能认 */
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--textSecondary);
  margin-bottom: 4px;
}
.cs-ep__field div {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-display);
  font-size: var(--Font-size-text-300);
  min-width: 0;
}
.cs-ep__field span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cs-ep__field .cs-muted { font-size: var(--Font-size-text-100); }

/* 小号复制按钮：Chain ID / 代币符号这类短值用，描边保证看得见 */
.cs-mini-copy {
  flex: none;
  width: 24px;
  height: 24px;
  border-radius: var(--Radius-200);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  background: var(--backgroundTertiary);
  color: var(--textSecondary);
  cursor: pointer;
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.cs-mini-copy:hover { color: var(--textPrimary); border-color: var(--borderSecondaryWhite); background: var(--backgroundSurface); }
.cs-mini-copy.is-copied { color: var(--primary); border-color: var(--primary); background: var(--primaryTransparent); }
.cs-mini-copy svg { width: 13px; height: 13px; }

/* 完整 RPC 地址 + 操作按钮：地址占满可用宽度，按钮排不下就换行，绝不把地址挤没 */
.cs-ep__url {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 8px 8px 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--Radius-300);
  background: var(--backgroundTertiary);
  min-width: 0;
}
.cs-ep__url code {
  flex: 1 1 200px;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: var(--Font-size-text-100);
  color: var(--textPrimaryMuted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cs-ep__urlacts { flex: none; margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }

/* 复制反馈：点一下换成对勾 +「已复制」，1.6 秒后复原 */
.cs-copy-btn__done { display: none; }
.cs-copy-btn.is-copied { background: var(--primary); border-color: var(--primary); color: var(--Content-primary_button_text); }
.cs-copy-btn.is-copied .cs-copy-btn__copy { display: none; }
.cs-copy-btn.is-copied .cs-copy-btn__done { display: inline-flex; }
.cs-mini-copy .cs-copy-btn__done { display: none; }
.cs-mini-copy.is-copied .cs-copy-btn__copy { display: none; }
.cs-mini-copy.is-copied .cs-copy-btn__done { display: inline-flex; }

/* 协议切换（HTTP / WSS）+ 网络下拉 */
.cs-ep__row { display: flex; gap: 8px; flex-wrap: wrap; }
.cs-ep__row .cs-select { flex: 1; min-width: 120px; }
.cs-seg {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--Radius-200);
  overflow: hidden;
  background: var(--backgroundTertiary);
  flex: none;
}
.cs-seg button {
  border: 0;
  background: transparent;
  color: var(--textSecondary);
  font-family: var(--font-sans);
  font-size: var(--Font-size-text-100);
  font-weight: 500;
  padding: 7px 14px;
  cursor: pointer;
  white-space: nowrap;
}
.cs-seg button[aria-pressed="true"] { background: var(--backgroundSurface); color: var(--textPrimary); }
.cs-seg button:disabled { color: var(--textSecondary); cursor: not-allowed; opacity: .55; }
.cs-seg button + button { border-left: 1px solid var(--border); }

/* 可复制地址条（.cs-urlbar）定义在 app.css 的 ⑩ 区，官网链目录与控制台共用。 */

/* 可选：把「请求头要带什么」写成一行提示，避免用户复制了地址还报 401 */
.cs-ep__hint {
  font-size: var(--Font-size-text-100);   /* G-07：一行提示是要读的 */
  color: var(--textSecondary);
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.cs-ep__hint code {
  font-family: var(--font-mono);
  font-size: var(--Font-size-text-50);
  padding: 1px 5px;
  border-radius: 4px;
  background: var(--backgroundSurface);
  color: var(--textPrimaryMuted);
}

/* ============================ ⑧ 表格容器 ============================== */

/* 【G-10】`.cs-table-wrap` 的容器外观（底色 / 圆角 / 横向滚动 / 表头）**只在
   app.css 定义一份**。这里原来也写了一份，多一个 --backgroundSecondary 底色，
   结果同一个 .cs-table 在定价页是「带底卡」、在文档页是「透明细边框」，
   外观取决于页面有没有引入本文件。本文件不再覆盖容器，只留下表内排版无关的
   业务表格（如 .billing-table 的窄屏卡片化）规则。
   → 控制台表格与营销页表格现在是同一套圆角、底色与表头样式。 */

@media (max-width: 620px) {
  .billing-table,
  .billing-table tbody { display: block; width: 100%; }
  .billing-table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }
  .billing-table tbody tr {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 12px;
    padding: 8px 12px;
    border-bottom: 1px solid var(--divider);
  }
  .billing-table tbody tr:last-child { border-bottom: 0; }
  .billing-table tbody td {
    display: block;
    min-width: 0;
    padding: 8px 0;
    border: 0;
    overflow-wrap: anywhere;
  }
  .billing-table tbody td::before {
    display: block;
    margin-bottom: 4px;
    color: var(--textSecondary);
    font-size: var(--Font-size-text-100);   /* G-07：手机端表格的字段名标签 */
    line-height: 1.4;
  }
  .billing-table tbody td:nth-child(1)::before { content: "日期 / 账单号"; }
  .billing-table tbody td:nth-child(2)::before { content: "计算单元 / 金额"; }
  .billing-table tbody td:nth-child(3)::before { content: "金额 / 状态"; }
  .billing-table tbody td:nth-child(4)::before { content: "状态 / 操作"; }
  .billing-table tbody td:nth-child(5)::before { content: "操作"; }
  .billing-table tbody td:first-child,
  .billing-table tbody td:nth-child(3) { grid-column: 1 / -1; }
  .billing-table tbody td:last-child > div,
  .billing-table tbody td:last-child .cs-row {
    display: flex;
    align-items: stretch;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
  }
  .billing-table tbody td:last-child .cs-btn {
    width: 100%;
    min-width: 0;
    min-height: 36px;
    padding: 6px 8px;
    white-space: normal;
    text-align: center;
  }
}

/* ============================ ⑨ 窄屏 ============================== */

/* 1048px 以下侧栏收进抽屉：内容区太窄时并排两栏会把表格压出横向滚动 */
@media (max-width: 1048px) {
  body.cs-console { padding-left: 0; }
  body.cs-console > .cs-side {
    width: 264px;
    z-index: 200;
    transform: translateX(-100%);
    transition: transform .22s ease;
    box-shadow: 0 0 40px rgba(0, 0, 0, .5);
  }
  body.cs-console.is-side-open > .cs-side { transform: translateX(0); }
  body.cs-console .cs-container { padding: 0 16px; }
  .cs-topbar { padding: 0 16px; }
  .cs-topbar__burger { display: inline-flex; }
  .cs-topbar-alert { padding: 10px 16px; }
}

/* 抽屉打开时的遮罩 */
.cs-side-scrim {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 190;
  background: rgba(0, 0, 0, .6);
  border: 0;
  padding: 0;
}
body.cs-console.is-side-open .cs-side-scrim { display: block; }

@media (prefers-reduced-motion: reduce) {
  body.cs-console > .cs-side { transition: none; }
}

@media (max-width: 768px) {
  .cs-stat-grid { grid-template-columns: minmax(0, 1fr); }
  .cs-ep-grid { grid-template-columns: minmax(0, 1fr); }
  .cs-page-head h1 { font-size: var(--Font-size-header-100); }
  .cs-stat__value { font-size: var(--Font-size-header-100); }
  .cs-ep__fields { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 480px) {
  .cs-topbar {
    display: grid;
    grid-template-columns: 36px minmax(0, 1fr);
    gap: 4px 10px;
    padding: 8px 12px;
  }
  .cs-topbar__burger { grid-column: 1; grid-row: 1; }
  .cs-topbar__crumb { grid-column: 2; grid-row: 1; }
  .cs-topbar__right {
    grid-column: 1 / -1;
    grid-row: 2;
    width: 100%;
    justify-content: flex-end;
  }
}

@media (min-width: 769px) and (max-width: 1180px) {
  /* 两列端卡片在中等宽度下会把地址挤成一行省略号，降为单列更好读 */
  .cs-ep-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ============================ ⑩ 尺寸变量 ============================== */

:root {
  --cs-sidebar-w: 232px;
  --cs-topbar-h: 52px;
}

/* ============================ ⑪ 项目切换器 ============================== */

/* 项目是控制台的数据边界，切换器必须一眼可见、点开就能换。
   侧栏顶部空间有限，下拉层用 fixed 的绝对定位即可（侧栏本身 fixed，不受滚动影响）。 */
.cs-side__orgwrap { position: relative; margin: 10px 12px 6px; }

.cs-side__menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 320;
  padding: 6px;
  border: 1px solid var(--border);
  border-radius: var(--Radius-300);
  background: var(--backgroundSurface);
  box-shadow: 0 18px 40px rgba(0, 0, 0, .55);
  max-height: 60vh;
  overflow-y: auto;
}
.cs-side__menu[hidden] { display: none; }

.cs-side__menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 10px;
  border: 1px solid transparent;
  border-radius: var(--Radius-200);
  background: transparent;
  color: var(--textPrimaryMuted);
  font-family: inherit;
  font-size: var(--Font-size-text-100);
  text-align: left;
  cursor: pointer;
  text-decoration: none;
}
.cs-side__menu-item:hover { background: var(--backgroundTertiary); color: var(--textPrimary); }
.cs-side__menu-item.is-active { background: var(--primary08); color: var(--primary); border-color: var(--primaryLight); }
.cs-side__menu-item svg { margin-left: auto; flex: none; }
.cs-side__menu-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
}
.cs-side__menu-meta {
  display: block;
  font-size: var(--Font-size-text-50);
  color: var(--textSecondary);
  white-space: nowrap;
}
.cs-side__menu-sep { height: 1px; margin: 6px 4px; background: var(--divider); }

/* 项目切换器里的名字过长时省略，不要把侧栏撑宽 */
.cs-side__org #csProjectName {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 侧栏内容超出视口时必须让人看见「还能往下滚」。
   全局滚动条样式在深色侧栏里对比度很低，这里单独提亮一点。 */
.cs-side__nav::-webkit-scrollbar { width: 6px; }
.cs-side__nav::-webkit-scrollbar-track { background: transparent; }
.cs-side__nav::-webkit-scrollbar-thumb { background: var(--borderSecondaryWhite); border-radius: 999px; }
.cs-side__nav { scrollbar-width: thin; }

/* ============================ ⑫ 侧滑抽屉（Top-Up） ============================== */

/* 充值走侧滑抽屉而不是居中弹窗：和 dRPC 一样从右侧推进来，
   用户还能看到后面的余额数字，知道自己是在给哪个账户充值。 */
.cs-drawer-mask {
  position: fixed;
  inset: 0;
  z-index: 260;
  background: rgba(0, 0, 0, .6);
  display: flex;
  justify-content: flex-end;
}
.cs-drawer-mask[hidden] { display: none; }

.cs-drawer {
  width: min(420px, 100vw);
  height: 100%;
  background: var(--backgroundLandingDark);
  border-left: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  box-shadow: -20px 0 60px rgba(0, 0, 0, .6);
  animation: cs-drawer-in .22s ease;
}
@keyframes cs-drawer-in { from { transform: translateX(24px); opacity: .4; } to { transform: none; opacity: 1; } }

.cs-drawer__hd {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--divider);
  flex: none;
}
.cs-drawer__hd h2 { font-family: var(--font-display); font-size: var(--Font-size-text-500); font-weight: 500; flex: 1; }
.cs-drawer__close {
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border: 1px solid var(--border);
  border-radius: var(--Radius-200);
  background: transparent;
  color: var(--textSecondary);
  cursor: pointer;
}
.cs-drawer__close:hover { color: var(--textPrimary); border-color: var(--borderSecondaryWhite); }

.cs-drawer__bd { padding: 20px; overflow-y: auto; flex: 1; }
.cs-drawer__ft { padding: 14px 20px; border-top: 1px solid var(--divider); flex: none; }

/* 充值渠道：可用 / 不可用都明确写原因，不摆一个点了没反应的按钮 */
.tu-channel {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: var(--Radius-300);
  background: var(--backgroundSecondary);
  margin-bottom: 10px;
}
.tu-channel--off { opacity: .72; }
.tu-channel__icon {
  width: 34px; height: 34px; flex: none;
  border-radius: var(--Radius-200);
  display: grid; place-items: center;
  background: var(--backgroundTertiary);
  color: var(--textSecondaryBright);
}
.tu-channel__main { min-width: 0; flex: 1; }
/* G-16：变量名少写了连字符（--FontSize-text-200），font-size 整条失效、继承父级 */
.tu-channel__main b { display: block; font-size: var(--Font-size-text-200); font-weight: 500; }
.tu-channel__main span { display: block; margin-top: 3px; font-size: var(--Font-size-text-100); color: var(--textSecondary); line-height: 1.55; }
.tu-channel__badge { flex: none; }

/* =============================================================================
   ⑬ 外壳就绪前不显示正文（消除「一闪」）
   -----------------------------------------------------------------------------
   【现象】点菜单跳到下一个页面时，会先看到「没有侧栏、正文顶到最左边」的一帧，
   然后侧栏突然出现、正文被挤到右边 —— 看起来像闪了一下、甚至像跳错页面。
   原因是外壳由 console-shell.js 注入，而浏览器在脚本执行前就先按
   「只有 <main>、没有侧栏」的初始 DOM 画了一帧。

   【做法】正文在 body 加上 cs-shell-ready 之前保持不可见；外壳渲染完立刻加上。
   【兜底】万一脚本没执行（被拦、报错），2 秒后自动显示 ——
   宁可让外壳缺失，也不能让用户看到一个永远空白的页面。
   ============================================================================= */
body.cs-console:not(.cs-shell-ready) > main { visibility: hidden; }

@keyframes cs-shell-fallback {
  to { visibility: visible; }
}
body.cs-console:not(.cs-shell-ready) > main {
  animation: cs-shell-fallback 0s linear 2s forwards;
}

/* 外壳就绪前的极细加载条：只出现在顶部，不遮挡内容区 */
body.cs-console:not(.cs-shell-ready)::after {
  content: '';
  position: fixed;
  top: 0;
  left: 0;
  height: 2px;
  width: 40%;
  background: var(--primary);
  animation: cs-shell-loading 0.9s ease-in-out infinite;
  z-index: 999;
}
@keyframes cs-shell-loading {
  0% { left: -40%; }
  100% { left: 100%; }
}

/* =============================================================================
   ⑭ 账单、充值抽屉与套餐（版式取自 drpc.org 的 Billing / Top-Up / Pricing）
   -----------------------------------------------------------------------------
   照抄的是**结构**而不是数字：四张 KPI 卡 + 账单历史表 + 三段式充值抽屉
   + 四档套餐卡。颜色、圆角、字体仍全部来自 tokens.css（drpc.org 线上变量）。
   ============================================================================= */

/* ---- 四张 KPI 卡：标签小字 → 大数字 → 一行说明 → 底部按钮 ---- */
.cs-billgrid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.cs-billcard {
  display: flex; flex-direction: column; gap: 6px; min-width: 0;
  padding: 18px; border: 1px solid var(--border); border-radius: var(--Radius-500);
  background: var(--backgroundSecondary);
}
.cs-billcard__label { font-size: var(--Font-size-text-100); color: var(--textSecondary); }
.cs-billcard__num {
  font-family: var(--font-display); font-size: clamp(var(--Font-size-header-100), 2.2vw, var(--Font-size-header-200));
  line-height: 1.15; font-weight: 500; font-variant-numeric: tabular-nums;
  color: var(--textPrimary); overflow-wrap: anywhere;
}
.cs-billcard__num small { font-size: var(--Font-size-text-200); font-weight: 400; color: var(--textSecondary); }
.cs-billcard__hint { font-size: var(--Font-size-text-100); color: var(--textSecondary); line-height: 1.5; }
.cs-billcard__foot { margin-top: auto; padding-top: 10px; }

/* ---- 白底主按钮（dRPC 的 Top-Up / Continue / Add funds 是白底黑字）----
   定义已搬到 app.css 的「定价页 / 营销页共用组件」段：营销页 pricing.html
   也要用它，而营销页不该为了一个按钮引入整套控制台样式表。 */

/* ---- 充值金额与快捷额度（dRPC 的 $50 / $200 / $500 / $1,000 药丸） ---- */
.cs-amount { position: relative; display: flex; align-items: center; }
.cs-amount input {
  width: 100%; height: 52px; padding: 0 64px 0 14px;
  background: var(--backgroundSurface); border: 1px solid var(--border);
  border-radius: var(--Radius-400); color: var(--textPrimary);
  /* 金额输入框是「钱」，比正文大一档；22px 落在 token 阶梯之间，用 clamp 保住 20→24 */
  font-family: var(--font-display);
  font-size: clamp(var(--Font-size-text-500), 1.6vw, var(--Font-size-header-100));
  font-variant-numeric: tabular-nums;
}
.cs-amount input:focus { outline: 2px solid var(--primaryLighter); outline-offset: 1px; }
.cs-amount__unit {
  position: absolute; right: 12px; font-size: var(--Font-size-text-100);
  color: var(--textSecondary); pointer-events: none;
}
.cs-toppills { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.cs-toppill {
  padding: 7px 16px; border: 1px solid var(--border); border-radius: 999px;
  background: transparent; color: var(--textPrimary); font-size: var(--Font-size-text-200);
  cursor: pointer; font-family: var(--font-sans);
}
.cs-toppill:hover { border-color: var(--borderSecondaryWhite, rgba(255,255,255,.28)); }
.cs-toppill.is-on { border-color: var(--primary); color: var(--primary); }
.cs-receive {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-top: 12px; padding: 12px 14px; border-radius: var(--Radius-300);
  background: var(--backgroundSurface); font-size: var(--Font-size-text-200);
}
.cs-receive b { font-family: var(--font-display); font-size: var(--Font-size-text-300); font-weight: 500; }
.cs-receive span { color: var(--textSecondary); }

/* ---- 支付方式卡片（加密支付地址卡） ---- */
.cs-paycard {
  margin-top: 12px; padding: 14px; border: 1px solid var(--border);
  border-radius: var(--Radius-500); background: var(--backgroundSecondary);
}
.cs-paycard__addr {
  display: flex; align-items: center; gap: 10px; font-family: var(--font-mono);
  font-size: var(--Font-size-text-200); overflow-wrap: anywhere;
}

/* ---- 套餐与订阅 ----
   `.cs-planpick*` 的完整定义在 app.css（营销页定价区块与控制台共用同一份），
   这里不再重复，避免两处各改一半。 */
.cs-subrow {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
  padding: 14px 16px; border-bottom: 1px solid var(--divider);
}
.cs-subrow:last-child { border-bottom: 0; }
.cs-subrow__main { flex: 1 1 260px; min-width: 0; }
.cs-subrow__no { font-family: var(--font-mono); font-size: var(--Font-size-text-100); color: var(--textSecondary); }
.cs-quota { height: 6px; border-radius: 999px; background: var(--backgroundSurface); overflow: hidden; margin-top: 8px; }
.cs-quota__bar { height: 100%; background: var(--primary); border-radius: 999px; }

/* ---- 全站低余额提示条（dRPC 的黄色 Low CU balance 条） ----
   G-17：原来写死 #f5c518 / #141415，是全站第 3 个黄。改用 tokens 的警告黄
   ——lightYellow（#e8cf47）与深色文字，语义色只剩一套。 */
.cs-lowbal {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
  padding: 10px 14px; border-radius: var(--Radius-300);
  background: var(--lightYellow); color: var(--textNegative);
  font-size: var(--Font-size-text-200);
}
.cs-lowbal__icon { flex: none; display: inline-flex; }
.cs-lowbal__text { flex: 1 1 240px; min-width: 0; line-height: 1.5; }
.cs-lowbal__text b { font-weight: 600; }
.cs-lowbal .cs-btn { border-color: color-mix(in srgb, var(--black) 16%, transparent); }

/* ---- 侧栏项目余额徽标（dRPC 左上的 PAYG $49） ---- */
.cs-side__balance {
  display: inline-flex; align-items: center; gap: 4px; flex: none;
  padding: 3px 7px; border-radius: var(--Radius-200);
  background: var(--primary); color: var(--textNegative);
  font-family: var(--font-display); font-size: var(--Font-size-text-50); font-weight: 600;
  text-decoration: none; white-space: nowrap;
}
.cs-side__balance:hover { background: var(--primaryLighter); color: var(--textNegative); }
/* 类选择器的 display:inline-flex 会盖掉 [hidden] 的 UA 样式，
   结果就是「还没拿到余额时先显示一个空的绿色小方块」。这里显式压回去。 */
.cs-side__balance[hidden] { display: none; }

@media (max-width: 1048px) {
  .cs-billgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 620px) {
  .cs-billgrid { grid-template-columns: minmax(0, 1fr); }
  .cs-billcard__num { font-size: var(--Font-size-header-100); }
}

/* 充值通道右侧的动作区：徽标与按钮排成一行，不把正文挤成一条竖线 */
.tu-channel__act { flex: none; display: inline-flex; align-items: center; gap: 8px; }

/* 黄色提示条上的按钮：ghost 按钮的灰色文字在黄底上几乎看不清，这里改成深色 */
.cs-lowbal .cs-btn--ghost { color: var(--textNegative); border-color: color-mix(in srgb, var(--black) 22%, transparent); }
.cs-lowbal .cs-btn--ghost:hover {
  background: color-mix(in srgb, var(--black) 8%, transparent);
  color: var(--textNegative);
  border-color: color-mix(in srgb, var(--black) 30%, transparent);
}

/* ==========================================================================
   控制台精细化优化：卡片呼吸悬停微抬、表格平滑高亮与状态反馈
   ========================================================================== */

/* 1. 控制台端点卡与项目卡呼吸微浮 */
.cs-ep, .cs-metric-card, .cs-billcard, .cs-planpick__card {
  transition: transform .22s var(--ease-out-expo, cubic-bezier(0.16, 1, 0.3, 1)),
              box-shadow .22s var(--ease-out-expo, cubic-bezier(0.16, 1, 0.3, 1)),
              border-color .18s ease !important;
}
/* G-12：端点卡 / 账单 KPI 多数不是链接，位移会让人以为能点（点了没反应 = 假交互）。
   纯展示卡只给边框与阴影，位移只留给真的能点的卡（<a> 或 data-href）。 */
.cs-ep:hover, .cs-metric-card:hover, .cs-billcard:hover {
  border-color: var(--borderSecondaryWhite);
  box-shadow: 0 12px 28px -4px color-mix(in srgb, var(--black) 45%, transparent), 0 0 16px var(--glow-primary);
}
a.cs-ep:hover, [data-href].cs-ep:hover { transform: translateY(-2px); }

/* 2. 侧栏与顶栏导航项交互提升 */
.cs-side__link {
  transition: background .18s ease, color .18s ease, transform .15s ease !important;
}
.cs-side__link:active {
  transform: scale(0.98);
}

/* 3. 复制徽标与微按钮点击动效 */
.cs-mini-copy {
  transition: all .18s ease !important;
}
.cs-mini-copy:active {
  transform: scale(0.92);
}
