:root {
  --bg: #f7f7f5;
  --surface: #ffffff;
  --line: rgba(0, 0, 0, .10);
  --line-soft: rgba(0, 0, 0, .06);
  --ink: #1d1d1b;
  --ink-2: #5f5e5a;
  --ink-3: #8a8983;
  --accent: #534ab7;
  --human: #1d9e75;
  --bot: #b4b2a9;
  --ai: #7f77dd;
  --danger: #e24b4a;
  --warn: #ba7517;
  --radius: 12px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #16161a;
    --surface: #1e1e23;
    --line: rgba(255, 255, 255, .12);
    --line-soft: rgba(255, 255, 255, .07);
    --ink: #ececea;
    --ink-2: #a8a7a1;
    --ink-3: #75746f;
    --accent: #afa9ec;
    --human: #5dcaa5;
    --bot: #6f6e69;
    --ai: #afa9ec;
    --danger: #f09595;
    --warn: #ef9f27;
  }
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 14px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI",
        "PingFang SC", "Microsoft YaHei", "Hiragino Sans GB", sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* ---------- 顶栏 ---------- */
.topbar {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  padding: 10px 22px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 20;
}

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

.logo {
  width: 16px; height: 16px;
  border-radius: 4px;
  background: var(--accent);
  display: inline-block;
  flex: none;
}

.brand-text { font-weight: 500; font-size: 15px; }

.tz-badge {
  font-size: 11px;
  color: var(--ink-3);
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 2px 9px;
  white-space: nowrap;
}

.nav { display: flex; gap: 3px; flex-wrap: wrap; flex: 1; }

.nav a {
  color: var(--ink-2);
  text-decoration: none;
  padding: 5px 11px;
  border-radius: 7px;
  font-size: 13px;
  white-space: nowrap;
}

