/*
 * 控制台样式。
 *
 * 主题：<html data-theme="light|dark">，由 index.html 里的内联脚本在首屏绘制前定好，
 * 所以不会有"先白一下再变黑"。CSS 这边只认这一个属性，不再写 prefers-color-scheme —
 * 媒体查询和手动切换混在一起时，优先级会绕得没人能改。
 *
 * 色值尽量用 color-mix 从语义色现调，明暗两套只需要维护那几个基色。
 */

/* ================================================================ 设计变量 */

:root {
  color-scheme: light;

  /* 画布与容器 */
  --bg: #f2f5f9;
  --bg-tint-a: rgba(53, 99, 233, .10);
  --bg-tint-b: rgba(16, 185, 129, .06);
  --panel: #ffffff;
  --panel-2: #f7f9fc;          /* 面板里的次级底：表头、进度槽、代码块 */
  --veil: rgba(255, 255, 255, .72);   /* 顶栏毛玻璃 */
  --border: #e5e9f0;
  --border-strong: #d2d9e4;

  /* 文字 */
  --text: #0e1626;
  --text-2: #3f4b60;
  --muted: #6b7789;

  /* 语义色 */
  --accent: #3563e9;
  --accent-2: #6d8dff;         /* 渐变的另一端 */
  --on-accent: #ffffff;
  --pass: #0f9d58;
  --warn: #b57d00;
  --challenge: #d9700f;
  --fail: #d92d20;
  --dead: #98a2b3;

  /* 层次 */
  --shadow-1: 0 1px 2px rgba(16, 24, 40, .04), 0 1px 3px rgba(16, 24, 40, .06);
  --shadow-2: 0 2px 4px rgba(16, 24, 40, .04), 0 8px 24px rgba(16, 24, 40, .07);
  --shadow-3: 0 2px 8px rgba(16, 24, 40, .08), 0 32px 64px rgba(16, 24, 40, .20);
  --ring: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);

  /* 尺度 */
  --r-xs: 5px;
  --r-sm: 7px;
  --r-md: 10px;
  --r-lg: 14px;
  --r-full: 999px;

  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
          "Liberation Mono", "Courier New", monospace;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text", "Segoe UI",
          Inter, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --bg: #0c0f15;
  --bg-tint-a: rgba(91, 140, 255, .13);
  --bg-tint-b: rgba(16, 185, 129, .07);
  --panel: #141922;
  --panel-2: #1a202b;
  --veil: rgba(20, 25, 34, .74);
  --border: #232b38;
  --border-strong: #313b4b;

  --text: #e7ecf4;
  --text-2: #aeb9cc;
  --muted: #7e8ba1;

  --accent: #5b8cff;
  --accent-2: #8aa9ff;
  --on-accent: #0b1120;
  --pass: #33cf8b;
  --warn: #e0b040;
  --challenge: #f2883c;
  --fail: #f9736b;
  --dead: #5d6a80;

  --shadow-1: 0 1px 2px rgba(0, 0, 0, .30);
  --shadow-2: 0 2px 6px rgba(0, 0, 0, .30), 0 12px 32px rgba(0, 0, 0, .30);
  --shadow-3: 0 4px 12px rgba(0, 0, 0, .40), 0 40px 80px rgba(0, 0, 0, .55);
}

* {
  box-sizing: border-box;
  /* 默认滚动条在深色下是亮白的一条，很跳 */
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
}

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  /* 两团很淡的光晕，避免整屏纯色发死。fixed 让它不跟着滚动 */
  background-image:
    radial-gradient(900px 500px at 12% -10%, var(--bg-tint-a), transparent 70%),
    radial-gradient(700px 420px at 92% 0%, var(--bg-tint-b), transparent 70%);
  background-attachment: fixed;
  background-repeat: no-repeat;
  color: var(--text);
  font: 14px/1.55 var(--sans);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

::selection { background: color-mix(in srgb, var(--accent) 26%, transparent); }

*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border: 3px solid transparent;
  background-clip: content-box;
  border-radius: var(--r-full);
}
*::-webkit-scrollbar-thumb:hover { background: var(--muted); background-clip: content-box; }

/* ================================================================ 通用类 */

.hidden { display: none !important; }
.spacer { flex: 1; }
.muted { color: var(--muted); font-size: 12.5px; }
.right { text-align: right; }
.num { text-align: right; font-variant-numeric: tabular-nums; }
.mono { font-family: var(--mono); font-size: 12.5px; letter-spacing: -.1px; }
.danger-text { color: var(--fail); }

code { font-family: var(--mono); font-size: .92em; }

:focus-visible { outline: none; box-shadow: var(--ring); border-radius: var(--r-xs); }

