/* IP99 前端样式 —— 自包含，无外部依赖；深浅色跟随系统 */

/* 字体自托管，随二进制分发（合计 47KB）。
   刻意不外链 Google Fonts：站点面向国内用户，外部字体源的可达性不受我们控制，
   加载失败时整站排版会突变；自托管还省掉一条 CSP 放行项。
   中文不受影响——这两个字体没有中文字形，中文一律回落系统字体栈。 */
@font-face {
  font-family: "Public Sans";
  src: url("/fonts/public-sans-var.woff2") format("woff2");
  font-weight: 100 900;   /* 可变字体，一个文件覆盖全部字重 */
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fonts/ibm-plex-mono-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fonts/ibm-plex-mono-600.woff2") format("woff2");
  font-weight: 600; font-style: normal; font-display: swap;
}

:root {
  --font-sans: "Public Sans", -apple-system, BlinkMacSystemFont, "PingFang SC",
               "Hiragino Sans GB", "Microsoft YaHei", "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --bg: #f6f8fb;
  --bg-card: #ffffff;
  --text: #101828;
  --text-dim: #5b6778;
  --text-faint: #8593a6;
  --line: #e3e9f2;
  --accent: #2563eb;
  --accent-ink: #ffffff;
  --ok: #16a34a;
  --low: #16a34a;
  --medium: #d97706;
  --high: #ea580c;
  --critical: #dc2626;
  /* Pulse 证据卡的强调色。默认中性，JS 按处置建议档位覆写
     （challenge/signal/monitor/none 各有其色）——声明在此保证
     JS 未跑或取不到 Pulse 时卡片仍是完整的中性样式。 */
  --pulse-color: #5b6778;
  --code-bg: #0f172a;
  --code-ink: #dbe4f5;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0b1020;
    --bg-card: #141a2e;
    --text: #e7ecf6;
    --text-dim: #9aa7bf;
    --text-faint: #74839c;
    --line: #232c45;
    --accent: #3b82f6;
    --code-bg: #0a0f1e;
    /* 暗色下中性色要提亮，否则 Pulse 卡左边框在深底上看不见 */
    --pulse-color: #9aa7bf;
  }
}

* { box-sizing: border-box; }
/* hidden 属性必须始终隐藏，压过下面各类 display 声明 */
[hidden] { display: none !important; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--text);
  line-height: 1.6;
}
.container { max-width: 960px; margin: 0 auto; padding: 0 20px; }

/* 锚点跳转要避开 sticky 页头。
   页头 57px 高、position:sticky top:0，而锚点默认把目标顶到 y=0——
   实测 #query 和 #api 落点整个被页头盖住，用户点了导航像是没反应。
   72px = 页头高 + 一点呼吸。:target 管 hash 跳转，section[id] 管
   scrollIntoView 这类程序化滚动（后者不会命中 :target）。 */
:target, section[id] { scroll-margin-top: 72px; }
a { color: var(--accent); text-decoration: none; }

