/* sub2api 监控大屏 —— 深色模式是"选定"的，不是把浅色反转出来的。
   所有色值取自已通过校验的深色档（分类色 4 槽在 #1a1a19 表面上 CVD/对比度全 PASS）。 */

.viz-root {
  color-scheme: dark;

  /* 表面与文字 */
  --plane:          #0d0d0d;  /* 页面底 */
  --surface-1:      #1a1a19;  /* 卡片/图表表面 */
  --text-primary:   #ffffff;
  --text-secondary: #c3c2b7;
  --text-muted:     #898781;  /* 轴/次要标签 */
  --gridline:       #2c2c2a;  /* 发丝网格，实线 */
  --baseline:       #383835;
  --border:         rgba(255, 255, 255, 0.10);

  /* 分类色（深色档，固定顺序，按实体分配不按排名） */
  --series-1: #3987e5;  /* Token 用量 */
  --series-2: #d95926;  /* 消耗金额 */
  --series-3: #199e70;  /* QPS */
  --series-4: #c98500;  /* TPS */

  /* 状态色（保留槽，永不当作第 5 个系列用） */
  --good:     #0ca30c;
  --warning:  #fab219;
  --serious:  #ec835a;
  --critical: #d03b3b;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--plane);
  font-family: system-ui, -apple-system, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
}

/* 严格一屏：高度锁死在视口，内部靠 grid 分配剩余空间，页面本身不滚动。
   大屏是拿来"扫一眼"的，一旦需要滚动，屏幕下半部分就等于不存在。
   列表类卡片（在线用户 / 账号）内部仍可滚动 —— 它们的条目数不可控。 */
.viz-root {
  height: 100vh;
  overflow: hidden;
  padding: clamp(8px, 0.7vw, 14px);
  display: flex;
  flex-direction: column;
  gap: clamp(6px, 0.6vw, 11px);
  background: var(--plane);
  color: var(--text-primary);
}

/* ---------- 顶栏 ---------- */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 2px 4px;
}

.brand { display: flex; align-items: center; gap: 12px; }

.brand-mark {
  width: 10px;
  height: 26px;
  border-radius: 3px;
  background: var(--series-1);
}

.topbar h1 {
  margin: 0;
  font-size: clamp(18px, 1.5vw, 26px);
  font-weight: 650;
  letter-spacing: 0.02em;
}

.topbar-right { display: flex; align-items: center; gap: clamp(10px, 1vw, 20px); }

.btn {
  background: var(--surface-1);
  color: var(--text-secondary);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 7px 14px;
  font-size: 13px;
  font-family: inherit;
  cursor: pointer;
}
.btn:hover { color: var(--text-primary); border-color: var(--text-muted); }

.conn { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-secondary); }

.dot {
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--text-muted);
  flex: none;
}
.dot.ok   { background: var(--good); }
.dot.bad  { background: var(--critical); }
.dot.warn { background: var(--warning); }

.clock {
  font-size: clamp(16px, 1.3vw, 22px);
  font-variant-numeric: tabular-nums; /* 时钟每秒跳动，等宽才不抖 */
  color: var(--text-secondary);
}

/* ---------- KPI 行 ---------- */

/* KPI 行压到刚好放下内容：每省下 20px 都会变成下面图表的高度 */
.kpi-row {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: clamp(6px, 0.6vw, 11px);
  flex: none;
}

