/* ══════════════════════════════════════════════════════════
   577 设计系统 —— 数据终端风
   ──────────────────────────────────────────────────────────
   取向:这是给人「读数字」的工具,不是给人「看着舒服」的官网。
   因此:
     · 浅色打底,卡片纯白 —— 层次靠「白 vs 灰」拉开,不靠投影堆叠
     · 所有数字走等宽 + tabular-nums,列对齐才能扫读
     · 用 1px 边框和背景层级构建结构
     · 颜色只承担语义(涨/跌/强调),不做装饰
     · 密度优先 —— 留白服务于分组,而不是撑场面

   所有颜色都必须走下面的 token。浅色模式下 1px 线是主要的结构手段,
   任何写死的色值都会在某个角落露出不属于这套配色的边。
   ══════════════════════════════════════════════════════════ */

:root {
  /* 底色:极浅冷灰。卡片用纯白,靠明度差浮出来,不需要阴影 */
  --bg:         #f4f6f9;
  --surface:    #ffffff;
  --surface-2:  #f0f3f7;
  --surface-3:  #e5eaf1;

  --line:        #e3e8ef;
  --line-strong: #ccd4e0;
  --line-hover:  #a9b4c4;

  /* 正文不用纯黑:纯黑配纯白对比过硬,长时间扫数据会累 */
  --text:   #10141c;
  --text-2: #4b5568;   /* 白底 7.5:1 */
  --text-3: #5c6579;   /* 白底 5.7:1,最浅的辅助文字也守住 4.5 */

  /* 强调色在白底上必须压深,深色模式那支亮蓝在白底会糊成一片 */
  --accent:        #1f6feb;
  --accent-hover:  #1a5fd0;
  --accent-active: #154fb0;
  --accent-soft:   #dbe9ff;
  --accent-dim:    #eff5ff;
  --accent-line:   #b9d3fb;
  --on-accent:     #ffffff;   /* 落在 accent 底上的文字 */

  /* 语义色:只用在涨跌与状态上 */
  --up:        #076c43;   /* 浅绿底上 5.6:1 */
  --up-soft:   #dcf3e7;
  --up-line:   #a9dcc4;
  --up-rgb:    7, 108, 67;   /* 供 rgba() 调透明度用 */
  --down:      #b8221b;   /* 浅红底上 5.4:1 */
  --down-soft: #fde7e5;
  --down-line: #f5b7b3;
  --warn:      #965d0d;

  --mask:      rgba(16, 20, 28, .42);  /* 模态遮罩 */
  --nav-bg:    rgba(255, 255, 255, .86);
  --hairline:  rgba(0, 0, 0, .07);
  --code-text: #1a4b8f;

  --radius:    10px;
  --radius-sm: 7px;

  --mono: ui-monospace, "SF Mono", "JetBrains Mono", "Roboto Mono", Menlo, Consolas, monospace;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", Roboto, sans-serif;

  --ease: cubic-bezier(.2, .8, .2, 1);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: var(--accent); text-decoration: none; }