/* 头部 */
.site-header {
  position: sticky; top: 0; z-index: 10;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.header-inner { display: flex; align-items: center; justify-content: space-between; height: 56px; }
.brand { display: flex; align-items: center; gap: 8px; color: var(--text); font-weight: 700; }
.brand-mark {
  display: inline-grid; place-items: center;
  width: 28px; height: 28px; border-radius: 7px;
  background: var(--accent); color: var(--accent-ink);
  font-size: 13px; font-weight: 800;
}
.nav { display: flex; align-items: center; gap: 20px; font-size: 14px; }
.nav a { color: var(--text-dim); }
.nav a:hover { color: var(--text); }

/* 导航项永不断词。不加这条时中文会被压成竖排（「查询」变成上下两个字），
   登录按钮更会从 34px 撑到 100px 以上，把 56px 的头部整个顶破。 */
.nav a, .btn-login { white-space: nowrap; }

/* 窄屏把头部拆成两行：品牌一行，导航单独一行并允许横向滚动。
   刻意不用 display:none 藏掉导航项——「各国 IP 段」是落地页在 Google 侧
   唯一的发现路径（Googlebot 从不取 sitemap），藏起来等于把它又变回孤岛。
   680px 这个断点是实测出来的：五项导航在此以下必然挤压。 */
@media (max-width: 680px) {
  .header-inner {
    height: auto; min-height: 56px; flex-wrap: wrap;
    row-gap: 2px; padding-top: 8px; padding-bottom: 8px;
  }
  .nav {
    width: 100%; gap: 16px; overflow-x: auto;
    scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .nav::-webkit-scrollbar { display: none; }
  /* 品牌与登录同处第一行，导航整行排到第二行 */
  .auth-area { order: 1; margin-left: auto; }
  .nav { order: 2; }
}

/* 登录态 */
.auth-area { display: inline-flex; align-items: center; }
.btn-login {
  border: 1.5px solid var(--accent); background: none; color: var(--accent);
  font: inherit; font-size: 14px; padding: 5px 16px; border-radius: 8px; cursor: pointer;
}
.btn-login:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.user-box { display: inline-flex; align-items: center; gap: 10px; }
/* 脱敏后的邮箱仍可能较长，限宽并省略，避免把顶栏挤变形 */
.user-email {
  color: var(--text);
  max-width: 18ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.btn-logout {
  border: none; background: none; color: var(--text-dim); font: inherit; font-size: 13px; cursor: pointer;
}
.btn-logout:hover { color: var(--critical); }

/* 额度是状态。原来 13px 而邻行 14px——1px 的差不构成层级，只是噪声；
   改为同字号，用更浅的颜色区分。 */
/* 额度是状态，不是动作。原来 13px 而邻行 14px——1px 的差不构成层级，
   只是噪声；改为同字号，用更浅的颜色把它降一档。 */
.quota-line {
  margin-top: 10px; font-size: 14px; color: var(--text-faint);
}
.quota-line a { cursor: pointer; }

/* 登录弹窗 */
.modal-mask {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(0,0,0,0.5); backdrop-filter: blur(2px);
  display: grid; place-items: center; padding: 20px;
}
.modal {
  position: relative; width: 100%; max-width: 380px;
  background: var(--bg-card); border: 1px solid var(--line);
  border-radius: 16px; padding: 28px 26px 22px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.25);
}
.modal h2 { margin: 0 0 6px; font-size: 20px; }
.modal-sub { margin: 0 0 20px; font-size: 13.5px; color: var(--text-dim); }
.modal-close {
  position: absolute; top: 14px; right: 16px;
  border: none; background: none; font-size: 24px; line-height: 1;
  color: var(--text-dim); cursor: pointer;
}
.modal-close:hover { color: var(--text); }
.field { display: block; margin-bottom: 16px; }
.field > span { display: block; font-size: 13px; color: var(--text-dim); margin-bottom: 6px; }
.field input {
  width: 100%; padding: 11px 13px; font-size: 15px;
  border: 1.5px solid var(--line); border-radius: 10px;
  background: var(--bg); color: var(--text); font-variant-numeric: tabular-nums;
}
.field input:focus { outline: none; border-color: var(--accent); }
.code-row { display: flex; gap: 8px; }
.code-row input { flex: 1; min-width: 0; }
.btn-code {
  flex: none; white-space: nowrap; padding: 0 14px;
  border: 1.5px solid var(--line); border-radius: 10px;
  background: var(--bg); color: var(--accent); font: inherit; font-size: 13px; cursor: pointer;
}
.btn-code:hover:not(:disabled) { border-color: var(--accent); }
.btn-code:disabled { color: var(--text-dim); cursor: not-allowed; }
.btn-submit {
  width: 100%; margin-top: 4px; padding: 12px; font-size: 15px; font-weight: 600;
  border: none; border-radius: 10px; background: var(--accent); color: var(--accent-ink); cursor: pointer;
}
.btn-submit:disabled { opacity: 0.6; cursor: wait; }
.modal-alert {
  margin-bottom: 14px; padding: 9px 12px; border-radius: 9px; font-size: 13px;
  background: color-mix(in srgb, var(--critical) 12%, var(--bg-card));
  border: 1px solid color-mix(in srgb, var(--critical) 35%, transparent);
}
.modal-note { margin: 14px 0 0; font-size: 12px; color: var(--text-dim); text-align: center; }

/* 搜索区 */
.hero { padding: 64px 0 40px; text-align: center; }
.hero h1 { margin: 0 0 8px; font-size: clamp(26px, 4.5vw, 38px); letter-spacing: -0.02em; }
.hero .sub { margin: 0 auto 28px; max-width: 560px; color: var(--text-dim); }
.search {
  display: flex; gap: 10px; max-width: 560px; margin: 0 auto;
}
.search input {
  flex: 1; min-width: 0;
  padding: 13px 16px; font-size: 16px;
  border: 1.5px solid var(--line); border-radius: 12px;
  background: var(--bg-card); color: var(--text);
  font-variant-numeric: tabular-nums;
}
.search input:focus { outline: none; border-color: var(--accent); }
.search button {
  padding: 13px 26px; font-size: 16px; font-weight: 600;
  border: none; border-radius: 12px; cursor: pointer;
  background: var(--accent); color: var(--accent-ink);
}
.search button:disabled { opacity: 0.6; cursor: wait; }
.self-line { margin-top: 14px; font-size: 14px; color: var(--text-dim); }
.self-ip {
  border: none; background: none; padding: 0;
  color: var(--accent); font: inherit; cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.alert {
  max-width: 560px; margin: 16px auto 0;
  padding: 10px 14px; border-radius: 10px; font-size: 14px; text-align: left;
  background: color-mix(in srgb, var(--critical) 12%, var(--bg-card));
  border: 1px solid color-mix(in srgb, var(--critical) 35%, transparent);
}

/* 结果区 */
.result { padding-bottom: 16px; }
.banner {
  margin-bottom: 16px; padding: 10px 14px;
  border-radius: 10px; font-size: 14px;
  background: color-mix(in srgb, var(--medium) 14%, var(--bg-card));
  border: 1px solid color-mix(in srgb, var(--medium) 40%, transparent);
}
.card {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 20px;
}
.card-title { margin: 0 0 12px; font-size: 15px; color: var(--text-dim); font-weight: 600; }
.grid-top, .grid-bottom { display: grid; gap: 16px; margin-bottom: 16px; }
.grid-top { grid-template-columns: 5fr 4fr; }
.grid-bottom { grid-template-columns: 1fr 1fr; }
@media (max-width: 720px) {
  .grid-top, .grid-bottom { grid-template-columns: 1fr; }
}

/* 评分卡 */
.score-card { display: flex; align-items: center; gap: 24px; }
.gauge { position: relative; width: 150px; height: 150px; flex: none; }
.gauge svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.gauge-bg { fill: none; stroke: var(--line); stroke-width: 11; }
.gauge-fg {
  fill: none; stroke: var(--level-color, var(--accent));
  stroke-width: 11; stroke-linecap: round;
  stroke-dasharray: 326.7;
  stroke-dashoffset: 326.7;
  transition: stroke-dashoffset 0.7s ease, stroke 0.3s ease;
}
.gauge-text { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; }
.gauge-score { font-size: 36px; font-weight: 800; line-height: 1.1; font-variant-numeric: tabular-nums; }
.gauge-cap { font-size: 12px; color: var(--text-dim); }
.score-side { min-width: 0; }
.queried-ip {
  font-size: 20px; font-weight: 700; word-break: break-all;
  font-variant-numeric: tabular-nums; margin-bottom: 8px;
}
.level-badge {
  display: inline-block; padding: 3px 12px; border-radius: 999px;
  font-size: 13px; font-weight: 700;
  color: #fff; background: var(--level-color, var(--accent));
  margin-bottom: 10px;
}
/* 0 分时的语义说明。刻意排在徽标和标签之间：读者的视线从「0」下来，
   先撞上这句话，再看到标签，才不会把 0 读成「安全」。 */
.level-note {
  margin: 0 0 10px; max-width: 42em;
  font-size: 12.5px; line-height: 1.65; color: var(--text-dim);
}
.tags { display: flex; flex-wrap: wrap; gap: 6px; }
.tag {
  font-size: 12px; padding: 2px 10px; border-radius: 999px;
  background: color-mix(in srgb, var(--level-color, var(--accent)) 14%, var(--bg-card));
  border: 1px solid color-mix(in srgb, var(--level-color, var(--accent)) 38%, transparent);
}
.tag small { opacity: 0.72; font-size: 10.5px; font-variant-numeric: tabular-nums; }

/* 信号 */
.signals {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: 1fr 1fr; gap: 8px 16px;
}
.signals li {
  display: flex; align-items: center; gap: 8px;
  font-size: 14px; padding: 6px 0;
}
.dot { width: 9px; height: 9px; border-radius: 50%; flex: none; background: var(--line); }
.signals li.on { font-weight: 600; }
.signals li.on .dot { background: var(--critical); box-shadow: 0 0 0 3px color-mix(in srgb, var(--critical) 22%, transparent); }
.signals li.off { color: var(--text-dim); }

/* 键值对 */
.kv { display: grid; grid-template-columns: auto 1fr; gap: 6px 18px; margin: 0; font-size: 14px; }
.kv dt { color: var(--text-dim); }
.kv dd { margin: 0; font-weight: 500; word-break: break-all; }

.meta-line { color: var(--text-dim); font-size: 12.5px; text-align: right; margin: 0 4px 8px; }

/* API 区 */
/* 只写纵向内边距。用简写 padding 会把 .container 的左右内边距清零
   —— 两者特异性相同而这条在后面，结果是整段文字顶到视口边缘。 */
.api { padding-top: 40px; padding-bottom: 64px; }
.api h2 { margin: 0 0 6px; font-size: 24px; }
.api .sub { margin: 0 0 20px; color: var(--text-dim); }
.api-card { padding: 22px; }
.api-row { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; }
.method {
  font-size: 12px; font-weight: 800; letter-spacing: 0.04em;
  color: var(--ok); border: 1px solid color-mix(in srgb, var(--ok) 45%, transparent);
  padding: 2px 8px; border-radius: 6px;
}
.api-row code { font-size: 14.5px; }
pre {
  margin: 0 0 14px; padding: 14px 16px; overflow-x: auto;
  background: var(--code-bg); color: var(--code-ink);
  border-radius: 10px; font-size: 13px; line-height: 1.55;
}
pre code { font-family: var(--font-mono); }
details { margin-bottom: 14px; }
details summary { cursor: pointer; color: var(--text-dim); font-size: 14px; margin-bottom: 8px; }
.plans { width: 100%; border-collapse: collapse; font-size: 14px; margin-bottom: 14px; }
.plans th, .plans td { text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--line); }
.plans th { color: var(--text-dim); font-weight: 600; }
.api-note { margin: 0; font-size: 14px; color: var(--text-dim); }

/* 页脚 */
.site-footer { border-top: 1px solid var(--line); padding: 20px 0 28px; }
.site-footer .container {
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 8px;
  color: var(--text-dim); font-size: 13px;
}
.site-footer .beian { color: var(--text-dim); }
.site-footer .beian:hover { color: var(--text); }

/* ---- 联系销售 / API Key 自助管理 ---- */
/* 容器与卡片拆成两层，不要让同一个元素兼任。
   两者在 padding 上必然打架：.container 给左右留白定出内容边界，
   而卡片要自己的内边距——简写 padding 会把容器那份覆盖掉，
   结果这一段的标题比同级的 #api 右移几个像素。
   这个坑先后踩了两次（.api 一次、.contact 一次），拆层是唯一稳的解法。 */
/* 与「开发者 API」用同一套纵向节奏：标题在卡片外，卡片承载表单。
   只写单边内边距——简写会覆盖 .container 的左右留白（见 TestContainerPaddingNotOverridden）。 */
.geo-nav { padding-top: 40px; padding-bottom: 8px; }
.geo-nav h2 { margin: 0 0 6px; font-size: 24px; }
.geo-nav .sub { margin: 0 0 18px; color: var(--text-dim); max-width: 62ch; }
.geo-links { display: flex; flex-wrap: wrap; gap: 8px; }
.geo-links a {
  display: inline-block; padding: 6px 13px; border: 1px solid var(--line);
  border-radius: 999px; background: var(--bg-card); color: var(--text);
  text-decoration: none; font-size: 14.5px; line-height: 1.4;
}
.geo-links a:hover, .geo-links a:focus-visible { border-color: var(--accent); color: var(--accent); }
.geo-more { margin: 16px 0 0; font-size: 14.5px; display: flex; flex-wrap: wrap; gap: 6px 18px; }
.geo-more span { color: var(--text-dim); }

.contact-section { padding-top: 40px; padding-bottom: 64px; }
.contact-section h2 { margin: 0 0 6px; font-size: 24px; }
.contact-section > .sub { margin: 0 0 20px; color: var(--text-dim); }

.contact-card {
  background: var(--bg-card); border: 1px solid var(--line);
  border-radius: 14px; padding: 22px;
}
.contact-card .sub { color: var(--text-dim); margin: 0 0 14px; font-size: 14px; }
.contact-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; }
.contact-foot { display: flex; align-items: center; gap: 12px; margin-top: 12px; flex-wrap: wrap; }
.contact-card .field b { color: var(--critical); }
.contact-card textarea {
  width: 100%; box-sizing: border-box; resize: vertical;
  font: inherit; padding: 9px 11px; border: 1px solid var(--line);
  border-radius: 8px; background: var(--bg); color: var(--text);
}
.alert.ok { color: var(--ok); }

.keys-box { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--line); }
.keys-box h3 { font-size: 15px; margin: 0 0 10px; }
.keys-actions { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.key-row { display: flex; align-items: center; gap: 8px; padding: 6px 0; flex-wrap: wrap; }
.btn-mini {
  font: inherit; font-size: 12px; padding: 3px 10px; cursor: pointer;
  border: 1px solid var(--line); border-radius: 6px;
  background: transparent; color: var(--text-dim);
}
.btn-mini:hover { color: var(--critical); border-color: var(--critical); }
.key-reveal { margin-top: 12px; padding: 12px; border-radius: 8px; background: var(--bg); border: 1px solid var(--medium); }
.key-reveal .warn { color: var(--medium); font-size: 13px; margin-bottom: 6px; }
/* 密钥要能整段选中复制，长串必须换行而不是溢出 */
.key-reveal code { display: block; word-break: break-all; user-select: all; }

/* ---- 流量与行为 ---- */
.tf-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 14px; flex-wrap: wrap; }
.funnel { display: flex; flex-direction: column; gap: 8px; }
.funnel-row { display: grid; grid-template-columns: 130px 1fr 96px; align-items: center; gap: 12px; }
.funnel-row .fl { color: var(--text-dim); font-size: 13px; }
.funnel-bar { height: 26px; border-radius: 5px; background: var(--accent); min-width: 2px; transition: width .3s; }
.funnel-row .fv { text-align: right; font-variant-numeric: tabular-nums; }
.funnel-row .fv small { color: var(--text-dim); margin-left: 6px; }
.funnel-drop { color: var(--critical); font-size: 12px; }