/* ================================================================ 按钮 */

button {
  font: 500 13px/1.4 var(--sans);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 32px;
  padding: 0 14px;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: linear-gradient(180deg, var(--accent-2), var(--accent));
  color: var(--on-accent);
  cursor: pointer;
  white-space: nowrap;
  box-shadow: var(--shadow-1);
  transition: transform .12s ease, box-shadow .16s ease, background .16s ease,
              border-color .16s ease, color .16s ease, opacity .16s ease;
}
button:hover:not(:disabled) { box-shadow: var(--shadow-2); filter: saturate(1.08) brightness(1.04); }
button:active:not(:disabled) { transform: translateY(1px); box-shadow: var(--shadow-1); }
button:disabled { opacity: .45; cursor: not-allowed; box-shadow: none; filter: none; }
button:focus-visible { box-shadow: var(--ring); }

button.ghost {
  background: var(--panel);
  color: var(--text-2);
  border-color: var(--border);
  box-shadow: none;
}
button.ghost:hover:not(:disabled) {
  background: color-mix(in srgb, var(--accent) 7%, var(--panel));
  border-color: color-mix(in srgb, var(--accent) 40%, var(--border));
  color: var(--accent);
  filter: none;
}
button.danger { background: linear-gradient(180deg, color-mix(in srgb, var(--fail) 82%, white), var(--fail)); color: #fff; }
:root[data-theme="dark"] button.danger { color: #1a0d0d; }

button.ghost.danger { background: var(--panel); color: var(--fail); border-color: var(--border); }
button.ghost.danger:hover:not(:disabled) { background: var(--fail); color: #fff; border-color: var(--fail); }

button.icon {
  width: 30px;
  height: 30px;
  padding: 0;
  background: transparent;
  color: var(--muted);
  border-color: transparent;
  box-shadow: none;
  border-radius: var(--r-sm);
  font-size: 15px;
}
button.icon:hover:not(:disabled) { background: color-mix(in srgb, var(--muted) 14%, transparent); color: var(--text); filter: none; }

button.mini { height: 25px; padding: 0 10px; font-size: 12px; border-radius: var(--r-xs); }
button.accent { background: linear-gradient(180deg, var(--accent-2), var(--accent)); color: var(--on-accent); border-color: transparent; box-shadow: var(--shadow-1); }

/* ================================================================ 表单控件 */

input, select, textarea {
  font: 13px/1.4 var(--sans);
  height: 32px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--panel);
  color: var(--text);
  transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
}
input::placeholder, textarea::placeholder { color: color-mix(in srgb, var(--muted) 78%, transparent); }
input:hover:not(:disabled), select:hover:not(:disabled) { border-color: var(--border-strong); }
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--ring);
}
input[readonly] { background: var(--panel-2); color: var(--muted); cursor: not-allowed; }

select {
  appearance: none;
  padding-right: 28px;
  /* 自绘箭头，系统那个在深色下经常是黑的 */
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 15px) 14px, calc(100% - 10px) 14px;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

input[type="search"] {
  padding-left: 30px;
  background-repeat: no-repeat;
  background-position: 10px center;
  background-size: 13px;
  /* 内联 SVG 放大镜，不引图标字体 */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%238b95a5' stroke-width='1.7' stroke-linecap='round'%3E%3Ccircle cx='7' cy='7' r='4.6'/%3E%3Cpath d='M10.6 10.6 14 14'/%3E%3C/svg%3E");
}
input[type="checkbox"] { height: auto; accent-color: var(--accent); cursor: pointer; }
.checkbox { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; }

/* ================================================================ 登录 */

.login {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 24px;
  background: var(--bg);
  background-image:
    radial-gradient(760px 420px at 50% -8%, var(--bg-tint-a), transparent 72%),
    radial-gradient(560px 340px at 84% 104%, var(--bg-tint-b), transparent 72%);
  z-index: 50;
}
.login-box {
  position: relative;
  width: 340px;
  max-width: 100%;
  padding: 30px 28px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-3);
  display: flex;
  flex-direction: column;
  gap: 12px;
  animation: rise .32s cubic-bezier(.2, .8, .3, 1);
}
/* 顶边一道渐变高光，卡片才不像个白方块 */
.login-box::before {
  content: "";
  position: absolute;
  inset: -1px -1px auto;
  height: 2px;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
  opacity: .8;
}
.login-box h1 { margin: 0; font-size: 18px; font-weight: 650; letter-spacing: -.2px; }
.login-box p { margin: 0; line-height: 1.65; }
.login-box input { height: 36px; }
.login-box button { height: 36px; }
.login-error { color: var(--fail); font-size: 12.5px; min-height: 18px; }