/* 所有数字一律等宽等距:列才能对齐,才谈得上扫读 */
.num, .val, .kpi .num, .mono, .site-table .num, code, .code-box {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

::selection { background: var(--accent-soft); color: var(--text); }

/* 滚动条也要融进深色,否则一条亮边会毁掉整体 */
* { scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 6px; border: 3px solid var(--bg); }
*::-webkit-scrollbar-thumb:hover { background: var(--line-hover); }

/* ── 按钮 ───────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  border: 1px solid var(--accent); border-radius: var(--radius-sm);
  padding: 8px 15px; font-size: 13px; font-weight: 600; font-family: inherit;
  background: var(--accent); color: var(--on-accent);
  white-space: nowrap; flex: none;
  transition: background .14s, border-color .14s, color .14s;
}
.btn:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn:active { background: var(--accent-active); }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.btn.ghost { background: transparent; color: var(--text); border-color: var(--line-strong); }
.btn.ghost:hover { background: var(--surface-3); border-color: var(--line-hover); color: var(--text); }
.btn.sm { padding: 5px 11px; font-size: 12.5px; }
.btn.danger { background: transparent; color: var(--down); border-color: var(--down-line); }
.btn.danger:hover { background: var(--down-soft); border-color: var(--down); }

.container { max-width: 1200px; margin: 0 auto; padding: 0 24px; }

/* ── 顶部导航 ───────────────────────────────────────── */
.nav {
  background: var(--nav-bg);
  backdrop-filter: saturate(160%) blur(12px);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 20;
}
.nav .container { display: flex; align-items: center; justify-content: space-between; height: 56px; }
.logo { display: flex; align-items: center; gap: 9px; font-weight: 700; font-size: 17px;
  color: var(--text); letter-spacing: -.2px; }
.logo .dot { width: 22px; height: 22px; display: inline-block; flex: none;
  background: url("/favicon.svg") center / contain no-repeat; }
.nav-links { display: flex; gap: 20px; align-items: center; min-width: 0; }
.nav-links a { color: var(--text-2); font-weight: 500; font-size: 13.5px; white-space: nowrap;
  transition: color .14s; }
.nav-links a:hover { color: var(--text); }
.nav-links a.cur { color: var(--text); }
@media (max-width: 720px) {
  .nav .container { gap: 14px; }
  .nav-links { gap: 15px; overflow-x: auto; scrollbar-width: none; }
  .nav-links::-webkit-scrollbar { display: none; }
}

/* ── 落地页 ─────────────────────────────────────────── */
.hero { padding: 96px 0 72px; position: relative; overflow: hidden; }
/* 极淡的网格底纹:强化「终端/数据」的语境,不喧宾夺主 */
.hero::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background-image:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: radial-gradient(720px 340px at 50% 8%, #000 20%, transparent 78%);
  opacity: .5;
}
.hero .container { position: relative; }
.hero h1 { font-size: clamp(34px, 5.2vw, 54px); line-height: 1.12; margin: 0 0 20px;
  letter-spacing: -1.6px; font-weight: 700; max-width: 17ch; }
.hero h1 .hl { color: var(--accent); }
.hero p { font-size: 16.5px; color: var(--text-2); max-width: 56ch; margin: 0 0 34px; line-height: 1.7; }
.hero .cta { display: flex; gap: 12px; }

/* 数据条:用等宽数字 + 上下分栏,读起来像仪表读数 */
.stats-strip { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
  margin-top: 64px; background: var(--line); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden; }
.stats-strip .s { background: var(--surface); padding: 20px 22px; }
/* 这里的值是中英混排(如「1 行」),不能上等宽字体 ——
   等宽对 CJK 的字距处理很差,会把「1 行」拉出难看的空隙。
   等宽只留给纯数字场景(KPI、表格、时间戳)。 */
.stats-strip .s b { display: block; font-size: 25px; font-weight: 650;
  color: var(--text); letter-spacing: -.5px; font-variant-numeric: tabular-nums; }
.stats-strip .s p { margin: 5px 0 0; color: var(--text-3); font-size: 12.5px;
  letter-spacing: .04em; }
@media (max-width: 720px) { .stats-strip { grid-template-columns: repeat(2, 1fr); } }

.features { padding: 76px 0; }
.features h2 { font-size: 27px; margin: 0 0 8px; letter-spacing: -.6px; font-weight: 650; }
.features .sub { color: var(--text-2); margin: 0 0 40px; font-size: 15px; }
.grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1px;
  background: var(--line); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }

/* 卡片之间用 1px 缝隙拼接成一张表格,比一堆浮空圆角卡更像「控制台」 */
.feature { display: flex; flex-direction: column; background: var(--surface);
  padding: 24px; color: inherit; transition: background .16s; min-height: 100%; }
.feature:hover { background: var(--surface-2); }
.feature:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.feature .ico { width: 34px; height: 34px; border-radius: var(--radius-sm); background: var(--surface-3);
  border: 1px solid var(--line-strong);
  display: flex; align-items: center; justify-content: center; font-size: 17px; margin-bottom: 14px; }
.feature h3 { margin: 0 0 7px; font-size: 15px; font-weight: 600; color: var(--text); }
.feature p { margin: 0; color: var(--text-2); font-size: 13.5px; line-height: 1.65; }
.feature .more { margin-top: auto; padding-top: 14px; font-size: 12.5px; font-weight: 600;
  color: var(--accent); opacity: 0; transform: translateX(-3px); transition: .16s; }
.feature:hover .more, .feature:focus-visible .more { opacity: 1; transform: none; }
@media (hover: none) { .feature .more { opacity: 1; transform: none; } }
@media (max-width: 900px) { .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px) { .grid { grid-template-columns: 1fr; } }

.footer { border-top: 1px solid var(--line); padding: 30px 0; color: var(--text-3);
  font-size: 12.5px; background: var(--surface); }
.footer a { color: var(--text-2); }
.footer a:hover { color: var(--text); }

/* ── 登录 / 注册 ────────────────────────────────────── */
.auth-wrap { min-height: calc(100vh - 56px); display: flex; align-items: center;
  justify-content: center; padding: 40px 20px; }