/* ---------- 改版新增（2026-08-22）---------- */

/* 主按钮。index.html 里 #c-submit 一直写着 class="btn-primary"，
   而样式表里从来没有这个类——提交按钮一直是浏览器默认样式。
   既有的 .btn-submit 是登录弹窗里的通栏按钮，形态不同，不能直接复用。 */
.btn-primary {
  padding: 11px 24px; font-size: 15px; font-weight: 600;
  border: none; border-radius: 10px; cursor: pointer;
  background: var(--accent); color: var(--accent-ink);
}
.btn-primary:hover { background: color-mix(in srgb, var(--accent) 88%, #000); }
.btn-primary:disabled { opacity: .6; cursor: wait; }

/* IP 地址与数字统一走等宽并对齐数位：这个产品满屏都是地址和分数，
   比例字体下数位不对齐，扫读时很难比较。 */
#ip-input, #queried-ip, .ex, .kv-val, .sig-time {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

/* 「可点即查」的地址行。合并了原来的「你的 IP」与「试试示例」两行：
   它们是同一类动作，分开只会让搜索框下面堆三行同色小字，谁都不突出。 */
.try-line {
  margin-top: 14px; text-align: center; font-size: 14px; color: var(--text-dim);
  display: flex; flex-wrap: wrap; justify-content: center; align-items: baseline;
  gap: 2px 6px;
}
/* 这两个包裹层只用于整体显隐（没有对应数据时隐藏），
   不该成为 flex 子元素——否则它们内部的 IP 与标签拿不到 gap，会挤在一起。 */
#self-line, #ex-risky { display: contents; }
#self-line[hidden], #ex-risky[hidden] { display: none; }
.ex {
  background: none; border: none; padding: 0 2px; cursor: pointer;
  color: var(--accent); font-size: 14px;
}
.ex:hover { text-decoration: underline; }
.ex-note { color: var(--text-dim); }
.ex-sep { margin: 0 6px; color: var(--line); }

/* 能力指标卡。耗时那张在拿到真实数值前隐藏——
   显示一个「—」比不显示更像故障。 */
.stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px; margin: 34px auto 0; max-width: 760px;
}
.stat {
  background: var(--bg-card); border: 1px solid var(--line); border-radius: 12px;
  padding: 16px 18px;
}
.stat b {
  display: block; font-size: 22px; font-weight: 700; color: var(--text);
  line-height: 1.2; letter-spacing: -.01em;
}
.stat span { display: block; font-size: 13px; color: var(--text-dim); margin-top: 4px; }

/* 风险信号表：把「最近捕获」从 tooltip 提到正文。
   一个信号命中于三天前还是一小时前，风控上的含义完全不同，
   藏在 hover 里等于没有。 */
.sig-table { width: 100%; border-collapse: collapse; font-size: 14.5px; }
.sig-table th {
  text-align: left; font-size: 12px; letter-spacing: .05em; color: var(--text-dim);
  font-weight: 600; padding: 0 12px 8px; border-bottom: 1px solid var(--line);
}
.sig-table td { padding: 9px 12px; border-bottom: 1px solid var(--line); }
.sig-table tr:last-child td { border-bottom: none; }
.sig-table tr.hit { background: color-mix(in srgb, var(--critical) 6%, transparent); }
.sig-table tr.hit td:first-child { font-weight: 600; }
.sig-verdict { white-space: nowrap; }
.sig-table tr.hit .sig-verdict { color: var(--critical); font-weight: 600; }
.sig-table tr.miss .sig-verdict { color: var(--text-dim); }
.sig-time { color: var(--text-dim); font-size: 13px; white-space: nowrap; }
.sig-count { float: right; font-size: 13px; color: var(--text-dim); font-weight: 400; }

/* API 文档里的可折叠细节（响应头与错误码）。
   默认折叠：这些是接入时才需要的参考，摊开会淹没「怎么调用」这个主线。 */
.api-more { margin-top: 16px; border-top: 1px solid var(--line); padding-top: 14px; }
.api-more > summary {
  cursor: pointer; font-size: 14.5px; font-weight: 600; color: var(--accent);
  list-style: none;
}
.api-more > summary::-webkit-details-marker { display: none; }
.api-more > summary::before { content: "▸ "; }
.api-more[open] > summary::before { content: "▾ "; }
.api-more table { margin-top: 10px; }
.api-more pre { margin: 10px 0; }
.api-more code { font-family: var(--font-mono); }

/* ── Pulse 证据卡 ──
   与下方静态画像的视觉关系：这张卡是「此刻的判断」，用实心强调色边框；
   静态画像是「固有属性」，保持原有中性卡片。两者不该长得一样。 */
.pulse-card {
  border: 1px solid var(--line);
  border-left: 4px solid var(--pulse-color, var(--text-dim));
  border-radius: 10px;
  background: var(--bg-card);
  padding: 20px 22px;
  margin-bottom: 16px;
}
.pulse-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 20px; flex-wrap: wrap; }
.pulse-left { min-width: 0; }
.pulse-band {
  font-size: 24px; font-weight: 700; letter-spacing: -0.01em;
  color: var(--pulse-color, var(--text));
}
.pulse-band-why { font-size: 13px; color: var(--text-dim); margin-top: 4px; max-width: 46ch; }
.pulse-right { text-align: right; flex: none; }
.pulse-score {
  font-size: 40px; font-weight: 700; line-height: 1;
  color: var(--pulse-color, var(--text)); font-variant-numeric: tabular-nums;
}
.pulse-score.is-none { font-size: 17px; font-weight: 600; line-height: 1.4; }
.pulse-score-cap { font-size: 12px; color: var(--text-dim); margin-top: 6px; line-height: 1.5; }
.pulse-score-cap span { color: var(--text-dim); opacity: .75; }