/* 没设密码那块要放一段可复制的 JSON，比密码框宽一点才不会折行折得难看 */
#loginOpen { width: 420px; }
.login-code {
  margin: 2px 0;
  padding: 11px 13px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font-family: var(--mono);
  font-size: 12px;
  color: var(--accent);
  overflow-x: auto;
}

@keyframes rise {
  from { opacity: 0; transform: translateY(10px) scale(.985); }
  to   { opacity: 1; transform: none; }
}

/* ================================================================ 顶栏 */

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 10px 20px;
  background: var(--veil);
  backdrop-filter: saturate(1.6) blur(14px);
  -webkit-backdrop-filter: saturate(1.6) blur(14px);
  border-bottom: 1px solid var(--border);
}

.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  font-weight: 640;
  font-size: 14px;
  letter-spacing: -.2px;
  white-space: nowrap;
}
.brand-mark {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 8px;
  font-size: 14px;
  background: linear-gradient(145deg, var(--accent-2), var(--accent));
  box-shadow: 0 2px 8px color-mix(in srgb, var(--accent) 40%, transparent);
}
@media (max-width: 900px) { .brand-text { display: none; } }

/* 分段控件式的标签栏 */
.tabs {
  display: flex;
  gap: 2px;
  padding: 3px;
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--muted) 11%, transparent);
  overflow-x: auto;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  height: 28px;
  padding: 0 13px;
  background: transparent;
  color: var(--muted);
  border-radius: var(--r-sm);
  box-shadow: none;
  font-weight: 500;
}
.tab:hover:not(.active) { background: color-mix(in srgb, var(--panel) 60%, transparent); color: var(--text); filter: none; }
.tab.active {
  background: var(--panel);
  color: var(--accent);
  font-weight: 600;
  box-shadow: var(--shadow-1);
}

.topbar-right { display: flex; align-items: center; gap: 8px; margin-left: auto; }

.conn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 28px;
  padding: 0 11px 0 9px;
  border-radius: var(--r-full);
  border: 1px solid var(--border);
  font-size: 12.5px;
  color: var(--muted);
  white-space: nowrap;
}
.dot { width: 7px; height: 7px; border-radius: 50%; background: var(--dead); flex: none; }
.conn.live { color: var(--pass); border-color: color-mix(in srgb, var(--pass) 34%, transparent); }
.conn.live .dot { background: var(--pass); animation: pulse 2.2s ease-in-out infinite; }
.conn.down { color: var(--fail); border-color: color-mix(in srgb, var(--fail) 34%, transparent); }
.conn.down .dot { background: var(--fail); }
@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--pass) 55%, transparent); }
  60%      { box-shadow: 0 0 0 5px transparent; }
}

/* ================================================================ 页面骨架 */

.page { display: none; padding: 20px; max-width: 1760px; margin: 0 auto; }
.page.active { display: block; animation: fade .22s ease; }
@keyframes fade { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

.panel {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  margin-bottom: 16px;
  overflow: hidden;
}
.panel-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 16px;
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, color-mix(in srgb, var(--panel-2) 70%, transparent), transparent);
}
.panel-head h2 {
  margin: 0;
  font-size: 13px;
  font-weight: 640;
  letter-spacing: .01em;
}
/* 第一个 .muted 顶到右边，后面的紧跟着它排，不要各自再吃掉一份空白 */
.panel-head .muted { margin-left: auto; }
.panel-head .muted ~ .muted, .panel-head .muted ~ .checkbox { margin-left: 0; }

.hint {
  margin: 0;
  padding: 11px 16px;
  font-size: 12px;
  line-height: 1.7;
  color: var(--muted);
  border-top: 1px solid var(--border);
  background: color-mix(in srgb, var(--panel-2) 55%, transparent);
}
.hint b { color: var(--text-2); font-weight: 600; }
.hint + .hint { border-top: none; padding-top: 0; }
/* 警示性的说明：左边一根黄条，跟普通 hint 区分开 */
.warn-hint {
  position: relative;
  border-top: none;
  padding: 0 16px 11px 26px;
}
.warn-hint::before {
  content: "";
  position: absolute;
  left: 16px;
  top: 2px;
  bottom: 11px;
  width: 2px;
  border-radius: 2px;
  background: color-mix(in srgb, var(--warn) 55%, transparent);
}