.auth-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  width: 100%; max-width: 380px; padding: 30px; }
.auth-card h2 { margin: 0 0 6px; font-size: 21px; letter-spacing: -.4px; }
.auth-card .muted { color: var(--text-2); font-size: 13.5px; margin: 0 0 22px; }
.field { margin-bottom: 15px; }
.field label { display: block; font-size: 12px; font-weight: 600; margin-bottom: 6px;
  color: var(--text-2); letter-spacing: .04em; }
.field input { width: 100%; padding: 9px 12px; background: var(--bg);
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  font-size: 13.5px; color: var(--text); font-family: inherit; transition: border-color .14s; }
.field input::placeholder { color: var(--text-3); }
.field input:focus { outline: none; border-color: var(--accent); }
.tabs { display: flex; gap: 2px; background: var(--bg); padding: 3px; border: 1px solid var(--line);
  border-radius: var(--radius-sm); margin-bottom: 22px; }
.tabs button { flex: 1; white-space: nowrap; border: 0; background: transparent; padding: 7px;
  border-radius: 5px; cursor: pointer; font-weight: 600; color: var(--text-2);
  font-family: inherit; font-size: 13px; transition: .14s; }
.tabs button:hover { color: var(--text); }
.tabs button.active { background: var(--surface-3); color: var(--text); }
.msg { font-size: 12.5px; margin-top: 10px; min-height: 18px; }
.msg.err { color: var(--down); }
.msg.ok { color: var(--up); }

/* ── 看板骨架 ───────────────────────────────────────── */
.dash { display: flex; min-height: 100vh; }
.side { width: 232px; background: var(--surface); border-right: 1px solid var(--line);
  padding: 16px 12px; position: sticky; top: 0; height: 100vh; overflow-y: auto; flex: none; }
.side .logo { font-size: 15px; margin: 4px 8px 18px; }
.site-list { list-style: none; margin: 0; padding: 0; }
.site-list li { padding: 8px 10px; border-radius: var(--radius-sm); cursor: pointer;
  margin-bottom: 2px; font-size: 13px; color: var(--text-2);
  display: flex; justify-content: space-between; align-items: center; gap: 8px;
  transition: background .12s, color .12s; }
.site-list li > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.site-list li > span:last-child { font-family: var(--mono); font-size: 11.5px; color: var(--text-3); flex: none; }
.site-list li:hover { background: var(--surface-2); color: var(--text); }
.site-list li.active { background: var(--accent-dim); color: var(--accent); }
.site-list li.active > span:last-child { color: var(--accent); }
.site-list li.all-sites { border-bottom: 1px solid var(--line); border-radius: var(--radius-sm);
  margin-bottom: 8px; padding-bottom: 10px; font-weight: 600; color: var(--text); }
.side .add { width: 100%; margin-top: 10px; justify-content: center; }

.main { flex: 1; padding: 20px 26px 60px; overflow-x: hidden; min-width: 0; }
.topbar { display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 18px; flex-wrap: wrap; gap: 12px; }
.topbar h1 { font-size: 19px; margin: 0; font-weight: 600; letter-spacing: -.3px; }

/* 分段控件:统一给「时间范围」「设备」用 */
.ranges, .seg { display: inline-flex; gap: 2px; background: var(--surface); padding: 3px;
  border: 1px solid var(--line); border-radius: var(--radius-sm); }
.ranges button, .seg button { border: 0; white-space: nowrap; background: transparent;
  padding: 5px 12px; border-radius: 5px; cursor: pointer; font-size: 12.5px; font-weight: 500;
  color: var(--text-2); font-family: inherit; transition: .14s; }
.ranges button:hover, .seg button:hover { color: var(--text); }
.ranges button.active, .seg button.active { background: var(--surface-3); color: var(--text); font-weight: 600; }

/* ── KPI ────────────────────────────────────────────── */
.kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px;
  margin-bottom: 18px; background: var(--line); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden; }