/* 0 分的专门形态：没证据 ≠ 安全，这条必须显式说出来 */
.pulse-noev {
  margin-top: 14px; padding: 12px 14px; border-radius: 8px;
  background: var(--bg); border: 1px solid var(--line);
  font-size: 13.5px; color: var(--text); line-height: 1.7;
}
.pulse-noev a { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }
.pulse-exit { display: block; margin-top: 6px; color: var(--text-dim); }

/* 证据行：新鲜度桶决定颜色，一眼看出哪条还有效 */
.pulse-ev { margin-top: 14px; }
.pulse-ev:empty { display: none; }
.pev { display: flex; align-items: center; gap: 10px; padding: 9px 0; border-top: 1px solid var(--line); }
.pev:first-child { border-top: none; }
.pev-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--text-dim); }
.pev-dot.fresh { background: var(--high); }
.pev-dot.aging { background: var(--medium); }
.pev-name { font-weight: 600; font-size: 14.5px; }
.pev-fresh { font-size: 13px; color: var(--text-dim); }
.pev-cal { font-size: 11.5px; color: var(--text-dim); border: 1px solid var(--line); border-radius: 4px; padding: 1px 6px; }
.pev-cal.no { opacity: .7; }

.pulse-foot {
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line);
  display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  font-size: 12.5px; color: var(--text-dim);
}
.pulse-contrast { font-variant-numeric: tabular-nums; }