/* ================================================================ 概览卡片 */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(172px, 1fr));
  gap: 12px;
  margin-bottom: 16px;
}
.card {
  position: relative;
  padding: 13px 15px 14px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
  overflow: hidden;
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.card:hover { transform: translateY(-1px); box-shadow: var(--shadow-2); border-color: var(--border-strong); }
/* 左侧状态色条：默认中性，有状态的卡片染色 */
.card::before {
  content: "";
  position: absolute;
  left: 0;
  top: 10px;
  bottom: 10px;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: color-mix(in srgb, var(--muted) 26%, transparent);
  transition: background .2s ease;
}
.card.ok::before   { background: var(--pass); }
.card.warn::before { background: var(--warn); }
.card.bad::before  { background: var(--fail); }

.card .label {
  font-size: 11.5px;
  font-weight: 500;
  color: var(--muted);
  letter-spacing: .02em;
}
.card .value {
  margin-top: 3px;
  font-size: 27px;
  font-weight: 660;
  line-height: 1.15;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}
.card.ok .value   { color: var(--pass); }
.card.warn .value { color: var(--warn); }
.card.bad .value  { color: var(--fail); }
/* 一张卡里塞两个数（上行 / 下行）时字号收一档，免得换行 */
.card.dual .value { font-size: 18px; letter-spacing: -.01em; }
.card .sub {
  margin-top: 3px;
  font-size: 11.5px;
  color: var(--muted);
  overflow-wrap: anywhere;
}

/* ================================================================ 覆盖率色带 */

.bars { padding: 14px 16px; display: flex; flex-direction: column; gap: 11px; }
/* 一项 = 一条色带 +（可能有的）一行结论。包成一个节点，增量更新时才好按 key 配对 */
.bar-item { display: flex; flex-direction: column; gap: 7px; }
.bar-row { display: flex; align-items: center; gap: 12px; }
.bar-name { width: 110px; flex: none; font-size: 12.5px; font-weight: 550; }
.bar-track {
  flex: 1;
  height: 9px;
  border-radius: var(--r-full);
  background: color-mix(in srgb, var(--muted) 15%, transparent);
  overflow: hidden;
  display: flex;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--muted) 8%, transparent);
}
.bar-track span { height: 100%; transition: width .5s cubic-bezier(.2, .8, .3, 1); }
.bar-track .s-pass      { background: var(--pass); }
.bar-track .s-warn      { background: var(--warn); }
.bar-track .s-challenge { background: var(--challenge); }
.bar-track .s-fail      { background: var(--fail); }
.bar-val {
  width: 178px;
  flex: none;
  text-align: right;
  font-size: 11.5px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* 一整项全挂时的结论。缩进对齐到进度条，让人一眼知道是在说上面那一行 */
.bar-reason,
.bar-verdict { margin-left: 122px; font-size: 12px; line-height: 1.6; }
.bar-reason { color: var(--muted); }
.bar-verdict {
  padding: 8px 11px;
  border-radius: var(--r-sm);
  border: 1px solid;
  color: var(--text-2);
}
.bar-verdict.systemic   { border-color: color-mix(in srgb, var(--warn) 42%, transparent);      background: color-mix(in srgb, var(--warn) 9%, transparent); }
.bar-verdict.reputation { border-color: color-mix(in srgb, var(--challenge) 42%, transparent); background: color-mix(in srgb, var(--challenge) 9%, transparent); }

/* ================================================================ 运行参数 */

.kv {
  padding: 12px 16px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(252px, 1fr));
  gap: 2px 24px;
}
.kv div {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  font-size: 12.5px;
  padding: 6px 0;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 70%, transparent);
}
.kv .k { color: var(--muted); flex: none; }
.kv div > :last-child { text-align: right; color: var(--text-2); }

/* ================================================================ 工具栏 */

.toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 14px;
}
.toolbar #q, .toolbar #qq { min-width: 240px; flex: 0 1 320px; }

.scanbar {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
  padding: 10px 14px;
  font-size: 12.5px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
}
.progress {
  flex: 1;
  height: 7px;
  background: color-mix(in srgb, var(--muted) 16%, transparent);
  border-radius: var(--r-full);
  overflow: hidden;
}
.progress-fill {
  height: 100%;
  width: 0;
  border-radius: var(--r-full);
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  transition: width .4s cubic-bezier(.2, .8, .3, 1);
  /* 斜纹在跑，让人知道它没卡住 */
  background-size: 200% 100%;
  animation: sweep 2s linear infinite;
}
@keyframes sweep { to { background-position: -200% 0; } }

/* ================================================================ 表格 */