.kpis.kpis6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.kpis.kpis8 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1460px) { .kpis.kpis6 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 1100px) { .kpis.kpis8 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { .kpis, .kpis.kpis6, .kpis.kpis8 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.kpi { background: var(--surface); padding: 14px 16px 15px; transition: background .16s; }
.kpi:hover { background: var(--surface-2); }
/* 小写标签 + 字距:是终端界面的典型语汇,也把视觉重量让给数字 */
.kpi .label { color: var(--text-3); font-size: 11.5px; letter-spacing: .05em; }
.kpi .num { font-size: 25px; font-weight: 600; margin-top: 5px; letter-spacing: -.8px;
  color: var(--text); line-height: 1.15; }

.kpi .delta { margin-top: 7px; font-size: 11.5px; display: flex; align-items: center;
  gap: 6px; min-height: 17px; white-space: nowrap; }
.kpi .delta .pill { font-weight: 600; font-family: var(--mono); font-size: 11px;
  padding: 1px 6px; border-radius: 4px; border: 1px solid transparent; }
.pill.up   { background: var(--up-soft);   color: var(--up);   border-color: var(--up-line); }
.pill.down { background: var(--down-soft); color: var(--down); border-color: var(--down-line); }
.pill.flat { background: var(--surface-3); color: var(--text-3); border-color: var(--line-strong); }
.kpi .delta .vs { color: var(--text-3); }

/* ── 筛选区 ─────────────────────────────────────────── */
.filters { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
.filters .flabel { font-size: 12px; color: var(--text-3); letter-spacing: .04em; }
.custom-range { display: none; align-items: center; gap: 7px; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 4px 8px; }
.custom-range.show { display: flex; }
.custom-range input[type="date"] { background: var(--bg); border: 1px solid var(--line-strong);
  border-radius: 5px; padding: 4px 8px; font-size: 12.5px; color: var(--text);
  font-family: var(--mono); color-scheme: dark; }
.custom-range input[type="date"]:focus { outline: none; border-color: var(--accent); }
.custom-range .sep { color: var(--text-3); font-size: 12px; }
.range-note { font-size: 12px; color: var(--text-3); }
.range-note b { color: var(--text-2); font-family: var(--mono); font-weight: 500; }
.filter-err { color: var(--down); font-size: 12px; }

/* 下钻标签 */
.chips { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.chip { display: inline-flex; align-items: center; gap: 7px; background: var(--accent-dim);
  color: var(--accent); border: 1px solid var(--accent-line); border-radius: 6px;
  padding: 3px 4px 3px 9px; font-size: 12px; font-weight: 500; }
.chip .k { color: var(--text-3); font-size: 11px; }
.chip .v { max-width: 190px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--mono); }
.chip .x { border: 0; background: transparent; color: var(--text-3); width: 17px; height: 17px;
  line-height: 1; border-radius: 4px; cursor: pointer; font-size: 13px;
  display: flex; align-items: center; justify-content: center; padding: 0; transition: .12s; }
.chip .x:hover { background: var(--accent); color: var(--on-accent); }
.chip-clear { border: 0; background: transparent; color: var(--text-3); font-size: 12px;
  cursor: pointer; font-family: inherit; padding: 0; }
.chip-clear:hover { color: var(--text); text-decoration: underline; }

/* ── 面板 ───────────────────────────────────────────── */
.panels { display: grid; grid-template-columns: 2fr 1fr; gap: 14px; margin-bottom: 14px; }
.panel { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 16px 18px; min-width: 0; }
.panel h3 { margin: 0 0 14px; font-size: 13px; font-weight: 600; color: var(--text);
  letter-spacing: .01em; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.panel.full { grid-column: 1 / -1; }
.two { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.three { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
@media (max-width: 900px) { .three, .panels, .two { grid-template-columns: 1fr; } }
.sub-title { font-size: 11.5px; font-weight: 500; color: var(--text-3);
  letter-spacing: .05em; margin-bottom: 8px; }
.drill-hint { font-size: 11px; color: var(--text-3); font-weight: 400;
  background: var(--surface-3); border: 1px solid var(--line); padding: 1px 7px; border-radius: 4px; }

/* ── 排行榜 ─────────────────────────────────────────── */
.rank { list-style: none; margin: 0; padding: 0; }
.rank li { display: flex; align-items: center; gap: 10px; padding: 6px 0; font-size: 13px;
  border-bottom: 1px solid var(--line); color: var(--text-2); }
.rank li:last-child { border-bottom: 0; }
.rank .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
/* 条形是背景刻度而非装饰:靠它一眼看出量级差 */
.rank .bar { height: 3px; border-radius: 2px; background: var(--accent); opacity: .55; flex: none; }
.rank .val { color: var(--text-2); min-width: 46px; text-align: right; font-size: 12.5px; flex: none; }
.rank li.drill { cursor: pointer; border-radius: 5px; padding-left: 6px; padding-right: 6px;
  margin: 0 -6px; transition: background .12s; }
.rank li.drill:hover { background: var(--surface-2); }
.rank li.drill.on { background: var(--accent-dim); }
.rank li.drill.on .name { color: var(--accent); font-weight: 600; }

.empty { color: var(--text-3); font-size: 12.5px; padding: 16px 0; text-align: center; }
.hint { color: var(--text-3); font-size: 12px; margin: 12px 0; line-height: 1.6; }

/* 实时 */
.realtime li { display: flex; gap: 10px; font-size: 12.5px; padding: 6px 0;
  border-bottom: 1px solid var(--line); }
.realtime .p { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
.realtime .meta { color: var(--text-3); font-family: var(--mono); font-size: 11.5px; flex: none; }
.dotlive { width: 6px; height: 6px; border-radius: 50%; background: var(--up); display: inline-block;
  box-shadow: 0 0 0 0 rgba(var(--up-rgb), .5); animation: pulse 1.8s infinite; flex: none; }
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(var(--up-rgb), .45); }
  70%  { box-shadow: 0 0 0 7px rgba(var(--up-rgb), 0); }
  100% { box-shadow: 0 0 0 0 rgba(var(--up-rgb), 0); }
}

/* ── 表格 ───────────────────────────────────────────── */
.site-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.site-table th { text-align: left; color: var(--text-3); font-size: 11.5px; font-weight: 500;
  letter-spacing: .05em; padding: 8px 10px; border-bottom: 1px solid var(--line-strong); }
.site-table td { padding: 9px 10px; border-bottom: 1px solid var(--line); color: var(--text-2); }
.site-table tr:last-child td { border-bottom: 0; }
.site-table tbody tr { cursor: pointer; transition: background .12s; }
.site-table tbody tr:hover td { background: var(--surface-2); }
.site-table .num { text-align: right; color: var(--text); }
.site-table .sname { font-weight: 600; color: var(--text); }
.site-table .sdomain { color: var(--text-3); font-size: 11.5px; font-weight: 400; margin-left: 8px;
  font-family: var(--mono); }
.site-table .share-cell { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }
.site-table .share-bar { height: 3px; border-radius: 2px; background: var(--accent); opacity: .55; min-width: 3px; }

.visits-table { font-size: 12.5px; min-width: 900px; }
.visits-table tbody tr { cursor: default; }
.visits-table td { padding: 8px 10px; white-space: nowrap; }
.visits-table td.path { max-width: 260px; overflow: hidden; text-overflow: ellipsis; color: var(--text); }
.daily-table { font-size: 12.5px; }
.daily-table td, .daily-table th { padding: 7px 10px; }
.daily-table tbody tr { cursor: default; }
.mono { font-size: 11.5px; color: var(--text-3); }

/* 分页 */
.pager { display: flex; align-items: center; gap: 8px; justify-content: flex-end;
  margin-top: 12px; flex-wrap: wrap; }
.pager button { border: 1px solid var(--line-strong); background: var(--surface); color: var(--text-2);
  padding: 5px 11px; border-radius: var(--radius-sm); cursor: pointer; font-size: 12.5px;
  font-family: inherit; transition: .12s; }
.pager button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.pager button:disabled { opacity: .35; cursor: not-allowed; }
.pager .info { font-size: 12px; color: var(--text-3); font-family: var(--mono); }

/* ── 访客足迹 ───────────────────────────────────────── */
.vid-btn { border: 0; background: transparent; color: var(--accent); cursor: pointer;
  font-family: var(--mono); font-size: 11.5px; padding: 2px 5px; border-radius: 4px; transition: .12s; }
.vid-btn:hover { background: var(--accent-dim); }

.journey { max-height: 60vh; overflow-y: auto; margin: 0 -4px; padding: 0 4px; }
.jsession { border: 1px solid var(--line); border-radius: var(--radius); padding: 13px 15px;
  margin-bottom: 10px; background: var(--bg); }
.jhead { display: flex; flex-wrap: wrap; gap: 13px; align-items: baseline; font-size: 11.5px;
  color: var(--text-3); padding-bottom: 9px; border-bottom: 1px solid var(--line); }
.jhead b { color: var(--text); font-size: 12.5px; font-family: var(--mono); font-weight: 500; }
.jsrc.utm      { color: var(--accent); font-weight: 600; }
.jsrc.referrer { color: var(--text-2); }
.jsrc.direct   { color: var(--text-3); }

.jsteps { list-style: none; margin: 9px 0 0; padding: 0; position: relative; }
/* 竖线把步骤串起来 —— 足迹的重点是「顺序」,结构要先于文字被看见 */
.jsteps::before { content: ''; position: absolute; left: 4px; top: 9px; bottom: 9px;
  width: 1px; background: var(--line-strong); }
.jsteps li { position: relative; padding: 5px 0 5px 20px; display: flex; gap: 12px;
  align-items: baseline; font-size: 12.5px; }
.jsteps li::before { content: ''; position: absolute; left: 0; top: 11px; width: 9px; height: 9px;
  border-radius: 50%; background: var(--bg); border: 1px solid var(--line-strong); }
.jsteps li:first-child::before { background: var(--accent); border-color: var(--accent); }
.jt { color: var(--text-3); font-size: 11px; font-family: var(--mono); flex: none; }
.jp { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
.jpath { color: var(--text-3); font-size: 11px; font-family: var(--mono);
  max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── 弹窗 ───────────────────────────────────────────── */
.modal-mask { position: fixed; inset: 0; background: var(--mask);
  backdrop-filter: blur(3px); display: none; align-items: center; justify-content: center;
  z-index: 40; padding: 20px; }
.modal-mask.show { display: flex; }
.modal { background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--radius);
  width: 100%; max-width: 500px; padding: 22px; }
.modal.wide { max-width: 780px; }
.modal h3 { margin: 0 0 16px; font-size: 15px; font-weight: 600; }

/* 代码块 */
.code-box { background: var(--surface-2); color: var(--code-text); border: 1px solid var(--line-strong);
  padding: 13px 15px; border-radius: var(--radius-sm); font-size: 12.5px;
  line-height: 1.65; position: relative;
  /* code-box 是 div,不加这个的话换行会被 HTML 折叠成空格 ——
     多行的接入示例(WordPress / Vue / Kotlin 那些)会挤成一整行没法看,
     复制出去也是一行,粘进编辑器直接是坏的。 */
  white-space: pre-wrap;
  /* 用 anywhere 而不是 word-break: break-all:后者会在标识符中间硬断,
     把 addEventListener 断成两截,读起来更糟。 */
  overflow-wrap: anywhere;
  /* 右上角有复制按钮,给它让出位置,否则会盖住第一行代码 */
  padding-right: 76px; }
.copy-btn { position: absolute; top: 9px; right: 9px; border: 1px solid var(--line-strong);
  background: var(--surface-2); color: var(--text-2); font-size: 11.5px; padding: 3px 10px;
  border-radius: 5px; cursor: pointer; font-family: var(--sans); transition: .12s; }
.copy-btn:hover { background: var(--surface-3); color: var(--text); border-color: var(--line-hover); }
.copy-btn.done { background: var(--up-soft); border-color: var(--up-line); color: var(--up); }

@media (max-width: 860px) {
  .side { display: none; }
  .main { padding: 16px 16px 48px; }
}

/* ── 点击热力图 ─────────────────────────────────────── */
.mini-select { background: var(--surface-3); color: var(--text); border: 1px solid var(--line-strong);
  border-radius: 5px; padding: 3px 8px; font-size: 12px; font-family: var(--mono);
  max-width: 260px; cursor: pointer; }
.mini-select:focus { outline: none; border-color: var(--accent); }
.mini-select:disabled { opacity: .5; cursor: not-allowed; }

.heat-wrap { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(220px, 1fr); gap: 20px; }
@media (max-width: 900px) { .heat-wrap { grid-template-columns: 1fr; } }

/* 画布容器:深底 + 内描边,让热区边缘不至于糊进背景 */
.heat-canvas-box { position: relative; background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--radius-sm); overflow: hidden; min-height: 200px; }
.heat-canvas-box canvas { display: block; width: 100%; }
.heat-empty { position: absolute; inset: 0; display: none; align-items: center; justify-content: center;
  color: var(--text-3); font-size: 12.5px; }

/* 纵向刻度:坐标是相对比例而非截图,给个参照才知道热区在页面的哪一段 */
.heat-ruler { position: absolute; inset: 0; pointer-events: none;
  display: flex; flex-direction: column; justify-content: space-between; padding: 2px 0; }
.heat-ruler span { font-size: 9.5px; color: var(--text-3); font-family: var(--mono);
  padding-left: 6px; border-top: 1px dashed var(--hairline); opacity: .8; }
.heat-ruler span:first-child { border-top: 0; }

.heat-side .rank li { padding: 5px 0; }
.heat-side .rank .name { font-size: 12.5px; }

/* ── 会话录制 ─────────────────────────────────────── */
.rec-table { font-size: 12.5px; min-width: 760px; }
.rec-table tbody tr { cursor: default; }
.rec-table td { padding: 8px 10px; white-space: nowrap; }
.rec-table td.path { max-width: 240px; overflow: hidden; text-overflow: ellipsis; color: var(--text); }
.rec-table .btn { margin-left: 4px; }

.rec-switch { display: flex; align-items: center; gap: 9px; margin-bottom: 18px;
  padding: 10px 12px; background: var(--bg); border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm); cursor: pointer; font-size: 13.5px; font-weight: 600; }
.rec-switch input { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; }

.rec-range { display: flex; align-items: center; gap: 12px; }
.rec-range input[type=range] { flex: 1; accent-color: var(--accent); }
.rec-range span { min-width: 42px; text-align: right; color: var(--text-2); font-size: 12.5px; }

.modal.player { max-width: 980px; }
/* 播放器内部是浅色页面快照,给个白底容器避免深色底把内容衬得发灰 */
.rec-player { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: auto;
  min-height: 300px; display: flex; align-items: center; justify-content: center; }
.rec-player .empty { color: var(--text-3); }

/* ── 付费墙 ─────────────────────────────────────────
   门禁不是错误状态,不能用红色报错的样子呈现。这里做成一块安静的引导:
   说清楚这是什么功能、为什么看不到、下一步做什么。 */
.locked { display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 44px 24px; gap: 9px;
  background: var(--surface-2); border: 1px dashed var(--line-strong);
  border-radius: var(--radius-sm); }
.lock-ico { font-size: 22px; opacity: .5; line-height: 1; }
.lock-title { font-size: 14.5px; font-weight: 650; color: var(--text); }
.lock-desc { margin: 0; font-size: 13px; color: var(--text-2); max-width: 42ch; line-height: 1.7; }
.lock-desc b { color: var(--text); }
.locked .btn { margin-top: 6px; }

/* ── 应用监控 ───────────────────────────────────────── */
.apm-table td { vertical-align: top; }
.apm-meta { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 1px; background: var(--line); border: 1px solid var(--line);
  border-radius: var(--radius-sm); overflow: hidden; }
.apm-meta > div { background: var(--surface); padding: 10px 13px; }
.apm-meta span { display: block; font-size: 11.5px; color: var(--text-3); margin-bottom: 3px; }
.apm-meta b { font-size: 14px; font-weight: 650; }

/* 行为轨迹:倒序展示,离出错最近的在最上面 */
.apm-crumbs { list-style: none; margin: 0; padding: 0;
  border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; }
.apm-crumbs li { display: flex; gap: 10px; align-items: baseline;
  padding: 8px 13px; font-size: 12.5px; border-bottom: 1px solid var(--line);
  background: var(--surface); }
.apm-crumbs li:last-child { border-bottom: 0; }
.apm-crumbs li.bad { background: var(--down-soft); color: var(--down); }
.apm-crumbs .ct { flex: none; width: 62px; font-size: 11px; color: var(--text-3);
  font-family: var(--mono); }
.apm-crumbs li.bad .ct { color: var(--down); }

.apm-stack { margin: 0; padding: 13px; font-family: var(--mono); font-size: 11.5px;
  line-height: 1.7; background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--radius-sm); overflow-x: auto; max-height: 260px;
  white-space: pre; color: var(--text-2); }

.apm-bds { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px; margin-top: 18px; }
.apm-bd-row { display: flex; justify-content: space-between; gap: 10px;
  padding: 4px 0; font-size: 12.5px; border-bottom: 1px dashed var(--hairline); }
.apm-bd-row:last-child { border-bottom: 0; }
.apm-bd-row span { color: var(--text-2); overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }

/* ── 告警设置 ───────────────────────────────────────── */
.alert-rules { display: grid; gap: 1px; background: var(--line);
  border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; }
.alert-rules label { display: block; background: var(--surface); padding: 11px 14px;
  cursor: pointer; font-size: 13.5px; }
.alert-rules label:hover { background: var(--surface-2); }
.alert-rules input[type=checkbox] { accent-color: var(--accent); margin-right: 6px; }
.alert-rules b { font-weight: 650; }
.alert-rules span { display: block; margin: 3px 0 0 22px; font-size: 12.5px; color: var(--text-3); }

.inp-mini { width: 70px; padding: 3px 8px; font-size: 12.5px; font-family: var(--mono);
  border: 1px solid var(--line-strong); border-radius: 5px;
  background: var(--surface); color: var(--text); }
.alert-mute { margin-top: 12px; font-size: 13.5px; }
.alert-mute .hint { display: block; margin-top: 4px; }

.alert-ch { display: flex; gap: 12px; align-items: flex-start; justify-content: space-between;
  padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  margin-bottom: 8px; background: var(--surface); flex-wrap: wrap; }
.alert-ch-main { flex: 1; min-width: 200px; }
.alert-ch-act { display: flex; gap: 6px; flex-wrap: wrap; }

.alert-add { margin-top: 14px; border: 1px dashed var(--line-strong);
  border-radius: var(--radius-sm); padding: 12px 14px; }
.alert-add summary { cursor: pointer; font-size: 13.5px; font-weight: 600; color: var(--accent); }
.fl2 { display: block; font-size: 12.5px; color: var(--text-2); margin: 10px 0 4px; }
.inp2 { width: 100%; padding: 8px 11px; font-size: 13px; font-family: inherit;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text); }
.err2 { color: var(--down); font-size: 12.5px; margin-top: 8px; min-height: 1em; }

/* ── Source Map ─────────────────────────────────────── */
.stack-toggle { display: flex; gap: 10px; align-items: center; margin-top: 8px; flex-wrap: wrap; }
.sm-rel { border: 1px solid var(--line); border-radius: var(--radius-sm);
  margin-bottom: 10px; overflow: hidden; }
.sm-rel-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 13px; background: var(--surface-2); border-bottom: 1px solid var(--line); }
.sm-rel-head .meta { flex: 1; }
.sm-file { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 8px 13px; font-size: 12.5px; border-bottom: 1px solid var(--line); }
.sm-file:last-child { border-bottom: 0; }
.sm-file .meta { flex: 1; }

/* ── 错误 ↔ 录像 ────────────────────────────────────── */
.apm-replay { display: flex; align-items: center; justify-content: space-between;
  gap: 14px; flex-wrap: wrap; margin-top: 18px;
  padding: 13px 16px; border-radius: var(--radius-sm);
  background: var(--accent-dim); border: 1px solid var(--accent-line); }
.apm-replay b { font-size: 13.5px; font-weight: 650; }
.apm-replay .meta { margin-top: 3px; }

/* ── 看板标签 ───────────────────────────────────────
   统计、监控、录制是三种不同的使用场景。混在一个长页面里的话,
   来查错误的人得先滚过十几张统计图表。 */
.dash-tabs { display: flex; gap: 2px; margin-bottom: 18px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 3px; width: fit-content; }
.dash-tabs button { border: 0; background: transparent; cursor: pointer;
  font-family: inherit; font-size: 13.5px; font-weight: 550; color: var(--text-2);
  padding: 7px 18px; border-radius: 5px;
  display: inline-flex; align-items: center; gap: 7px;
  transition: background .14s, color .14s; }
.dash-tabs button:hover { background: var(--surface-2); color: var(--text); }
.dash-tabs button.cur { background: var(--surface-3); color: var(--text); font-weight: 650; }
.dash-tabs button:focus-visible { outline: 2px solid var(--accent); outline-offset: -1px; }

/* 未解决问题数的角标:不切过去也能看到「有事发生」 */
.tab-badge { display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px;
  background: var(--down); color: #fff; font-size: 11px; font-weight: 700;
  font-variant-numeric: tabular-nums; }

/* ══════════════════ 看板:来源限制 / 母包 / 一键拉起 ══════════════════
   这几块的样式原本写在 dashboard.html 的 <style> 里 —— 但那个文件
   根本没有内联样式块,只 link 了本文件。写进去的规则一条都没生效,
   标签和输入框全挤在一行。样式统一放这里,不再假设页面里有 style 标签。 */

/* ── 来源限制 ── */
.origin-guard { border-top: 1px solid var(--line); margin-top: 16px; padding-top: 14px; }
.og-row { display: flex; gap: 10px; align-items: flex-start; cursor: pointer; }
.og-row input { margin-top: 3px; flex: none; }
.og-row b { font-size: 13.5px; display: block; }
.og-row em { font-style: normal; font-size: 12px; color: var(--text-3);
  display: block; margin-top: 3px; line-height: 1.6; }
.og-input { width: 100%; margin-top: 10px; padding: 8px 11px; font-size: 13px;
  font-family: var(--mono); border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm); background: var(--surface); color: var(--text); }