.nav a:hover { background: var(--bg); color: var(--ink); }
.nav a.on { background: var(--accent); color: #fff; }
@media (prefers-color-scheme: dark) { .nav a.on { color: #16161a; } }

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

select {
  font: inherit;
  font-size: 13px;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 5px 9px;
  max-width: 260px;
}

.linkbtn {
  font: inherit;
  font-size: 13px;
  color: var(--ink-2);
  background: none;
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 5px 11px;
  cursor: pointer;
}

.linkbtn:hover { color: var(--ink); background: var(--bg); }

/* ---------- 工具条 ---------- */
.toolbar {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
  padding: 10px 22px;
  border-bottom: 1px solid var(--line-soft);
}

.tb-label { font-size: 12px; color: var(--ink-3); }

.tb-chip {
  font-size: 12px;
  color: var(--ink-2);
  text-decoration: none;
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 3px 11px;
}

.tb-chip:hover { background: var(--surface); }
.tb-chip.on { background: var(--ink); color: var(--bg); border-color: var(--ink); }

.tb-sep {
  margin-left: auto;
  font-size: 12px;
  color: var(--ink-3);
}

/* ---------- 布局 ---------- */
.wrap { padding: 20px 22px 40px; max-width: 1560px; margin: 0 auto; }

.grid { display: grid; gap: 14px; }

/* 两栏的最小列宽从 420px 提到 560px。
   原来的 420px 在 1440px 宽屏下每栏只有约 660px，
   而「攻击目标路径 Top 20」「AI 抓取路径」这类表格有 3~5 列，
   数字列会被压到 60~100px，看起来像表格被挤扁。
   提高门槛后，含宽表格的卡片会自动落到单栏，拿满整行宽度。
   纯统计卡片（如总 PV / UV）内容短，两栏排列仍然紧凑。 */
.g2 { grid-template-columns: repeat(auto-fit, minmax(560px, 1fr)); }
.g3 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }

/* 宽表格卡片：内部表格列多时始终占满整行，不参与两栏并排 */
.g2 > .card-wide { grid-column: 1 / -1; }

/* 窄屏降级为单栏。
   必须显式写 1fr：CSS Grid 里 minmax(560px, 1fr) 的最小值 560px
   是硬下限，视口再窄列宽也不会收缩，卡片会直接撑破屏幕。
   之前把最小列宽从 420px 提到 560px 时漏了这条，
   导致手机端 390px 下卡片宽 560px、文档宽 582px，
   5 个页面横向溢出 192px。 */
@media (max-width: 640px) {
  .g2, .g3 { grid-template-columns: 1fr; }
  .wrap { padding: 16px 14px 32px; }
  .topbar, .toolbar { padding-left: 14px; padding-right: 14px; }
  .stats { grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 10px; }
  /* 横向进度条标签在窄屏占太宽，压缩它把空间让给条形 */
  .bar-label { width: 96px; font-size: 12px; }
  .bar-val { width: 64px; font-size: 11px; }

  /* 导航改为横向滚动。
     .nav 是 flex + wrap，链接又带 nowrap，
     窄屏下 7 个链接一行放不下就整体折行，
     变成「一行一个链接」的竖排导航，占掉半屏高度。
     改成单行 + 横向滚动条更符合手机习惯。 */
  .topbar { gap: 10px; padding-top: 8px; padding-bottom: 8px; }
  .nav {
    order: 10;
    width: 100%;
    flex: none;
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .nav::-webkit-scrollbar { display: none; }
  .nav a { padding: 5px 10px; font-size: 13px; }
}

.row { display: flex; gap: 14px; flex-wrap: wrap; }
.row > .card { flex: 1 1 320px; }

/* ---------- 卡片 ---------- */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px 18px;
  min-width: 0;
}

.card > h2 {
  margin: 0 0 14px;
  font-size: 14px;
  font-weight: 500;
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.card > h2 .hint { font-size: 12px; font-weight: 400; color: var(--ink-3); }

/* ---------- 指标块 ---------- */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
  gap: 12px;
  margin-bottom: 16px;
}

.stat {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 16px;
}

.stat .k { font-size: 12px; color: var(--ink-3); margin-bottom: 5px; }

.stat .v {
  font-size: 25px;
  font-weight: 500;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
}

.stat .u { font-size: 12px; color: var(--ink-3); margin-top: 3px; }
.stat.ok .v { color: var(--human); }
.stat.bad .v { color: var(--danger); }
.stat.warn .v { color: var(--warn); }

/* ---------- 表格 ---------- */
.scroll { overflow-x: auto; margin: 0 -4px; }

table { width: 100%; border-collapse: collapse; font-size: 13px; }

th, td {
  text-align: left;
  padding: 7px 10px;
  border-bottom: 1px solid var(--line-soft);
  white-space: nowrap;
}

th {
  font-weight: 500;
  color: var(--ink-3);
  font-size: 12px;
  position: sticky;
  top: 0;
  background: var(--surface);
  z-index: 1;
}

td.num, th.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  /* 数字列最小宽度保护。
     表格是 width:100%，长文本列（如 Referer）会吃掉几乎全部富余宽度，
     数字列可能被压到 60~90px，PV/UV 数字挤在一起甚至换行。
     给一个 92px 下限，保证「1,234,567」这类最坏情况也能单行显示。 */
  min-width: 92px;
}
tbody tr:hover { background: var(--bg); }
tbody tr:last-child td { border-bottom: none; }

/* 长文本列（路径、UA、Referer）允许换行并给出最小宽度。
   之前的实现对所有单元格一律 nowrap，导致两栏布局（.g2 的
   minmax(420px, 1fr)）遇到超长路径时，浏览器把该列压到几十像素，
   表格被挤成竖条（攻击页的「来源 IP Top 20」最明显）。
   这里改为：默认列 nowrap 保持紧凑，内容长的列显式加 .wrapcell。 */
th.wrapcell, td.wrapcell {
  white-space: normal;
  word-break: break-all;
  min-width: 220px;
  max-width: 460px;
  line-height: 1.5;
}

/* 路径类单元格用等宽字体 + 允许中途断行，避免长 URL 撑爆列宽 */
td.path {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
  word-break: break-all;
  white-space: normal;
  min-width: 200px;
  max-width: 420px;
  line-height: 1.5;
}

.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; }
.dim { color: var(--ink-3); }
.empty { color: var(--ink-3); font-size: 13px; padding: 18px 2px; }

/* ---------- 标签 ---------- */
.tag {
  display: inline-block;
  font-size: 11px;
  padding: 1px 8px;
  border-radius: 20px;
  border: 1px solid var(--line);
  color: var(--ink-2);
  white-space: nowrap;
}