.table-panel { overflow-x: auto; }
.grid { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 12.5px; }
.grid th {
  position: sticky;
  top: 0;
  z-index: 1;
  text-align: left;
  font-weight: 600;
  font-size: 11.5px;
  letter-spacing: .02em;
  color: var(--muted);
  padding: 9px 12px;
  white-space: nowrap;
  background: var(--panel-2);
  border-bottom: 1px solid var(--border);
}
.grid th.num, .grid th.right { text-align: right; }
.grid td {
  padding: 9px 12px;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 65%, transparent);
  white-space: nowrap;
  vertical-align: middle;
}
.grid tbody tr { transition: background .12s ease; }
.grid tbody tr:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.grid tbody tr:last-child td { border-bottom: none; }
.grid .empty { text-align: center; color: var(--muted); padding: 40px 16px; }
.grid td.actions { text-align: right; }
.grid td.actions button + button { margin-left: 6px; }
/* 行高亮时按钮才浮出来，平时不抢注意力 */
.grid td.actions button { opacity: .72; }
.grid tbody tr:hover td.actions button { opacity: 1; }

.pager {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 16px;
  border-top: 1px solid var(--border);
  background: color-mix(in srgb, var(--panel-2) 55%, transparent);
}

/* ================================================================ 徽章与状态 */

.badge {
  display: inline-block;
  padding: 1px 8px;
  border-radius: var(--r-full);
  font-size: 11.5px;
  font-weight: 550;
  line-height: 17px;
  border: 1px solid transparent;
}
.st-ok       { color: var(--pass);  background: color-mix(in srgb, var(--pass) 13%, transparent);  border-color: color-mix(in srgb, var(--pass) 26%, transparent); }
.st-cooldown { color: var(--warn);  background: color-mix(in srgb, var(--warn) 14%, transparent);  border-color: color-mix(in srgb, var(--warn) 28%, transparent); }
.st-dead     { color: var(--fail);  background: color-mix(in srgb, var(--fail) 12%, transparent);  border-color: color-mix(in srgb, var(--fail) 26%, transparent); }
.st-retired  { color: var(--muted); background: color-mix(in srgb, var(--muted) 14%, transparent); border-color: color-mix(in srgb, var(--muted) 26%, transparent); }

.grade { font-weight: 680; font-size: 12.5px; font-variant-numeric: tabular-nums; }
.g-A { color: var(--pass); }
.g-B { color: color-mix(in srgb, var(--pass) 82%, var(--warn)); }
.g-C { color: var(--warn); }
.g-D { color: var(--challenge); }
.g-F { color: var(--fail); }

/* 检测项小圆点 */
.dots { display: inline-flex; gap: 4px; align-items: center; }
.dots i {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--border-strong);
  cursor: default;
}
.dots i.pass      { background: var(--pass);      box-shadow: 0 0 0 2px color-mix(in srgb, var(--pass) 16%, transparent); }
.dots i.warn      { background: var(--warn);      box-shadow: 0 0 0 2px color-mix(in srgb, var(--warn) 16%, transparent); }
.dots i.challenge { background: var(--challenge); box-shadow: 0 0 0 2px color-mix(in srgb, var(--challenge) 16%, transparent); }
.dots i.fail      { background: var(--fail);      box-shadow: 0 0 0 2px color-mix(in srgb, var(--fail) 16%, transparent); }
/* 未测：灰空心。刻意不给填充色，跟四种"测出结果"的实心点一眼区分开 */
.dots i.skipped   { background: transparent; box-shadow: inset 0 0 0 1px var(--dead); }

.tag {
  display: inline-block;
  padding: 0 6px;
  border-radius: var(--r-xs);
  background: color-mix(in srgb, var(--accent) 13%, transparent);
  color: var(--accent);
  font-size: 11px;
  line-height: 17px;
  font-weight: 550;
  vertical-align: middle;
}

/*
 * 出口类型小标签。故意做得比状态色淡一档：它不计入分数、也不参与自动剔除，
 * 用 stat-fail 那种实心红会让人以为这条代理被判不合格了。
 * 只有描边 + 文字色，没有实心底色，视觉上明确属于"附注"而不是"结论"。
 */
.risk {
  display: inline-block;
  margin-left: 6px;
  padding: 0 5px;
  border: 1px solid currentColor;
  border-radius: var(--r-xs);
  font-size: 10.5px;
  line-height: 15px;
  font-weight: 550;
  vertical-align: 1px;
  white-space: nowrap;
  opacity: .85;
  cursor: help; /* 有 title 提示，鼠标形状提示一下可以悬停看 */
}
.risk-mobile  { color: var(--pass); }
.risk-home    { color: var(--pass); }
/* 机房 / 公开代理用中性偏暖的颜色，不用 --fail：这不是失败，是一类出口 */
.risk-hosting { color: var(--muted); }
.risk-proxy   { color: var(--warn); }

/* 标签页上的计数气泡 */
.pill {
  display: inline-block;
  min-width: 17px;
  padding: 0 5px;
  margin-left: 5px;
  border-radius: var(--r-full);
  background: color-mix(in srgb, var(--muted) 22%, transparent);
  color: var(--muted);
  font-size: 10.5px;
  font-weight: 600;
  line-height: 16px;
  text-align: center;
  vertical-align: 1px;
}
.tab.active .pill { background: var(--accent); color: var(--on-accent); }