.og-input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.og-hint { font-size: 11.5px; color: var(--text-3); margin-top: 6px; line-height: 1.6; }
.og-msg { font-size: 12px; margin-top: 8px; min-height: 1em; }
.og-msg.ok { color: var(--up); }
.og-msg.err { color: var(--down); }

/* ── 母包 ── */
.apk-box { border: 1px dashed var(--line-strong); border-radius: var(--radius-sm); padding: 16px; }
.apk-meta { display: flex; gap: 16px; align-items: baseline; flex-wrap: wrap; font-size: 13.5px; }

/* ── 一键拉起 ── */
.al-grid { display: grid; gap: 20px; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 820px) {
  .al-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}
/* 标签必须独占一行,否则会和输入框挤在一起 */
.al-grid .fl { display: block; font-size: 12.5px; color: var(--text-2); margin: 14px 0 5px; }
.al-grid > div > .fl:first-child { margin-top: 0; }
.al-grid textarea.inp2 { font-family: var(--mono); font-size: 11.5px; resize: vertical; }
.al-grid .fhelp,
.apk-box .fhelp { font-size: 11.5px; color: var(--text-3); margin-top: 5px; line-height: 1.6; }
.al-wk { margin-top: 18px; }
.al-wk .fhelp { font-size: 12px; color: var(--text-3); margin-bottom: 6px; }