.tile {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 11px;
  padding: clamp(7px, 0.65vw, 12px) clamp(10px, 0.9vw, 16px);
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.tile-label { font-size: clamp(10px, 0.75vw, 13px); color: var(--text-muted); }

.tile-value {
  font-size: clamp(20px, 1.9vw, 34px);
  font-weight: 600;
  line-height: 1.1;
  /* 大号独立数字用比例数字，等宽会让它显得松散 */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tile-sub {
  font-size: clamp(9px, 0.7vw, 12px);
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tile-live .tile-value { color: var(--series-3); }

/* sparkline：只表达形状和趋势，不需要轴 —— 精确值由上面的大号数字给出 */
.tile-spark { position: relative; }
.spark {
  height: clamp(18px, 1.7vw, 30px);
  margin-top: 2px;
  width: 100%;
}

/* ---------- 主网格 ---------- */

/* 三行大图。行数是可读性的第一约束：卡片越多每张越矮，
   压到一定程度轴刻度会开始互相重叠，图就只剩装饰作用了。
   宁可少几张卡，也要让每张图有能读出数据的高度。 */
.grid {
  flex: 1;
  display: grid;
  gap: clamp(8px, 0.8vw, 14px);
  grid-template-columns: 1fr 1fr clamp(300px, 23vw, 430px);
  grid-template-rows: 1.15fr 1.15fr 1fr;
  /* 主趋势图跨两行 —— 它是这块屏幕上最该被看清的东西。
     账号配额同样跨两行：进度条 + 倒计时 + 窗口内用量，一行放不下。 */
  grid-template-areas:
    "utok  utok  acct"
    "utok  utok  acct"
    "mod   rank  onl";
  min-height: 0;
}

.card {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: clamp(8px, 0.8vw, 14px) clamp(10px, 1vw, 16px) clamp(6px, 0.6vw, 10px);
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}

/* 按显式 class 指派网格区域：:nth-of-type 数的是元素类型（section），
   不是 class，用它会把 QPS/TPS 错配到趋势卡的位置上 */
.card-utok     { grid-area: utok; }
.card-online   { grid-area: onl; }
.card-accounts { grid-area: acct; }
.card-models   { grid-area: mod; }
.card-rank     { grid-area: rank; }

.card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 4px;
  flex: none;
}

.card-head h2 {
  margin: 0;
  font-size: clamp(12px, 0.95vw, 16px);
  font-weight: 600;
  color: var(--text-secondary);
}

.card-note {
  font-size: clamp(10px, 0.8vw, 13px);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* 图表容器带上 x 轴标签所需的高度，避免卡片内出现嵌套滚动条 */
.chart { flex: 1; min-height: 0; width: 100%; }

/* ---------- 在线用户 ---------- */

/* 每人一行，绝不滚动 —— 大屏上出现滚动条，就意味着有内容永远不会被看到。
   放不下时由 JS 截断并显示「还有 N 人」，而不是把它们藏进滚动区。
   行高在 --online-row 定死，JS 按它计算能放几行，两边必须保持一致。 */
.online-list {
  --online-row: 30px;
  flex: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.online-item {
  display: grid;
  grid-template-columns: 1fr auto minmax(40px, 72px) 34px;
  align-items: center;
  gap: 9px;
  height: var(--online-row);
  padding: 0 10px;
  border-radius: 7px;
  background: rgba(255, 255, 255, 0.03);
  flex: none;
}

.online-name {
  font-size: clamp(12px, 0.9vw, 15px);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 有人在排队是要动手的信号，不能因为"简洁"就丢掉 */
.online-wait {
  color: var(--warning);
  font-weight: 500;
  font-size: 0.9em;
  font-variant-numeric: tabular-nums;
}

.online-figs {
  font-size: clamp(10px, 0.8vw, 13px);
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.online-pct {
  font-size: clamp(10px, 0.8vw, 13px);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

/* 单个比值对着上限 —— meter，不是两片的饼 */
.meter {
  height: 6px;
  border-radius: 3px;
  background: var(--gridline);
  overflow: hidden;
}
.meter span {
  display: block;
  height: 100%;
  border-radius: 3px;
  background: var(--series-3);
}
.meter.hot span { background: var(--warning); }
.meter.full span { background: var(--critical); }

/* 被截断时的说明行：告诉你还有多少人没显示，而不是假装只有这么多 */
.online-more {
  height: var(--online-row);
  display: flex;
  align-items: center;
  padding: 0 10px;
  font-size: clamp(10px, 0.78vw, 12px);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  flex: none;
}

.empty {
  color: var(--text-muted);
  font-size: 13px;
  margin: auto;
  text-align: center;
}

/* ---------- 时间窗口选择器 ---------- */

.window-pick {
  display: flex;
  gap: 2px;
  padding: 2px;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 9px;
}

.window-pick button {
  background: none;
  border: none;
  color: var(--text-muted);
  font-family: inherit;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  padding: 5px 11px;
  border-radius: 7px;
  cursor: pointer;
}
.window-pick button:hover { color: var(--text-primary); }

/* 选中态不只靠背景色：加粗 + 提亮文字，弱视和灰度屏下同样分得出 */
.window-pick button[aria-pressed="true"] {
  background: var(--series-1);
  color: #ffffff;
  font-weight: 650;
}

/* ---------- 配额告警横幅 ---------- */

.alert-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 10px 14px;
  border-radius: 10px;
  background: rgba(208, 59, 59, 0.14);
  border: 1px solid var(--critical);
  font-size: clamp(12px, 0.95vw, 15px);
  color: var(--text-primary);
}

/* 逼近但还没撞满：降一档到警示色，措辞也要跟着降 */
.alert-banner.warn {
  background: rgba(250, 178, 25, 0.13);
  border-color: var(--warning);
}

.alert-banner .alert-icon { font-size: 1.1em; flex: none; }
.alert-banner b { font-variant-numeric: tabular-nums; }
.alert-banner .alert-sep { color: var(--text-muted); }

/* ---------- 账号配额 ---------- */

.acct-list {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.acct-item {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 9px 11px;
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid transparent;
  font-size: clamp(11px, 0.85vw, 14px);
}

/* 配额吃紧的账号描边，让它在一列卡片里能被扫到 */
.acct-item.alerting { border-color: var(--critical); background: rgba(208, 59, 59, 0.08); }

.acct-top { display: flex; align-items: center; gap: 8px; }

.acct-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.acct-plat { color: var(--text-muted); font-size: 0.9em; white-space: nowrap; }
.acct-state { margin-left: auto; white-space: nowrap; font-size: 0.9em; }

/* 状态永远是 图标 + 文字，不靠颜色单独表意 */
.acct-state.ok   { color: var(--good); }
.acct-state.warn { color: var(--warning); }
.acct-state.err  { color: var(--critical); }

/* 配额窗口：一行一个窗口，meter + 百分比 + 倒计时 */
.quota-row {
  display: grid;
  grid-template-columns: 34px 1fr auto;
  align-items: center;
  gap: 8px;
  font-size: 0.92em;
}

.quota-label { color: var(--text-muted); font-variant-numeric: tabular-nums; }

.quota-figs {
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  font-size: 0.95em;
}

.quota-meter {
  height: 6px;
  border-radius: 3px;
  background: var(--gridline);
  overflow: hidden;
}
.quota-meter span {
  display: block;
  height: 100%;
  border-radius: 3px;
  background: var(--series-1);
}
.quota-meter.warn span     { background: var(--warning); }
.quota-meter.critical span { background: var(--critical); }

/* 窗口内累计用量，比进度条低一级 */
.quota-detail {
  color: var(--text-muted);
  font-size: 0.85em;
  font-variant-numeric: tabular-nums;
}

/* 平台没有窗口概念时的说明 —— 绝不画一根 0% 的空进度条冒充"额度充足" */
.quota-na { color: var(--text-muted); font-size: 0.85em; }

/* ---------- 表格视图 ---------- */

.table-view {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.86);
  z-index: 50;
  overflow-y: auto;
  padding: 24px;
}

.table-view-inner {
  max-width: 1400px;
  margin: 0 auto;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 20px 24px 28px;
}

.table-view-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}
.table-view-head h2 { margin: 0; font-size: 18px; }

.tables { display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); gap: 24px; }

.tables h3 {
  font-size: 14px;
  color: var(--text-secondary);
  margin: 0 0 8px;
  font-weight: 600;
}

table { width: 100%; border-collapse: collapse; font-size: 13px; }
caption { text-align: left; color: var(--text-muted); font-size: 12px; padding-bottom: 6px; }
th, td {
  text-align: right;
  padding: 5px 8px;
  border-bottom: 1px solid var(--gridline);
  font-variant-numeric: tabular-nums; /* 表格里数字要竖向对齐 */
}
th:first-child, td:first-child { text-align: left; font-variant-numeric: normal; }
th { color: var(--text-muted); font-weight: 500; }
td { color: var(--text-secondary); }

/* ---------- 底栏 ---------- */

.footbar {
  display: flex;
  justify-content: space-between;
  font-size: clamp(10px, 0.75vw, 12px);
  color: var(--text-muted);
  padding: 0 4px;
  font-variant-numeric: tabular-nums;
}

/* 重新拉取时保持上一帧、降低不透明度，避免骨架闪烁和布局跳动 */
.viz-root.stale .grid,
.viz-root.stale .kpi-row { opacity: 0.55; transition: opacity 0.2s; }

::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-thumb { background: var(--gridline); border-radius: 3px; }
::-webkit-scrollbar-track { background: transparent; }

/* 窄屏放弃"一屏"约束：单列 6 张卡强塞进一屏只会让每张都不可读，
   这时可滚动才是对的。 */
@media (max-width: 1100px) {
  .viz-root { height: auto; min-height: 100vh; overflow: visible; }
  .kpi-row { grid-template-columns: repeat(3, 1fr); }
  .grid {
    grid-template-columns: 1fr;
    grid-template-rows: repeat(5, minmax(240px, auto));
    grid-template-areas: "utok" "acct" "mod" "rank" "onl";
  }
  .window-pick { order: 1; flex-basis: 100%; justify-content: flex-start; }
  .topbar { flex-wrap: wrap; }
}

/* 矮屏（1366x768 之类）再挤一档，保住图表高度 */
@media (min-width: 1101px) and (max-height: 820px) {
  .kpi-row { grid-template-columns: repeat(6, 1fr); }
  .tile-value { font-size: clamp(17px, 1.5vw, 24px); }
  .spark { height: 16px; }
  .topbar h1 { font-size: 18px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}