/* ================================================================ 实时监控 */

/* 会话表和事件流并排。两边都拉到视口高度，免得下面留一大片空白 */
.live-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(400px, 33%);
  gap: 16px;
  align-items: stretch;
  min-height: calc(100vh - 132px);
}
@media (max-width: 1200px) { .live-grid { grid-template-columns: 1fr; min-height: 0; } }

.live-grid > .panel { display: flex; flex-direction: column; margin-bottom: 0; min-height: 0; }
.live-grid > .table-panel { overflow: hidden; }
.live-grid > .table-panel > .grid-scroll { overflow: auto; flex: 1; min-height: 0; }

.log-panel { display: flex; flex-direction: column; min-height: 260px; }
.log {
  overflow-y: auto;
  padding: 4px 0;
  font-family: var(--mono);
  font-size: 11.5px;
  flex: 1;
  min-height: 0;
}
.log-empty { line-height: 1.8; font-family: var(--sans); }
.log-line {
  position: relative;
  display: flex;
  gap: 10px;
  padding: 5px 14px 5px 16px;
  line-height: 1.55;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
}
.log-line:last-child { border-bottom: none; }
/* 事件类型走左边一根 2px 的色条，不再整行泼底色 —— 密集滚动时底色会糊成一片 */
.log-line::before {
  content: "";
  position: absolute;
  left: 6px;
  top: 6px;
  bottom: 6px;
  width: 2px;
  border-radius: 2px;
  background: transparent;
}
/* 刚进来的那条闪一下底色，一眼看到新增在哪 */
.log-line:first-child { animation: log-in .6s ease-out; }
@keyframes log-in {
  from { background: color-mix(in srgb, var(--accent) 20%, transparent); }
  to   { background: transparent; }
}
.log-time { color: var(--muted); flex: none; font-variant-numeric: tabular-nums; opacity: .8; }
.log-body { word-break: break-all; white-space: pre-wrap; color: var(--text-2); }

.log-line.ev-fail::before, .log-line.ev-pool\.failure::before { background: var(--fail); }
.log-line.ev-fail .log-body, .log-line.ev-pool\.failure .log-body { color: var(--fail); }
.log-line.ev-rotate::before { background: var(--challenge); }
.log-line.ev-rotate .log-body { color: var(--challenge); }
.log-line.ev-bind::before { background: var(--pass); }
.log-line.ev-bind .log-body { color: var(--pass); }
/* 剔除会改池子，日志里加底色，滚动时也不会被漏掉 */
.log-line.ev-cull { background: color-mix(in srgb, var(--fail) 8%, transparent); }
.log-line.ev-cull::before { background: var(--fail); }
.log-line.ev-cull .log-body { color: var(--fail); font-weight: 600; }

/* ================================================================ 弹窗 */

.modal {
  position: fixed;
  inset: 0;
  background: color-mix(in srgb, #05070d 55%, transparent);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  display: grid;
  place-items: center;
  z-index: 40;
  padding: 24px;
  animation: fade .16s ease;
}
.modal-box {
  width: min(880px, 100%);
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-3);
  animation: rise .24s cubic-bezier(.2, .8, .3, 1);
  overflow: hidden;
}
.modal-head, .modal-foot { display: flex; align-items: center; gap: 12px; padding: 13px 18px; }
.modal-head {
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, color-mix(in srgb, var(--panel-2) 70%, transparent), transparent);
}
.modal-foot { border-top: 1px solid var(--border); background: color-mix(in srgb, var(--panel-2) 55%, transparent); }
.modal-head h2 { margin: 0; font-size: 14.5px; font-weight: 640; }
.modal-body { overflow-y: auto; padding: 18px; }

/* 报告头部：左边出口信息，右边大分数 */
.report-head { display: flex; gap: 20px; align-items: stretch; margin-bottom: 18px; }
.report-facts { flex: 1; display: grid; grid-template-columns: repeat(auto-fill, minmax(178px, 1fr)); gap: 13px; }
.fact .k { font-size: 11.5px; color: var(--muted); }
.fact .v { font-size: 14.5px; margin-top: 2px; color: var(--text); }
.report-score {
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-align: center;
  padding: 12px 20px;
  min-width: 128px;
  border-radius: var(--r-md);
  border: 1px solid var(--border);
  background: linear-gradient(160deg, color-mix(in srgb, var(--panel-2) 80%, transparent), transparent);
}
.report-score .n { font-size: 46px; font-weight: 700; line-height: 1; letter-spacing: -.04em; font-variant-numeric: tabular-nums; }
.report-score .g { font-size: 12px; color: var(--muted); margin-top: 6px; }