@media (max-width: 560px) {
  .pulse-head { flex-direction: column; }
  .pulse-right { text-align: left; }
}

/* 滑块拼图（人机验证加强档，只对可疑来源出现） */
.slide-mask {
  position: fixed; inset: 0; z-index: 120;
  background: rgba(0,0,0,0.55); backdrop-filter: blur(2px);
  display: grid; place-items: center; padding: 20px;
}
.slide-box {
  position: relative; width: 100%; max-width: 360px;
  background: var(--bg-card); border: 1px solid var(--line);
  border-radius: 16px; padding: 24px 20px 16px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.3);
}
.slide-title { margin: 0 0 4px; font-size: 16px; }
.slide-tip { margin: 0 0 14px; font-size: 13px; color: var(--text-dim); }
.slide-stage { position: relative; width: 100%; line-height: 0; border-radius: 10px; overflow: hidden; }
.slide-bg { width: 100%; height: auto; display: block; }
/* 拼图切片浮在背景之上，只做水平位移 */
.slide-piece { position: absolute; left: 0; height: auto; will-change: left; }
.slide-rail {
  position: relative; margin-top: 12px; height: 38px;
  background: var(--bg); border: 1.5px solid var(--line); border-radius: 10px;
}
.slide-handle {
  /* 必须 border-box：滑块宽度要和拼图切片严格一致，
     否则拖到底时切片和缺口差着边框那 3px，怎么调都对不准 */
  box-sizing: border-box;
  position: absolute; top: -1.5px; left: -1.5px; height: 38px;
  display: grid; place-items: center;
  background: var(--bg-card); border: 1.5px solid var(--line); border-radius: 10px;
  color: var(--text-dim); cursor: grab; user-select: none;
  /* 不设的话手机上拖动会变成页面滚动 */
  touch-action: none;
}
.slide-handle.is-drag { cursor: grabbing; border-color: var(--accent); color: var(--accent); }
.slide-handle.is-busy { cursor: wait; opacity: 0.7; }
.slide-handle.is-ok { border-color: var(--ok); color: var(--ok); }
.slide-err {
  margin-top: 10px; padding: 8px 11px; border-radius: 9px; font-size: 13px;
  background: color-mix(in srgb, var(--critical) 12%, var(--bg-card));
  border: 1px solid color-mix(in srgb, var(--critical) 35%, transparent);
}
.slide-acts { display: flex; justify-content: space-between; margin-top: 12px; }
.slide-link {
  border: none; background: none; padding: 0;
  font: inherit; font-size: 12.5px; color: var(--text-dim); cursor: pointer;
}
.slide-link:hover { color: var(--accent); }

/* 页头的控制台入口（仅登录态可见） */
.btn-console {
  padding: 5px 12px; border-radius: 8px; font-size: 13px; white-space: nowrap;
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  color: var(--accent); background: var(--bg-card);
}
.btn-console:hover { background: color-mix(in srgb, var(--accent) 8%, var(--bg-card)); }
