
  :root {
    --bg: #fff; --bg-soft: #f8f9fb; --bg-card: #fff; --bg-hover: #eef1f5;
    --text: #1a1a1a; --text-soft: #57606a; --text-muted: #8b949e;
    --border: #e1e4e8; --border-strong: #d8dce0;
    --shadow: 0 1px 4px rgba(0,0,0,0.06), 0 4px 12px rgba(0,0,0,0.04);
  }
  [data-theme="dark"] {
    --bg: #0d1117; --bg-soft: #161b22; --bg-card: #161b22; --bg-hover: #21262d;
    --text: #e6edf3; --text-soft: #c9d1d9; --text-muted: #8b949e;
    --border: #30363d; --border-strong: #444c56;
    --shadow: 0 1px 4px rgba(0,0,0,0.4), 0 4px 12px rgba(0,0,0,0.3);
  }
  @media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
      --bg: #0d1117; --bg-soft: #161b22; --bg-card: #161b22; --bg-hover: #21262d;
      --text: #e6edf3; --text-soft: #c9d1d9; --text-muted: #8b949e;
      --border: #30363d; --border-strong: #444c56;
      --shadow: 0 1px 4px rgba(0,0,0,0.4), 0 4px 12px rgba(0,0,0,0.3);
    }
  }
  /* 运营商类型 = ISP 时深绿色高亮（GitHub 语义绿，亮/暗双色保证对比度）*/
  .card .kv .v strong.ct-isp { color: #1a7f37; }
  .card .kv .v .asn-residential { color: #1a7f37; }
  [data-theme="dark"] .card .kv .v strong.ct-isp { color: #3fb950; }
  [data-theme="dark"] .card .kv .v .asn-residential { color: #3fb950; }
  @media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .card .kv .v strong.ct-isp { color: #3fb950; }
    :root:not([data-theme="light"]) .card .kv .v .asn-residential { color: #3fb950; }
  }
  .ts-wrap { position: relative; margin-left: auto; align-self: center; z-index: 100; margin-top: -6px; }
  .ts-btn { width: 28px; height: 28px; border-radius: 50%; border: 1px solid var(--border-strong); background: var(--bg-card); color: var(--text); display: flex; align-items: center; justify-content: center; cursor: pointer; padding: 0; transition: background 0.15s, transform 0.15s; -webkit-tap-highlight-color: transparent; }
  .ts-btn:hover { background: var(--bg-hover); }
  .ts-btn:active { transform: scale(0.96); }
  .ts-btn svg { width: 14px; height: 14px; stroke: currentColor; }
  .ts-menu { position: absolute; top: 44px; right: 0; min-width: 148px; background: var(--bg-card); border: 1px solid var(--border); border-radius: 10px; box-shadow: var(--shadow); padding: 4px; display: none; }
  .ts-menu.open { display: block; }
  .ts-item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 12px; background: transparent; border: none; color: var(--text); font: inherit; font-size: 14px; border-radius: 6px; cursor: pointer; text-align: left; -webkit-tap-highlight-color: transparent; }
  .ts-item:hover { background: var(--bg-hover); }
  .ts-item svg { width: 16px; height: 16px; stroke: currentColor; flex-shrink: 0; }
  .ts-item[aria-current="true"] { background: var(--bg-hover); font-weight: 500; }
  @media (max-width: 480px) {
    .ts-btn { width: 26px; height: 26px; }
    .ts-btn svg { width: 13px; height: 13px; }
  }
  [data-theme="dark"] .ip-head { background: var(--bg-card) !important; }
  @media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .ip-head { background: var(--bg-card) !important; }
  }
  body { background: var(--bg) !important; color: var(--text) !important; }

  * { margin: 0; padding: 0; box-sizing: border-box; }
  html { overflow-y: scroll; }
  body {
    font-family: system-ui, sans-serif;
    background: var(--bg-card); color: var(--text); min-height: 100vh; line-height: 1.6;
    overflow-x: hidden;
  }
  code, .mono { font-variant-numeric: tabular-nums; }
  .container { max-width: 1000px; margin: 0 auto; padding: 24px 20px; }
  @media (max-width: 480px) { .container { padding: 14px 12px; } }
  .nav { display: flex; gap: 20px; margin-bottom: 20px; font-size: 0.9em; flex-wrap: wrap; align-items: center; }
  .nav a { color: var(--text-soft); text-decoration: none; padding-bottom: 4px; border-bottom: 2px solid transparent; -webkit-tap-highlight-color: transparent; outline: none; display: inline-block; line-height: 1.5; white-space: nowrap; flex-shrink: 0; }
  .nav a:hover { color: var(--text); }
  .nav a:focus, .nav a:active { outline: none; }
  .nav a.active { color: var(--text); font-weight: 600; border-bottom: 2px solid var(--text); }
  .nav .short { display: none; }
  .nav .shortest { display: none; }
  /* nav-ipcard-new-css */
  .nav .pc-only-new { display: inline-flex; align-items: center; gap: 4px; }
  .nav .nav-new {
    font-size: 0.3em; font-weight: 700; padding: 1px 3px; border-radius: 3px;
    background: linear-gradient(90deg,#ef4444,#f59e0b); color: #fff;
    letter-spacing: 0.4px; text-transform: uppercase; line-height: 1.4;
  }
  @media (max-width: 580px) { .nav .pc-only-new { display: none; } }
  @media (max-width: 580px) { .nav .full { display: none; } .nav .short { display: inline; } .nav { gap: 14px; } }
  @media (max-width: 399px) {
    .nav a[href="/claude/"] .short { display: none; }
    .nav a[href="/claude/"] .shortest { display: inline; }
    .nav { gap: 12px; }
    .ts-btn { width: 24px; height: 24px; }
    .ts-btn svg { width: 12px; height: 12px; }
  }
  @media (max-width: 339px) {
    .nav { gap: 8px; font-size: 0.88em; }
    .ts-btn { width: 22px; height: 22px; }
    .ts-btn svg { width: 11px; height: 11px; }
  }
  h1 { font-size: 1.75em; font-weight: 700; margin-bottom: 8px; }

  .desc { color: var(--text-soft); font-size: 0.9em; margin-bottom: 24px; line-height: 1.6; }
  @media (max-width: 480px) { .desc { font-size: 0.82em; } }
  /* --- 标题行(描述文案 + 隐藏IP 开关,与 /claude/ 保持一致) --- */
  .ip-section-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 24px; }
  .ip-section-header .desc { margin: 0; flex: 1 1 auto; min-width: 0; }
  .ip-mask-toggle { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; user-select: none; font-size: 0.80em; color: var(--text-muted); flex-shrink: 0; }
  .ip-mask-toggle input { position: absolute; opacity: 0; pointer-events: none; }
  .ip-mask-toggle-slider { position: relative; display: inline-block; width: 26px; height: 14px; background: #d8dce0; border-radius: 7px; transition: background 0.2s ease; flex-shrink: 0; }
  .ip-mask-toggle-slider::after { content: ""; position: absolute; top: 2px; left: 2px; width: 10px; height: 10px; background: var(--bg-card); border-radius: 50%; transition: transform 0.2s ease; box-shadow: 0 1px 2px rgba(0,0,0,0.2); }
  .ip-mask-toggle input:checked + .ip-mask-toggle-slider { background: #34c759; }
  .ip-mask-toggle input:checked + .ip-mask-toggle-slider::after { transform: translateX(12px); }
  .ip-mask-toggle input:focus-visible + .ip-mask-toggle-slider { outline: 2px solid #34c759; outline-offset: 2px; }
  @media (max-width: 720px) { .ip-mask-toggle { display: none !important; } }
  /* 开启遮罩时搜索框文字透明(看起来为空)——value 保持真实值,依赖 input.value 的查询逻辑不受影响 */
  #ip-input.ip-mask-on { color: transparent; }
  #ip-input.ip-mask-on::selection { color: transparent; background: transparent; }
  .search-bar { display: flex; gap: 10px; margin-bottom: 24px; }
  /* 初始 .search-bar 在 container 顶层时隐藏——避免 FOUC（IP 查询前大版本→小版本跳变）。
     JS 拿到 IP 后会把它移进 .ip-head（不再是 .container 直接子元素），自动恢复显示。 */
  .container > .search-bar { display: none; }
  .search-bar input {
    flex: 1; padding: 10px 16px; border: 1px solid var(--border-strong); border-radius: 8px;
    font-size: 1em; outline: none; font-family: inherit; background: var(--bg-card); color: var(--text);
  }
  .search-bar input:focus { border-color: var(--text); }
  .search-bar button {
    padding: 12px 36px; border: none; border-radius: 8px;
    background: #1a1a1a; color: #fff; font-size: 1em; font-weight: 600;
    cursor: pointer; white-space: nowrap;
  }
  .search-bar button:hover { background: #333; }
  .search-bar button:disabled { background: #999; cursor: not-allowed; }
  .ip-head {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    padding: 14px 18px; border: 1px solid var(--border-strong); border-radius: 10px;
    background: linear-gradient(180deg, #f8f9fb 0%, #fff 100%);
    box-shadow: var(--shadow);
    margin-bottom: 20px;
  }
  .ip-head .ip {
    font-size: 1.35em; font-weight: 700;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
  }
  .ip-head .flag { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 14px; flex-shrink: 0; }
  .ip-head .flag img { width: 20px; height: auto; border-radius: 2px; box-shadow: 0 1px 1.5px rgba(0,0,0,0.1); display: block; }
  .ip-head .flag-fallback { font-size: 1.1em; }
  .flag-inline { display: inline-block; width: 20px; height: auto; vertical-align: -4px; margin-right: 4px; border-radius: 2px; box-shadow: 0 1px 1px rgba(0,0,0,0.1); }
  .signal-warn-banner { margin: 10px 0 16px; padding: 10px 14px; border-radius: 8px; background: #fff8e1; border: 1px solid #f5d98d; color: #7a5a00; font-size: 0.88em; line-height: 1.55; }
  .signal-warn-banner strong { color: #6b4800; }
  .signal-warn-banner ul { margin: 6px 0 0 18px; padding: 0; }
  .signal-warn-banner li { margin: 2px 0; }
  .ip-head .country {
    color: var(--text-soft); font-size: 0.92em; font-weight: 500;
    padding-left: 10px; margin-left: 6px; border-left: 1px solid #e1e4e8;
    flex: 1 1 0; min-width: 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    display: flex; align-items: center;
  }
  .ip-head .country .country-text {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    min-width: 0; display: inline-block;
  }
  .ip-head .country.no-divider { border-left: 0; padding-left: 0; margin-left: 0; }
  .ip-head .score-gauge {
    margin-left: auto; display: flex; flex-direction: row; align-items: baseline;
    gap: 6px; padding: 4px 12px; border-radius: 8px;
    line-height: 1.1;
  }
  .ip-head .score-gauge .score-label {
    font-size: 0.82em; font-weight: 600;
    letter-spacing: 0.2px; opacity: 0.85;
  }
  .ip-head .score-gauge .score-num {
    font-size: 1.15em; font-weight: 800;
    font-variant-numeric: tabular-nums;
  }
  .ip-head .search-bar {
    margin-bottom: 0; gap: 6px;
  }
  .ip-head .search-bar input {
    padding: 6px 10px; font-size: 0.88em; min-width: 120px; max-width: 180px;
  }
  .ip-head .search-bar button {
    padding: 6px 14px; font-size: 0.88em;
  }
  @media (max-width: 720px) {
    .ip-head { padding: 10px 12px; gap: 8px; }
    .ip-head .ip { font-size: 1.1em; letter-spacing: -0.02em; word-break: break-all; min-width: 0; }
    .ip-head .country { padding-left: 0; margin-left: 0; border-left: 0; flex-basis: 100%; font-size: 0.85em; }
    .ip-head .score-gauge { margin-left: 0; padding: 2px 8px; flex: 0 0 auto; }
    .ip-head .score-gauge .score-num { font-size: 1em; }
    .ip-head .search-bar { flex: 1 1 0; margin-top: 0; min-width: 0; gap: 4px; }
    .ip-head .search-bar input { flex: 1 1 auto; padding: 5px 8px; font-size: 0.82em; min-width: 0; max-width: none; }
    .ip-head .search-bar button { padding: 5px 10px; font-size: 0.82em; white-space: nowrap; flex: 0 0 auto; }
  }
  @media (max-width: 400px) {
    .ip-head .ip { font-size: 0.95em; }
    .ip-head .country { font-size: 0.8em; }
  }
  .score-high  { background: #e8f7ee; color: #1d7a3a; }
  .score-mid   { background: #fff6e0; color: #7a5a00; }
  .score-low   { background: #fcecec; color: #a13131; }
  .grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin-bottom: 16px; }
  @media (max-width: 720px) { .grid { grid-template-columns: 1fr; } }
  .card .kv.kv-iprange .v {
    white-space: nowrap;
    max-width: none;
    word-break: normal;
    font-variant-numeric: tabular-nums;
    text-align: right;
  }
  @media (max-width: 400px) {
    .card .kv.kv-iprange { gap: 8px; }
    .card .kv.kv-iprange .v { font-size: 0.82em; }
  }
  .grid-3 .card .kv .v,
  .grid-3 .card .kv .v * {
    font-weight: 400 !important;
  }
  .grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; margin-bottom: 16px; }
  .grid-3 > .card-full { grid-column: 1 / -1; }
  @media (max-width: 960px) { .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
  @media (max-width: 720px) { .grid-3 { grid-template-columns: 1fr; } }
  .grid > .card-full { grid-column: 1 / -1; }
  .card {
    border: 1px solid var(--border-strong); border-radius: 10px; padding: 14px 16px;
    background: var(--bg-card);
    box-shadow: 0 1px 4px rgba(0,0,0,0.04);
    min-width: 0;  
  }
  .card h3 {
    font-size: 0.82em; color: var(--text-muted); text-transform: uppercase;
    letter-spacing: 0.5px; margin-bottom: 14px; font-weight: 600;
  }
  .card .kv {
    display: flex; justify-content: space-between; align-items: baseline;
    padding: 6px 0; border-bottom: 1px dashed var(--border);
    font-size: 0.92em; gap: 16px;
    min-width: 0;  
  }
  .card .kv:last-child { border-bottom: none; }
  .card .kv .k { color: var(--text-muted); font-weight: 400; flex-shrink: 0; }
  .card .kv .v {
    color: var(--text); font-weight: 600; text-align: right;
    max-width: 65%; word-break: break-all; min-width: 0;
  }
  @media (max-width: 400px) {
    .card { padding: 12px 12px; }
    .card .kv { font-size: 0.85em; gap: 10px; padding: 5px 0; }
    .card .kv .v { max-width: 62%; }
    .trunc { max-width: min(18ch, 100%); }
  }
  .card .kv.kv-wide .v {
    max-width: none; white-space: nowrap; overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    flex: 1 1 0;   
    width: 0;
  }
  @media (max-width: 720px) {
    .card .kv.kv-wide {
      align-items: center; gap: 10px;
    }
    .card .kv.kv-wide .k {
      display: inline-flex; align-items: center; line-height: 1;
    }
    .card .kv.kv-wide .v {
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
      max-width: 100%; min-width: 0; word-break: normal;
      flex: 1 1 0; width: 0;   
      font-weight: 400; font-size: 0.88em;
    }
    .card .kv.kv-wide .v .geo-coord { display: none; }
    .card .kv .v .trunc,
    .card .kv .v.trunc {
      font-weight: 400;
    }
  }
  /* ---- Multi-source geo comparison: 2x2 grid on PC, single col on mobile ---- */
  .geo-rows-grid { display: block; }
  @media (min-width: 721px) {
    .geo-rows-grid {
      display: grid;
      grid-template-columns: 1fr 1fr;
      column-gap: 24px;
      row-gap: 0;
    }
    .geo-rows-grid .kv.kv-wide {
      padding: 6px 0;
      border-bottom: 1px dashed var(--border);
      min-width: 0;
    }
    /* Drop border on the LAST VISUAL ROW only (handles odd counts):
       - :last-child is always in last row
       - :nth-last-child(2):nth-child(odd) catches the left cell of a
         2-item last row (even total). Odd total keeps the right-col
         cell (position 2) bordered, which gives a short dashed line
         under it — acceptable. */
    .geo-rows-grid .kv.kv-wide:last-child,
    .geo-rows-grid .kv.kv-wide:nth-last-child(2):nth-child(odd) {
      border-bottom: none;
    }
    /* Cap the value column so long DB-IP city strings ellipsis cleanly
       inside the half-width cell (flex:1 already set in base .kv-wide .v). */
    .geo-rows-grid .kv.kv-wide .v {
      max-width: 100%;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    /* Shrink coord link so it has breathing room in the narrower cell */
    .geo-rows-grid .kv.kv-wide .v .geo-coord {
      font-size: 0.78em;
      margin-left: 6px;
    }
  }
  .card .kv .v strong { font-weight: 700; color: var(--text); }
  .card .kv.kv-hx { gap: 10px; }
  .card .kv.kv-hx .k { flex: 0 0 auto; }
  .card .kv.kv-hx .v {
    font-weight: 400;
    text-align: right;
    max-width: none;
    flex: 1 1 0; width: 0;
    min-width: 0;
    justify-content: flex-end !important;
  }
  .card .kv.kv-hx .v strong { font-weight: 400; }
  #portScanRow {
    flex-wrap: wrap; justify-content: flex-start;
    align-items: center; gap: 8px; row-gap: 6px;
  }
  #portScanRow .v {
    display: contents;   
  }
  #portScanRow .k { margin-right: 4px; }
  #portScanRow:has(.v > #portScanBtn:only-child) #portScanBtn {
    margin-left: auto;
  }
  #portScanRow #portScanPingBtn { margin-left: auto; }
  #portScanRow #pingVerdictSlot:not(:empty) { margin-left: auto; }
  #portScanRow:not(:has(#portScanPingBtn)):not(:has(#pingVerdictSlot:not(:empty))) #portScanCtrl {
    margin-left: auto;
  }
  .gp-grid {
    display: grid;
    grid-template-columns: repeat(8, minmax(0, 1fr));
    gap: 8px;
  }
  @media (max-width: 900px) { .gp-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
  @media (max-width: 480px) { .gp-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; } }
  .gp-cell {
    text-align: center; font-size: 0.82em; line-height: 1.35;
    padding: 4px 2px;
  }
  .gp-head {
    display: inline-flex; align-items: center; justify-content: center;
    gap: 4px; margin-bottom: 2px;
  }
  .gp-cell img {
    width: 20px; height: 14px; object-fit: contain;
    border-radius: 2px; flex-shrink: 0;
  }
  .gp-city { color: var(--text-soft); font-weight: 400; line-height: 1; white-space: nowrap; }
  @media (max-width: 480px) { .gp-city { font-size: 0.82em; } }
  .gp-val  { display: block; font-weight: 400; font-size: 0.92em; margin-top: 2px; font-variant-numeric: tabular-nums; }
  .gp-wait { color: #c0c4c9; animation: gpWait 1.2s ease-in-out infinite; }
  @keyframes gpWait { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } }
  @keyframes gp-dots {
    0%   { content: ''; }
    25%  { content: '.'; }
    50%  { content: '..'; }
    75%  { content: '...'; }
    100% { content: ''; }
  }
  .gp-ok   { color: #1b8a2d; }
  .gp-med  { color: #6fcf7c; }
  .gp-slow { color: #d4a017; }
  .gp-bad  { color: #c62828; }
  .gp-err  { color: #d4a017; font-weight: 400; font-size: 0.9em; }
  .gp-pending { color: #a8afb5; font-weight: 400; font-size: 0.9em; }
  #portScanRow #portScanCtrl {
    display: inline-flex; align-items: center; margin: 0;
    font-weight: 400; font-size: 0.78em; color: var(--text-soft);
  }
  #portScanRow #portScanCtrl a { font-weight: 400; }
  .card .kv .v.mono {
    font-variant-numeric: tabular-nums;
  }
  .trunc {
    display: inline-block;
    max-width: min(48ch, 100%);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: bottom;
  }
  @media (max-width: 720px) {
    .trunc { max-width: min(22ch, 100%); }
  }
  .card .kv.kv-lh { gap: 10px; align-items: center; }
  .card .kv.kv-lh .k { flex-shrink: 0; }
  .card .kv.kv-lh .v.lh-val {
    text-align: right; max-width: none; min-width: 0;
    flex: 1 1 auto;
    display: flex; align-items: center; justify-content: flex-end; gap: 4px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    font-weight: 500;
  }
  .card .kv.kv-lh .v.lh-val .lh-text {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    min-width: 0;
  }
  .card .kv.kv-lh .v.lh-val img,
  .card .kv.kv-lh .v.lh-val .flag-inline { flex-shrink: 0; }
  @media (max-width: 400px) {
    .card .kv.kv-lh { font-size: 0.85em; gap: 6px; }
    .card .kv.kv-lh .k { font-size: 0.78em; }
  }
  .dn-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 4px 10px;
    margin-top: 4px;
  }
  .dn-cell {
    display: flex; align-items: center; gap: 4px;
    min-width: 0; padding: 3px 4px;
    font-size: 0.85em;
  }
  .dn-cell .dn-flag { flex: 0 0 auto; line-height: 1; }
  .dn-cell .dn-flag img { vertical-align: middle; }
  .dn-cell .dn-ip {
    flex: 1 1 auto; min-width: 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .dn-cell a.dn-ip { color: var(--text); text-decoration: none; }
  .dn-cell a.dn-ip:hover { color: var(--text); text-decoration: underline; }
  .dn-toggle { color: var(--text-soft); }
  .dn-toggle:hover { color: var(--text); }
  @media (max-width: 720px) {
    .dn-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 3px 6px; }
    .dn-grid:not(.expanded) .dn-cell:nth-child(n+7) { display: none; }
  }
  .dn-toggle {
    display: none;  /* shown only on mobile via media query */
    margin-top: 6px; padding: 4px 0;
    font-size: 0.82em; color: #5a3dbd; cursor: pointer;
    text-decoration: none; user-select: none;
  }
  .dn-toggle:hover { text-decoration: underline; }
  @media (max-width: 720px) { .dn-toggle { display: inline-block; } }
  .rd-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px 12px;
    margin-top: 4px;
  }
  .rd-item {
    padding: 8px 10px;
    background: var(--bg-soft);
    border: 1px solid var(--border);
    border-radius: 6px;
    min-width: 0;
    overflow: hidden;
  }
  .rd-item .rd-domain {
    font-size: 0.92em; font-weight: 600; color: var(--text);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .rd-item .rd-via {
    font-size: 0.82em; color: var(--text-soft); margin-top: 2px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  @media (max-width: 720px) {
    .rd-grid { grid-template-columns: 1fr; gap: 6px; }
  }
  .chip {
    display: inline-block; padding: 2px 10px; border-radius: 10px;
    font-size: 0.82em; font-weight: 600; margin-right: 4px; letter-spacing: 0.2px;
  }
  .chip-ok   { background: #e8f7ee; color: #1d7a3a; }
  .chip-warn { background: #fff6e0; color: #7a5a00; }
  .chip-bad  { background: #fcecec; color: #a13131; }
  .chip-info { background: #e7f0fc; color: #1f4d8a; }
  .ht-pill {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 3px 10px; border-radius: 999px;
    font-weight: 500; font-size: 0.92em; line-height: 1.4;
    vertical-align: middle;
  }
  .ht-pill svg { width: 14px; height: 14px; flex-shrink: 0; }
  .ht-pill-human     { background: #e8f7ee; color: #1d7a3a; font-weight: 700; }
  .ht-pill-robot     { background: #fff7ed; color: #b45309; }
  .ht-pill-crawler   { background: #f5f3ff; color: #6d28d9; }
  .ht-pill-satellite { background: #eff6ff; color: #1d4ed8; }
  .ai-card {
    border: 1px solid var(--border-strong); border-radius: 10px; padding: 18px 20px;
    background: linear-gradient(135deg, #f6f3ff 0%, #fff 100%);
    margin-bottom: 16px;
  }
  .ai-card .ai-label {
    font-size: 0.78em; color: #6b4dbe; text-transform: uppercase;
    letter-spacing: 0.4px; font-weight: 600; margin-bottom: 8px;
  }
  .ai-card .ai-verdict { font-size: 1.2em; font-weight: 700; }
  .ai-card .ai-reason  { color: #555; font-size: 0.9em; margin-top: 6px; }
  .ai-spinner {
    display: inline-block; width: 14px; height: 14px;
    border: 2px solid #d6c8ff; border-top-color: #6b4dbe; border-radius: 50%;
    animation: spin 0.8s linear infinite; vertical-align: middle; margin-right: 8px;
  }
  @keyframes spin { to { transform: rotate(360deg); } }
  .footer {
    margin-top: 40px; padding-top: 16px; border-top: 1px solid var(--border);
    color: #888; font-size: 0.82em; text-align: center;
  }
  .footer a { color: var(--text-soft); text-decoration: none; margin: 0 8px; }
  .footer a:hover { color: var(--text); }
  .actions { display: flex; gap: 10px; flex-wrap: wrap; margin: 10px 0 20px; }
  @media (min-width: 720px) {
    .actions-row { display: flex; gap: 14px; align-items: flex-start; margin: 10px 0 20px; }
    .actions-row .actions { margin: 0; flex: 0 0 auto; }
    .actions-row .ext-tools { margin: 0; flex: 1 1 auto; min-width: 0; }
  }
  .actions a {
    padding: 8px 14px; border: 1px solid var(--border-strong); border-radius: 8px;
    color: var(--text); text-decoration: none; font-size: 0.88em; font-weight: 500;
    transition: background .12s ease, border-color .12s ease;
  }
  .actions a:hover { background: var(--bg-soft); border-color: #b9c0c8; }
  .skeleton-card {
    border: 1px solid #e5e7eb; border-radius: 10px; padding: 16px;
    background: var(--bg-card); overflow: hidden; position: relative;
  }
  .skeleton-line {
    height: 10px; background-color: #edeef1; overflow: hidden; position: relative;
    border-radius: 4px; margin: 8px 0;
  }
  .skeleton-line::after {
    content: ''; position: absolute; inset: 0;
    background: linear-gradient(90deg, transparent, #f7f8fa, transparent);
    animation: shimmer 1.3s linear infinite; will-change: transform;
  }
  .skeleton-line.short { width: 40%; }
  .skeleton-line.medium { width: 70%; }
  .skeleton-line.title { width: 30%; height: 12px; margin-bottom: 14px; }
  .flag-skel {
    background-color: #edeef1; overflow: hidden; position: relative;
  }
  .flag-skel::after {
    content: ''; position: absolute; inset: 0;
    background: linear-gradient(90deg, transparent, #f7f8fa, transparent);
    animation: shimmer 1.3s linear infinite; will-change: transform;
  }
  @keyframes shimmer { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } }
  .ip-head .country small { color: var(--text-muted); font-weight: 400; }
  .signal-banner-big {
    display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
    padding: 14px 18px; border: 1px solid var(--border-strong); border-radius: 10px;
    background: var(--bg-soft); margin-bottom: 16px;
  }
  .signal-banner-big .sig-label {
    font-size: 0.75em; font-weight: 600; color: var(--text-muted);
    text-transform: uppercase; letter-spacing: 0.5px; margin-right: 4px;
  }
  .sig-pill {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 5px 12px; border-radius: 20px; font-size: 0.88em; font-weight: 600;
    border: 1px solid transparent;
  }
  .sig-pill .dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }
  .sig-ok    { background: #e8f7ee; color: #1d7a3a; border-color: #c7ecd5; }
  .sig-ok .dot    { background: #1d7a3a; }
  .sig-warn  { background: #fff6e0; color: #7a5a00; border-color: #f5d98d; }
  .sig-warn .dot  { background: #c17900; }
  .sig-bad   { background: #fcecec; color: #a13131; border-color: #f5c2c7; }
  .sig-bad .dot   { background: #a13131; }
  .sig-info  { background: #e7f0fc; color: #1f4d8a; border-color: #b8ccec; }
  .sig-info .dot  { background: #1f4d8a; }
  .ext-tools {
    display: flex; flex-wrap: wrap; gap: 6px;
    padding: 8px 12px; border: 1px dashed var(--border-strong); border-radius: 8px;
    background: var(--bg-soft); margin-bottom: 20px; align-items: center;
  }
  .ext-tools .ext-label {
    font-size: 0.70em; font-weight: 600; color: var(--text-muted);
    text-transform: uppercase; letter-spacing: 0.5px; margin-right: 4px;
  }
  .ext-tools a {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 3px 8px; border-radius: 5px; border: 1px solid var(--border-strong);
    background: var(--bg-card); color: var(--text); text-decoration: none;
    font-size: 0.72em; font-weight: 500;
    transition: all .12s ease;
  }
  .ext-tools a:hover { background: var(--bg-hover); border-color: var(--text-muted); }
  .ext-tools a::after { content: '↗'; font-size: 0.72em; color: var(--text-muted); margin-left: 2px; }
  .ext-tools .ext-more { display: none; }
  .ext-tools.open .ext-more { display: inline-flex; }
  .ext-tools .ext-toggle {
    cursor: pointer; user-select: none;
    padding: 3px 8px; border-radius: 5px; border: 1px solid var(--border-strong);
    background: var(--bg-card); color: var(--text-soft);
    font-size: 0.72em; font-weight: 500;
  }
  .ext-tools .ext-toggle:hover { background: var(--bg-hover); border-color: var(--text-muted); }
  .ext-tools.open .ext-toggle-open { display: none; }
  .ext-tools:not(.open) .ext-toggle-close { display: none; }
  .copy-btn {
    display: inline-block; margin-left: 6px; padding: 0 5px;
    border: 1px solid var(--border-strong); border-radius: 4px;
    background: var(--bg-card); color: var(--text-muted); cursor: pointer;
    font-size: 0.78em; font-family: inherit; font-weight: 500;
    vertical-align: middle; line-height: 1.6;
    transition: all .12s ease;
  }
  .copy-btn:hover { background: var(--bg-soft); color: var(--text); border-color: var(--text-muted); }
  .copy-btn.copied { background: #e8f7ee; color: #1d7a3a; border-color: #c7ecd5; }
  .neighbor-nav {
    padding-top: 8px; margin-top: 6px; border-top: 1px dashed var(--border);
    font-size: 0.85em;
  }
  .neighbor-nav .nn-row {
    display: flex; gap: 8px; flex-wrap: wrap; align-items: center;
  }
  .neighbor-nav .nn-row + .nn-row { margin-top: 6px; }
  .neighbor-nav .nn-label { color: var(--text-muted); font-weight: 600; }
  .neighbor-nav a {
    color: #1f4d8a; text-decoration: none;
    padding: 2px 8px; border-radius: 4px; background: var(--bg-soft);
  }
  .neighbor-nav a:hover { background: #e7f0fc; }
  .error-box {
    padding: 14px 18px; border: 1px solid #f5c2c7; background: #fcecec;
    color: #a13131; border-radius: 8px; margin: 20px 0;
  }
  .loading { color: var(--text-soft); font-style: italic; }
  .muted { color: #888; }
  .tip-wrap { position: relative; display: inline-flex; align-items: center; cursor: help; color: var(--text-muted); margin-left: 4px; font-size: 0.85em; }
  .tip-wrap .tip-text {
    visibility: hidden; opacity: 0; transition: opacity .15s, visibility .15s;
    position: absolute; bottom: 125%; left: 50%; transform: translateX(-50%);
    min-width: 220px; max-width: 300px; padding: 8px 12px; border-radius: 6px;
    background: #333; color: #fff; font-size: 0.82em; font-weight: 400;
    line-height: 1.5; z-index: 10; text-transform: none; letter-spacing: 0;
    text-align: left; pointer-events: none;
  }
  .tip-wrap:hover .tip-text { visibility: visible; opacity: 1; }
  @media (max-width: 720px) {
    .tip-wrap .tip-text {
      position: fixed;
      left: 16px; right: 16px;
      top: 50%; bottom: auto;
      transform: translateY(-50%);
      min-width: 0; max-width: none; width: auto;
      font-size: 0.9em; padding: 12px 14px;
      box-shadow: 0 6px 24px rgba(0,0,0,0.35);
    }
  }

  /* === IPv6 + mobile overflow fixes === */
  /* H1: keep full IP in DOM for SEO; visually clip the IP portion on
     mobile so it never wraps to a second line. .h1-ip is wrapped around
     $req_ip by nginx sub_filter (server-side render). */
  /* h1 line-height inherited from body (1.6) — matches /claude/ baseline */
  .h1-ip { display: inline-block; vertical-align: bottom; max-width: 100%; }
  /* Mobile: align h1 size with /claude/ baseline (1.4em). Long-IPv6 overflow
     protection is moved to .h1-ip only (the dynamic IP wrapper injected by
     nginx sub_filter on /ip/{ip}). Bare /ip/ has no .h1-ip so it stays clean. */
  @media (max-width: 480px) {
    h1 { font-size: 1.4em; }
  }
  @media (max-width: 720px) {
    h1 { white-space: nowrap; overflow: hidden; }
    .h1-ip {
      max-width: calc(100% - 100px);  /* reserve for "IP " + " 评分" at 1.4em */
      overflow: hidden; white-space: nowrap;
      /* hard cut, no ellipsis — full IP still in DOM for crawlers */
    }
  }
  /* IPv6 in .ip-head — allow shrink/wrap so country/city is not squeezed */
  .ip-head .ip.is-v6 {
    min-width: 0; flex-shrink: 1;
    overflow-wrap: anywhere; word-break: break-all;
    font-size: 1.1em; max-width: 100%;
  }
  @media (max-width: 720px) {
    .ip-head .ip.is-v6 { font-size: 0.95em; }
  }
  /* IP range — IPv6 ranges (2x39 chars) overflow the right side cell */
  .card .kv.kv-iprange .v {
    overflow-wrap: anywhere; word-break: break-all;
    line-height: 1.4;
  }
  @media (max-width: 720px) {
    .card .kv.kv-iprange .v {
      white-space: normal; text-align: right;
      font-size: 0.78em;
    }
  }

  /* IP in header is now an <a>; keep it visually identical to the
     previous <span>, add subtle hover affordance. */
  .ip-head a.ip { color: inherit; text-decoration: none; cursor: pointer; }
  .ip-head a.ip:hover {
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
  }

  /* Google Maps link on geo coord text — subtle hover underline only */
  .card .kv.kv-wide .v a.geo-coord:hover {
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
  }

  /* Hide the '综合地理源定位：...' prefix on mobile; the legacy tail
     phrase stays visible on both PC and mobile. */
  @media (max-width: 720px) {
    .geo-sum-full { display: none; }
  }
  /* Align the flag vertically with the 0.8em footer text so flag and
     text sit on the same horizontal line. */
  .geo-sum-full .flag-inline {
    width: 16px; height: auto;
    vertical-align: middle;
    margin-right: 2px;
    position: relative; top: -1px;
  }

  /* nav-more 下拉(原内联,移入head防FOUC) */
  .nav-more{position:relative;display:inline-flex;align-items:center}.nav-more-trigger{cursor:pointer;display:inline-flex;align-items:center;gap:3px;color:var(--text-soft,#666);line-height:1.5;border-bottom:2px solid transparent;padding-bottom:4px;white-space:nowrap}.nav-more:hover .nav-more-trigger{color:var(--text,#1a1a1a)}.nav-more-arrow{transition:transform .15s}.nav-more:hover .nav-more-arrow{transform:rotate(180deg)}.nav-more-menu{position:absolute;top:100%;left:50%;transform:translateX(-50%);margin-top:2px;background:var(--bg-card,#fff);border:1px solid var(--border,#e1e4e8);border-radius:9px;box-shadow:0 4px 16px rgba(0,0,0,0.12);padding:5px;min-width:120px;opacity:0;visibility:hidden;transition:opacity .15s;z-index:300}.nav-more:hover .nav-more-menu{opacity:1;visibility:visible}.nav-more-menu a{display:block;padding:8px 12px;border-radius:6px;border-bottom:none !important;white-space:nowrap;color:var(--text,#1a1a1a);font-size:0.95em}.nav-more-menu a:hover{background:var(--bg-hover,#eef1f5)}.nav-more-menu::before{content:"";position:absolute;left:-12px;right:-12px;top:-18px;height:18px}.nav-more-menu{transition:opacity .15s ease,visibility 0s linear .35s}.nav-more:hover .nav-more-menu{transition:opacity .15s ease,visibility 0s}
  