.summary-line {
  padding: 11px 14px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  margin-bottom: 14px;
  font-size: 12.5px;
  color: var(--text-2);
}
.summary-line b { color: var(--text); font-variant-numeric: tabular-nums; }

.report-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 12.5px; }
.report-table th {
  text-align: left;
  color: var(--muted);
  font-weight: 600;
  font-size: 11.5px;
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
}
.report-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.report-table td { padding: 9px 10px; border-bottom: 1px solid color-mix(in srgb, var(--border) 65%, transparent); vertical-align: top; }
.report-table tr:last-child td { border-bottom: none; }

.stat { font-weight: 600; }
.stat-pass      { color: var(--pass); }
.stat-warn      { color: var(--warn); }
.stat-challenge { color: var(--challenge); }
.stat-fail      { color: var(--fail); }
/* 未测不是失败，所以不能用红色。灰字 + 不加粗，视觉权重压到最低 */
.stat-skipped   { color: var(--dead); font-weight: 400; }

.spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid color-mix(in srgb, var(--muted) 30%, transparent);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin .7s linear infinite;
  vertical-align: -2px;
}
@keyframes spin { to { transform: rotate(360deg); } }
.loading { text-align: center; color: var(--muted); padding: 44px 16px; line-height: 1.8; }

/* ================================================================ 提示条 */

.toast {
  position: fixed;
  bottom: 26px;
  left: 50%;
  transform: translateX(-50%);
  padding: 11px 18px;
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--text) 94%, transparent);
  color: var(--panel);
  box-shadow: var(--shadow-3);
  font-size: 13px;
  line-height: 1.6;
  z-index: 60;
  max-width: min(560px, 84vw);
  animation: toast-in .26s cubic-bezier(.2, .8, .3, 1);
}
@keyframes toast-in {
  from { opacity: 0; transform: translate(-50%, 12px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}

/* ================================================================ 自动剔除设置 */

.switch { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; cursor: pointer; }
.switch input { width: 16px; height: 16px; accent-color: var(--fail); }

/* 开着的时候整张卡片描边变红：它会在后台改池子，不能让人忘了 */
.panel.armed {
  border-color: color-mix(in srgb, var(--fail) 55%, var(--border));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--fail) 22%, transparent), var(--shadow-1);
}
.panel.armed > .panel-head { background: color-mix(in srgb, var(--fail) 7%, transparent); }
.panel.armed .switch span { color: var(--fail); font-weight: 650; }

.ar-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px 14px; padding: 15px 16px; }
.ar-form label { display: flex; flex-direction: column; gap: 5px; font-size: 11.5px; color: var(--muted); }
.ar-form input[type="number"] { width: 112px; }
.ar-form em { font-style: normal; font-size: 11px; }
#arScoreHint { flex-basis: 100%; font-size: 12px; color: var(--muted); min-height: 16px; }

/* 额度耗尽也剔：勾上会把整池搬进隔离区，说明文字得跟着变红 */
.ar-form .ar-check { flex-basis: 100%; flex-direction: row; align-items: baseline; gap: 8px; color: var(--text-2); }
.ar-form .ar-check input { margin: 0; }
.ar-form .ar-check em { flex: 1; line-height: 1.6; color: var(--muted); }
.ar-form .ar-check em.warn { color: var(--fail); }

/* 运行参数里那两个能改的。输入框宽一点：这里填的是秒数，动不动五位数 */
.rt-form { padding-bottom: 4px; }
.rt-form input[type="number"] { width: 132px; }
.rt-form em { color: var(--muted); min-width: 108px; }
.rt-err {
  flex-basis: 100%;
  color: var(--fail);
  font-size: 12.5px;
  line-height: 1.7;
}

/* 池底线填得比池子还大：开关是绿的但一个都不会剔，这条必须拦住视线 */
.ar-block {
  flex-basis: 100%;
  padding: 11px 13px;
  border: 1px solid color-mix(in srgb, var(--fail) 45%, transparent);
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--fail) 8%, transparent);
  color: var(--fail);
  font-size: 12.5px;
  line-height: 1.7;
}

/* ================================================================ 添加代理 / 隔离区 */

.modal-body textarea {
  width: 100%;
  height: auto;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.7;
  padding: 11px 13px;
  background: var(--panel-2);
  resize: vertical;
}
.modal-body .checkbox { margin: 12px 0 4px; font-size: 12.5px; }