.tag.human { color: var(--human); border-color: var(--human); }
.tag.ai    { color: var(--ai); border-color: var(--ai); }
.tag.bad   { color: var(--danger); border-color: var(--danger); }
.tag.warn  { color: var(--warn); border-color: var(--warn); }

/* ---------- 图表 ---------- */
.chart { position: relative; height: 260px; }
.chart.tall { height: 340px; }
.chart.short { height: 200px; }

.bar-row { display: flex; align-items: center; gap: 10px; margin-bottom: 7px; }
.bar-label { width: 128px; font-size: 13px; flex: none; }
.bar-track { flex: 1; height: 9px; background: var(--bg); border-radius: 5px; overflow: hidden; }
.bar-fill { height: 100%; border-radius: 5px; background: var(--accent); }
.bar-val { width: 78px; text-align: right; font-size: 12px; color: var(--ink-2); font-variant-numeric: tabular-nums; flex: none; }

/* ---------- 登录 ---------- */
.login-page {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 20px;
}

.login-box {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 30px 32px;
  width: 100%;
  max-width: 372px;
}

.login-box h1 { margin: 0 0 6px; font-size: 19px; font-weight: 500; }
.login-box p.sub { margin: 0 0 22px; font-size: 13px; color: var(--ink-3); }

.field { margin-bottom: 14px; }

.field label { display: block; font-size: 12px; color: var(--ink-3); margin-bottom: 5px; }

.field input {
  width: 100%;
  font: inherit;
  color: var(--ink);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 9px 11px;
}

.field input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }

.btn {
  width: 100%;
  font: inherit;
  font-weight: 500;
  color: #fff;
  background: var(--accent);
  border: none;
  border-radius: 8px;
  padding: 10px;
  cursor: pointer;
}

@media (prefers-color-scheme: dark) { .btn { color: #16161a; } }
.btn:hover { filter: brightness(1.08); }

.err {
  background: rgba(226, 75, 74, .10);
  border: 1px solid var(--danger);
  color: var(--danger);
  border-radius: 8px;
  padding: 8px 11px;
  font-size: 13px;
  margin-bottom: 16px;
}

.foot {
  padding: 16px 22px 26px;
  font-size: 12px;
  color: var(--ink-3);
  text-align: center;
}

.err-page { text-align: center; padding: 70px 20px; }
.err-page .code { font-size: 46px; font-weight: 500; color: var(--ink-3); }
.err-page .msg { margin: 10px 0 20px; color: var(--ink-2); }

.warnbox {
  background: rgba(186, 117, 23, .09);
  border: 1px solid var(--warn);
  border-radius: 8px;
  padding: 9px 12px;
  font-size: 12px;
  color: var(--ink-2);
  margin-bottom: 14px;
}

.warnbox b { color: var(--warn); font-weight: 500; }
/* ---------- 数据新鲜度状态条 ----------
   采集器是定时任务，可能静默失败。页面顶部必须明确显示数据延迟，
   否则用户会把几小时前的旧数字当成实时数据，这是统计系统最容易
   造成误判的地方。三个等级用颜色区分，ok 状态刻意做得非常轻，
   避免长期占据视觉注意力。 */
.freshbar {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 5px 16px;
  font-size: 12px;
  color: var(--ink-3);
  background: rgba(0, 0, 0, .02);
  border-bottom: 1px solid var(--line);
}

.freshbar .dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--human);
  flex: 0 0 auto;
}

/* ok：常态，弱化显示，不打扰 */
.fresh-ok .dot { background: var(--human); }

/* warn：数据偏旧，黄色提示 */
.fresh-warn {
  background: rgba(186, 117, 23, .10);
  color: var(--warn);
}
.fresh-warn .dot { background: var(--warn); }

/* bad：采集器可能已停，红 banner 明确告警 */
.fresh-bad {
  background: rgba(226, 75, 74, .12);
  color: var(--danger);
  font-weight: 500;
}
.fresh-bad .dot { background: var(--danger); }

/* unknown：查不到状态 */
.fresh-unknown .dot { background: var(--ink-3); }

.freshbar .lag {
  margin-left: auto;
  opacity: .75;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 640px) {
  .freshbar { padding: 5px 12px; font-size: 11px; }
}