.add-result {
  margin-top: 12px;
  padding: 11px 13px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--panel-2);
  font-size: 12.5px;
}
.add-err { margin-top: 6px; font-size: 11.5px; color: var(--fail); word-break: break-all; }

.grid th.check, .grid td.check { width: 36px; text-align: center; }
.grid td.check input { width: 15px; height: 15px; }
.grid tr.picked { background: color-mix(in srgb, var(--accent) 10%, transparent) !important; }
.grid td.reason { color: var(--muted); font-size: 11.5px; max-width: 400px; white-space: normal; }

/* ================================================================ 流量 */

.chart-wrap { padding: 10px 16px 14px; }
/* 高度写死、宽度自适应：SVG 用 preserveAspectRatio="none" 拉伸，不用监听 resize */
.chart { display: block; width: 100%; height: 220px; }
.chart path { fill: none; stroke-width: 1.8; vector-effect: non-scaling-stroke; stroke-linejoin: round; }
.chart .c-up   { stroke: var(--accent); }
.chart .c-down { stroke: var(--pass); }
/* 面积用半透明色，不用 <linearGradient>：那要在 SVG 里加 <defs> 和 id，
   而这张图是每 5 秒整块重画的，id 撞车比渐变好看那点收益麻烦得多 */
.chart .a-up   { fill: color-mix(in srgb, var(--accent) 16%, transparent); stroke: none; }
.chart .a-down { fill: color-mix(in srgb, var(--pass) 14%, transparent);   stroke: none; }
.chart .c-err  { fill: var(--fail); }
.chart .c-grid { stroke: var(--border); stroke-width: 1; vector-effect: non-scaling-stroke; stroke-dasharray: 3 4; }

.chart-axis {
  display: flex;
  gap: 10px;
  padding: 8px 2px 0;
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.legend { display: flex; gap: 18px; padding: 0 16px 14px; font-size: 11.5px; color: var(--muted); }
.legend i { display: inline-block; width: 9px; height: 9px; margin-right: 6px; border-radius: 3px; vertical-align: -1px; }
.legend .sw-up   { background: var(--accent); }
.legend .sw-down { background: var(--pass); }
.legend .sw-err  { background: var(--fail); }

.mini-bar {
  display: block;
  width: 100%;
  min-width: 64px;
  height: 6px;
  border-radius: var(--r-full);
  background: color-mix(in srgb, var(--muted) 16%, transparent);
  overflow: hidden;
}
.mini-bar i {
  display: block;
  height: 100%;
  border-radius: var(--r-full);
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  transition: width .4s ease;
}

/* ================================================================ 检测目标编辑器 */

.tg-list { padding: 4px 16px 6px; }

.tg-row {
  display: flex;
  gap: 12px;
  padding: 13px 0;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 70%, transparent);
}
.tg-row:last-child { border-bottom: none; }
/* 停用的那项整行压暗，一眼看出它不参与打分 */
.tg-row.off { opacity: .48; }

.tg-ord {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  width: 46px;
  flex: none;
  padding-top: 15px;
  font-variant-numeric: tabular-nums;
}
.tg-ord .icon.mini { width: 24px; height: 17px; font-size: 8px; line-height: 1; padding: 0; border-radius: var(--r-xs); }

.tg-fields { display: flex; flex-wrap: wrap; gap: 10px 12px; flex: 1; align-items: flex-end; min-width: 0; }
.tg-fields label { display: flex; flex-direction: column; gap: 5px; font-size: 11.5px; color: var(--muted); }
.tg-fields label.wide { flex: 1; min-width: 240px; }
.tg-fields input, .tg-fields select { height: 30px; font-size: 12.5px; }
.tg-fields input[data-f="key"]          { width: 122px; font-family: var(--mono); }
.tg-fields input[data-f="name"]         { width: 132px; }
.tg-fields input[data-f="url"],
.tg-fields input[data-f="target"]       { width: 100%; font-family: var(--mono); font-size: 12px; }
.tg-fields input[data-f="expectStatus"] { width: 104px; font-family: var(--mono); }
.tg-fields input[data-f="weight"]       { width: 76px; }
.tg-fields .tg-on { flex-direction: row; align-items: center; gap: 6px; padding-bottom: 8px; color: var(--text-2); }

.tg-err {
  margin: 4px 16px 14px;
  padding: 11px 13px;
  border: 1px solid color-mix(in srgb, var(--fail) 45%, transparent);
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--fail) 8%, transparent);
  color: var(--fail);
  font-size: 12.5px;
}

/* ================================================================ 空状态 */

.chart-wrap .empty, .panel > .empty, .log > .empty {
  text-align: center;
  color: var(--muted);
  padding: 44px 16px;
  line-height: 1.8;
}

/* ================================================================ 无障碍 */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}
