:root {
  /* surfaces */
  --bg: #000000;            /* 深色画布: 侧栏 + 内容区背景共享同色, 融为一体 (卡片保持白) */
  --surface: #ffffff;       /* 悬浮内容层 / 卡片 */
  --surface-muted: #f4f6f9; /* 内嵌块 / 表格底 */
  --surface-soft: #edf8f0;  /* 绿色浅块 */
  --sidebar-hover: rgba(255, 255, 255, 0.6);

  /* lines */
  --border: #e2e5ea;
  --border-soft: #eef0f3;

  /* text */
  --text: #1b2433;
  --text-muted: #6a7382;
  --text-faint: #98a0ac;

  /* brand（CleanIP 绿色） */
  --brand: #2faa50;
  --brand-dark: #23863e;
  --brand-soft: #edf8f0;

  /* status */
  --danger: #d4504f;
  --danger-bg: #fdf1f1;
  --success-bg: #edf8f0;
  --warning-bg: #fff7e8;
  --warn: #b45309;        /* 琥珀文字: 接近额度 / 部分耗尽 */
  --warn-fill: #f59e0b;   /* 琥珀填充: 进度条中段 (70~89%) */

  /* elevation */
  --shadow-float: 0 1px 2px rgba(20, 28, 40, 0.05), 0 10px 30px rgba(20, 28, 40, 0.07);
  --shadow-card: 0 1px 2px rgba(20, 28, 40, 0.04);
  --shadow-pop: 0 1px 2px rgba(20, 28, 40, 0.05), 0 4px 14px rgba(20, 28, 40, 0.06);

  /* radius scale */
  --radius: 8px;
  --radius-sm: 6px;
  --radius-md: 12px;
  --radius-lg: 16px;
  --radius-xl: 16px;
  --radius-pill: 999px;

  --sora: "Sora", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --viga: "Viga", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  color: var(--text);
  background: var(--bg);
  font: 14px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
  color-scheme: light;
}

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

code,
pre,
textarea,
input[type="text"],
input[type="password"],
input[type="number"],
select {
  font: inherit;
}

/* ============================================================
   App shell — 两层结构
   ① chrome: .topbar + .sidebar 共享 --bg 底
   ② float : .content 独立白色悬浮层
   ============================================================ */
.admin-body {
  background: var(--bg);
}

/* 左 sidebar（第①层，同底色）+ 右 content 浮层（第②层）；无顶栏 */
.admin-shell {
  height: 100vh;
  display: flex;
  gap: 10px;
  padding: 14px;
  overflow: hidden;
}

/* ---- Sidebar：logo(顶) · 导航(中) · 用户卡(底) ---- */
.sidebar {
  flex: 0 0 218px;
  width: 218px;
  display: grid;
  /* 显式单列 minmax(0,1fr): 防止隐式 auto 列按 max-content 撑大 → 否则内部 nav 项
     会超出 250px 被 overflow:hidden 裁掉右侧圆角(grid blowout) */
  grid-template-columns: minmax(0, 1fr);
  /* 3 个子元素: head(auto) / nav(minmax(0,1fr) 占满+滚动) / footer(auto, 钉底)。
     搜索框移除后从 4 行改 3 行 — 否则 nav 落到 auto 行按全高撑开, 把 footer 顶出 100vh 被 overflow:hidden 裁掉。 */
  grid-template-rows: auto minmax(0, 1fr) auto;
  gap: 10px;
  padding: 6px 8px;
  overflow: hidden;
  /* 深色侧栏 (内容区保持浅色)。在 .sidebar 作用域内重定义文字/边框/品牌色变量,
     一处改, 所有子元素(标题/导航/footer)自动跟着变深色; --brand 绿色以适配深底。 */
  background: #000000;
  --text: #EEF2F7;
  --text-muted: #9BA6B4;
  --text-faint: #6B7480;
  --border: rgba(255, 255, 255, 0.1);
  --border-soft: rgba(255, 255, 255, 0.08);
  --sidebar-hover: rgba(255, 255, 255, 0.05);
  --surface: #2C2C2C;
  --surface-muted: #2C2C2C;
  --brand: #2faa50;
  --brand-soft: rgba(47, 170, 80, 0.20);
}

.sidebar-head {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 6px 10px 2px;
}

.sidebar-logo {
  width: 40px;
  height: 40px;
  border-radius: 11px;
  display: block;
  object-fit: contain;
}

.sidebar-brand-text {
  display: flex;
  flex-direction: column;
  line-height: 1.2;
  min-width: 0;
}

.sidebar-title {
  font-family: var(--viga);
  text-transform: uppercase;
  font-weight: 700;
  font-size: 18px;
  letter-spacing: -0.02em;
  /* 金属银白文字渐变 */
  display: inline-block;
  background: linear-gradient(257.34deg, #e2e6ea 14.04%, #909fb0 30.93%, #fff 90.58%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.sidebar-sub {
  font-size: 9px;
  letter-spacing: 0.005em;
  text-transform: uppercase;
  color: var(--text-faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---- 导航（第①层，图标 + 分组）---- */
.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 9px;
  overflow-y: auto;
  overflow-x: hidden;
  /* 发光滑块(.nav-glider)的定位基准 */
  position: relative;
  scrollbar-width: none;
  /* 水平 6px: 让导航项与搜索框/退出按钮左右对齐, 并给激活态圆角留出离滚动/裁剪边界的余量
     (否则纵向滚动时激活白框右上下圆角会被裁成直角) */
  padding: 2px 6px;
  min-width: 0;
}

/* 侧栏滚动条始终隐藏; 内容区滚动条默认透明, 悬停或正在滚动时浮现 (.is-scrolling 由 admin.gohtml 脚本加) */
.sidebar-nav::-webkit-scrollbar {
  display: none;
}
.content::-webkit-scrollbar { width: 8px; height: 8px; }
.content::-webkit-scrollbar-track { background: transparent; }
.content::-webkit-scrollbar-thumb { border-radius: var(--radius-pill); background: transparent; }
.content:hover::-webkit-scrollbar-thumb,
.content.is-scrolling::-webkit-scrollbar-thumb { background: rgba(27, 36, 51, 0.22); }
.content::-webkit-scrollbar-thumb:hover { background: rgba(27, 36, 51, 0.36); }
.content:hover,
.content.is-scrolling { scrollbar-color: rgba(27, 36, 51, 0.22) transparent; }

/* ---- 用户卡（侧栏左下角）---- */
.sidebar-footer {
  display: grid;
  /* 显式列 minmax(0,1fr): 同 .sidebar — 否则隐式 auto 列被「上次登录」长 IP(尤其 v6)
     撑过 250px, 连带满宽的退出登录按钮一起超宽被裁 */
  grid-template-columns: minmax(0, 1fr);
  gap: 10px;
  /* 水平 6px: 让退出登录按钮 / 上次登录信息与搜索框、导航项左右对齐 (都缩进 14px) */
  padding: 12px 6px 2px;
  border-top: 1px solid var(--border);
}

.sidebar-user {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 2px 6px;
}

.sidebar-avatar {
  width: 38px;
  height: 38px;
  flex: 0 0 38px;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
  display: grid;
  place-items: center;
  font-weight: 600;
  font-size: 15px;
  font-family: var(--sora);
}

.sidebar-user-meta {
  display: flex;
  flex-direction: column;
  line-height: 1.25;
  min-width: 0;
}

.sidebar-user-name {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sidebar-user-role {
  font-size: 11px;
  color: var(--text-faint);
}

.sidebar-user-login {
  font-size: 11px;
  color: var(--text-faint);
  margin-top: 8px;
  line-height: 1.5;
  word-break: break-all;
}

.sidebar-avatar-img {
  width: 38px;
  height: 38px;
  flex: 0 0 38px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--surface-muted);
  border: 1px solid var(--border-soft);
}

.sidebar-user-badge {
  align-self: flex-start;
  margin-top: 3px;
  padding: 1px 8px;
  border-radius: var(--radius-pill);
  background: var(--brand-soft);
  color: var(--brand);
  font-size: 10.5px;
  font-weight: 600;
}

.pk-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
}

.nav-group {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.nav-group-label {
  margin: 0 0 2px;
  padding: 0 12px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.nav-link {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 6px 12px;
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  color: var(--text-muted);
  font-size: 13px;
  font-weight: 400;
  min-width: 0;
  transition: background-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
}

/* 左侧竖条由发光滑块 .nav-glider 承担(JS 跟随激活项平滑滑动)。这里只管文字/图标。 */
.nav-link:hover {
  background: transparent;
  color: var(--text);
  border-radius: 0;
}

.nav-link.is-active {
  background: transparent;
  color: #fff;
  border-color: transparent;
  border-radius: 0;
  font-weight: 600;
}

.nav-icon {
  flex: 0 0 18px;
  width: 18px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-faint);
  transition: color 0.15s ease;
}
.nav-fa {
  width: 18px;
  font-size: 16px;
  line-height: 1;
  text-align: center;
}

.nav-link:hover .nav-icon {
  color: var(--text-muted);
}

/* 激活: 图标加绿色小圆底 + 白色图标 */
.nav-link.is-active .nav-icon {
  flex: 0 0 24px;
  width: 24px;
  height: 24px;
  color: #fff;
  background: var(--brand);
  border-radius: 50%;
}
.nav-link.is-active .nav-fa {
  width: 14px;
  font-size: 12px;
}

/* ---- 发光滑块 (Uiverse glider 效果, 品牌绿): 沿左侧平滑滑到激活项 ---- */
/* height / transform(translateY) 由 JS(moveGlider) 按激活项位置设置 */
.nav-glider {
  position: absolute;
  left: 0;
  top: 0;
  width: 2px;
  height: 0;
  opacity: 0;
  pointer-events: none;
  z-index: 2;
  background: linear-gradient(
    180deg,
    transparent 0%,
    var(--brand) 50%,
    transparent 100%
  );
  transition: transform 0.5s cubic-bezier(0.37, 1.95, 0.66, 0.56),
    height 0.3s ease, opacity 0.2s ease;
}
/* 辉光 */
.nav-glider::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  height: 65%;
  width: 8px;
  background: var(--brand);
  filter: blur(11px);
}
/* 横向渐隐拖尾(向右淡入项内) */
.nav-glider::after {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: 120px;
  pointer-events: none;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--brand) 18%, transparent) 0%,
    transparent 100%
  );
}

.nav-label {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: #c8d0dc; /* 中文调亮(浅), 深背景上清晰; 与压暗的英文拉开对比 */
}
.nav-link:hover .nav-label,
.nav-link.is-active .nav-label {
  color: #fff;
}
/* 侧边栏 tab 中文后的小写英文标签 (压暗、小、缩进) —— 明显弱于中文 */
.nav-label-en {
  margin-left: 6px;
  font-size: 11px;
  font-weight: 400;
  color: #69727f;
}
.nav-link.is-active .nav-label-en {
  color: #97a2b1;
}
/* AJAX 切 tab 柔和过渡: 只淡入卡片内容(白卡容器不动, 不闪明暗), 纯 opacity 无位移, 0.3s 缓和 */
.content.tab-fade-in > * {
  animation: tabFadeIn 0.3s ease;
}
@keyframes tabFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ---- Content（第②层，独立悬浮白卡）---- */
.content {
  flex: 1;
  min-width: 0;
  position: relative;
  background: var(--surface);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-float);
  padding: 28px 30px;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: transparent transparent;
  transition: scrollbar-color 0.2s ease;
  display: grid;
  align-content: start;
  /* 行高按内容撑开: 否则直接子元素设了 overflow:hidden (卡片圆角裁切) 时, 网格会把那一行压到
     一屏以内, 内容被裁掉、内容区也就没有可滚动的高度 (2026-09-13 订阅清单页无法滚动) */
  grid-auto-rows: max-content;
  gap: 18px;
}


/* 骨架屏: AJAX 等待时的通用占位 (闪光动画) */
/* AJAX 加载: 内容卡片整体磨砂层 + 居中加载动画 */
.ajax-overlay {
  position: absolute;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.4);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  border-radius: var(--radius-xl);
  animation: ajaxOverlayIn 0.15s ease;
}
@keyframes ajaxOverlayIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

.page-header {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 12px;
  margin-bottom: 2px;
}

.page-header h1 {
  margin: 0;
  font-family: var(--sora);
  font-size: 24px;
  font-weight: 700;
  letter-spacing: -0.03em;
  display: inline-flex;
  align-items: center;
  gap: 9px;
}

.page-sub {
  margin: 0;
  color: var(--text-muted);
  font-size: 14px;
}

/* header 右侧操作按钮(如威胁情报「立即同步」)— 推到最右 + 垂直居中,
   不撑高 header(按钮用 btn-small, 高度不超过 h1 行高)。 */
.page-header-action {
  margin-left: auto;
  align-self: center;
}

.refresh-countdown {
  margin-left: auto;
  align-self: center;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  color: #94a3b8;
  background: #f1f5f9;
  border-radius: 8px;
  padding: 4px 11px;
}
.refresh-countdown b {
  font-family: var(--viga);
  font-variant-numeric: tabular-nums;
  color: #475569;
  min-width: 17px;
  text-align: right;
}
.refresh-countdown i {
  font-size: 11px;
}

.eyebrow,
.muted {
  margin: 0;
  color: var(--text-muted);
}

.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 14px;
}

.section-head h2 {
  margin: 0;
  font-family: var(--sora);
  font-size: 16px;
  letter-spacing: -0.02em;
}

.chart-summary {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* ============================================================
   Auth (login)
   ============================================================ */
.auth-body {
  min-height: 100vh;
  background: var(--bg);
  /* 登录页深色模式: 卡片 #0f0f0f, 控件 #1a1a1a, 文字/边框配深底 */
  --surface: #1a1a1a;
  --surface-muted: #161616;
  --text: #EEF2F7;
  --text-muted: #9BA6B4;
  --text-faint: #6B7480;
  --border: rgba(255, 255, 255, 0.12);
  --border-soft: rgba(255, 255, 255, 0.08);
}

.auth-shell {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 24px;
}

.auth-card {
  width: min(100%, 420px);
  padding: 34px;
  background: #0f0f0f;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-float);
}

/* ---- 登录卡片 (深色, 图标内嵌输入框) ---- */
.login-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}
.login-logo {
  width: 64px;
  height: 64px;
  border-radius: 15px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.02) 50%, rgba(255, 255, 255, 0.05) 100%);
  border: 1px solid rgba(255, 255, 255, 0.08);
}
.login-titles {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  text-align: center;
}
.login-brand-sub {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #6b7480;
  line-height: 1;
}
.login-subtitle {
  margin-top: 8px;
  font-size: 13px;
  color: #9ba6b4;
  line-height: 1.4;
}
.login-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
  width: 100%;
}
.login-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.login-label {
  font-size: 12px;
  font-weight: 600;
  color: #9ba6b4;
}
.login-input-wrap {
  position: relative;
  display: block;
}
.login-ic {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  width: 18px;
  height: 18px;
  color: #6b7480;
  pointer-events: none;
}
.login-input {
  width: 100%;
  height: 42px;
  padding: 0 12px 0 40px;
  border-radius: 8px;
  background: #1a1a1a;
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: #eef2f7;
  outline: none;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.login-input::placeholder {
  color: #5b626c;
}
.login-input:focus {
  border-color: transparent;
  box-shadow: 0 0 0 2px #65ca80;
}
.login-btn {
  width: 100%;
  height: 42px;
  border: 0;
  border-radius: 8px;
  background: #2faa50;
  color: #fff;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 0.15s ease;
}
.login-btn:hover {
  background: #23863e;
}
.login-sep {
  display: flex;
  align-items: center;
  gap: 16px;
  width: 100%;
  margin: 2px 0;
  color: #6b7480;
  font-size: 12px;
}
.login-line {
  flex: 1;
  height: 1px;
  border: 0;
  background: rgba(255, 255, 255, 0.1);
}
.login-btn-alt {
  width: 100%;
  height: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background: #1a1a1a;
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: #eef2f7;
  cursor: pointer;
  transition: background-color 0.15s ease;
}
.login-btn-alt:hover {
  background: #242424;
}

.brand-block {
  display: flex;
  align-items: center;
  gap: 11px;
  margin-bottom: 22px;
}

.brand-logo {
  width: 44px;
  height: 44px;
  border-radius: 11px;
  display: block;
  object-fit: contain;
  flex: 0 0 44px;
}

.brand-title {
  margin: 0;
  font-family: var(--viga);
  text-transform: uppercase;
  font-size: 23px;
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.1;
  display: inline-block;
  background: linear-gradient(257.34deg, #e2e6ea 14.04%, #909fb0 30.93%, #fff 90.58%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.brand-subtitle {
  margin: 2px 0 0;
  color: var(--text-faint);
  font-size: 10px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  line-height: 1.1;
}

.auth-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 18px 0 14px;
  color: var(--text-faint);
  font-size: 12px;
}

.auth-divider::before,
.auth-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

.auth-pk-msg {
  margin: 10px 0 0;
  font-size: 12px;
  text-align: center;
}

/* ============================================================
   Cards & layout grids
   ============================================================ */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md); /* Content cards sit inside the 16px workspace. */
  box-shadow: var(--shadow-pop);
  padding: 20px;
}

.grid-cards,
.two-col,
.three-col {
  display: grid;
  gap: 16px;
}

.grid-cards {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

/* ETL hero: 8 张统计卡一行, 收窄字号/内距以容纳 */
.etl-stat-row {
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: 8px;
}

.etl-stat-row .card {
  padding: 12px 12px;
}

.etl-stat-row .stat-card-label {
  font-size: 11px;
}

.etl-stat-row .stat-value {
  font-size: 19px;
}

@media (max-width: 1180px) {
  .etl-stat-row {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.two-col {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.three-col {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.chart-wrap {
  position: relative;
  height: 320px;
}

.stat-card {
  display: grid;
  gap: 6px;
}

/* 统计卡 label 行: 可带前置图标 */
.stat-card-label {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text-muted);
  font-size: 12px;
}

.stat-card-label svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

.stat-value {
  font-family: var(--sora);
  font-size: 32px;
  font-weight: 700;
  letter-spacing: -0.05em;
  /* 统一各统计卡数字行高 (系统概览/网站统计一致); 兼容数字滚动动画的 overflow */
  height: 1.25em;
  line-height: 1.25em;
  overflow: hidden;
}

/* 紧凑统计行: 4 卡一行、降低高度(威胁情报 hero 用) */
.stat-row-compact .card {
  padding: 12px 16px;
}

.stat-row-compact .stat-value {
  font-size: 22px;
}

.stat-row-compact .stat-time {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0;
}


.stat-tile {
  display: grid;
  gap: 4px;
  padding: 12px 14px;
  border-radius: var(--radius-md);
  background: var(--surface-muted);
}

.compact-gap {
  gap: 12px;
  margin: 14px 0;
}

/* ============================================================
   Forms
   ============================================================ */
.stack-lg,
.stack-md {
  display: grid;
  gap: 16px;
}

.stack-md {
  gap: 12px;
}

.field {
  display: grid;
  gap: 6px;
}

.field-grow {
  flex: 1;
}

.field-end {
  align-self: end;
}

label {
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 600;
}

input,
select,
textarea {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 11px 13px;
  color: var(--text);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

/* 复选框/单选框不该继承上面给文本框的 width:100%/padding (否则被撑满, 挤坏布局) */
input[type="checkbox"],
input[type="radio"] {
  width: auto;
  padding: 0;
  border-radius: 0;
}

input::placeholder,
textarea::placeholder {
  color: var(--text-faint);
}

/* select 统一自定义下拉箭头(替代浏览器原生, 跨浏览器一致 + 箭头位置可控,
   距右 13px 比原生贴边更靠左)。数据源表紧凑 select 单独缩短间距。 */
select {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 13px center;
  background-size: 14px;
  padding-right: 38px;
}
.sources-table select.cell-input {
  background-position: right 7px center;
  background-size: 12px;
  padding-right: 26px;
}

input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(47, 170, 80, 0.12);
}

/* 工具栏: tab + 搜索框 + 筛选 + 开关 一行对齐 */
.geo-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin: 0 0 14px;
}

/* 搜索框: 图标 + input 包裹, 整体一个圆角框, 聚焦时蓝环 */
/* 全后台统一搜索框: 与侧边栏 .sidebar-search 同款 (白底 + border-soft + 品牌聚焦环) */
.search-box {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 42px;
  padding: 0 12px;
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.search-box:focus-within {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 14%, transparent);
}

/* 统一搜索按钮: 圆形 + 放大镜 (图标 CSS mask 内置, HTML 只需 <button class="btn-search">) */
.btn-search {
  flex: none;
  width: 42px;
  min-width: 42px;
  height: 42px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--brand);
  cursor: pointer;
  display: inline-grid;
  place-items: center;
  transition: background-color 0.15s ease;
}

.btn-search:hover {
  background: var(--brand-dark);
}

.btn-search::before {
  content: "";
  width: 18px;
  height: 18px;
  background: #fff;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E") center / contain no-repeat;
}

.search-box > svg,
.search-box > i,
.search-box > .ti {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  font-size: 14px;
  line-height: 16px;
  text-align: center;
  color: var(--text-faint);
}

.search-box > input {
  width: 100%;
  border: none;
  background: transparent;
  padding: 0;
  height: auto;
}

.search-box > input:focus {
  outline: none;
  border: none;
  box-shadow: none;
}

.checkbox {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 42px;
}

.checkbox input {
  width: auto;
  margin: 0;
}

/* Toggle 开关: <label class="switch"><input type=checkbox><span class="switch-track"></span><span>文案</span></label> */
.switch {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 42px;
  cursor: pointer;
  font-size: 13px;
  color: var(--text-muted);
  user-select: none;
}

.switch input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.switch-track {
  position: relative;
  width: 38px;
  height: 22px;
  flex: none;
  border-radius: var(--radius-pill);
  background: #cbd5e1;
  transition: background-color 0.15s ease;
}

.switch-track::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 2px rgba(16, 24, 40, 0.2);
  transition: transform 0.15s ease;
}

.switch input:checked + .switch-track {
  background: var(--brand);
}

.switch input:checked + .switch-track::after {
  transform: translateX(16px);
}

.switch input:focus-visible + .switch-track {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 25%, transparent);
}

.inline-form,
.action-row,
.source-head,
/* 统一分页控件: 所有列表的 上一页/下一页/每页/页码 同一套样式 */
.pager {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 14px;
  font-size: 13px;
}

.pager .btn,
.pager a.btn {
  min-height: 32px;
  padding: 0 13px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-weight: 500;
}

.pager select,
.pager .cell-input {
  width: auto;
  min-width: 68px;
  min-height: 32px;
  padding-top: 0;
  padding-bottom: 0;
}

.pager .muted {
  font-size: 13px;
}

/* 分页组件 (全站通用): 首页/上一页/跳转输入/下一页/末页 */
.pager-bar {
  justify-content: space-between;
}
.pager-nav {
  display: flex;
  align-items: center;
  gap: 6px;
}
.pager-nav [aria-disabled="true"] {
  opacity: 0.4;
  pointer-events: none;
}
.pager-jump {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--text-muted);
  font-size: 13px;
  white-space: nowrap;
}
.pager-jump .cell-input {
  width: 54px;
  min-width: 54px;
  text-align: center;
  padding: 6px 4px;
}

/* 含带 label 的 .field 时, 控件与按钮按底部对齐(label 在控件上方,
   否则裸按钮居中对齐会与 field 内的 select/input 错位)。 */
.inline-form {
  align-items: flex-end;
}

.inline-only {
  display: inline;
}

/* IP 查询表单：搜索框 + 查询按钮同一行对齐；强制刷新单独一行 */
.query-form {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
}
.query-form .query-field {
  width: 100%;
}
.query-search-line {
  display: flex;
  align-items: center;
  gap: 12px;
}
.query-search-line input,
.query-search-line .search-box {
  flex: 1;
}

/* ============================================================
   Buttons
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 42px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0 16px;
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  font-weight: 500;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease;
}

.btn:hover {
  background: var(--surface-muted);
  border-color: var(--border);
}

.btn:active {
  transform: scale(0.98);
}

.btn-small {
  min-height: 34px;
  padding: 0 13px;
  border-radius: var(--radius-sm);
}

.btn-block {
  width: 100%;
}

/* ============================================================
   图标按钮 (全站统一): 列表行内的 编辑/删除/禁用/启用/刷新 等, 以及分页箭头。
   动作 → 图标/提示/色调 只在 row_actions.go 的 rowActions 定义:
   服务端模板用 {{actionBtn "delete"}}, JS 用 adminActionBtn("delete", {...})。
   页面里不要手写 class 或给按钮单独配色 —— 要新色调就在这里加 data-tone。
   悬浮 = 同色系加深一档 (不换色、不反白)。
   ============================================================ */
.icon-btn {
  --tone-fg: var(--text-muted);
  --tone-bg: var(--surface);
  --tone-bd: var(--border);
  --tone-fg-hover: var(--text);
  --tone-bg-hover: var(--surface-muted);
  --tone-bd-hover: #cdd2da;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 32px;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--tone-bd);
  border-radius: var(--radius-sm);
  background: var(--tone-bg);
  color: var(--tone-fg);
  font-size: 14px;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.icon-btn:hover {
  background: var(--tone-bg-hover);
  border-color: var(--tone-bd-hover);
  color: var(--tone-fg-hover);
}
.icon-btn:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}
.icon-btn:disabled,
.icon-btn[aria-disabled="true"] {
  opacity: 0.4;
  cursor: not-allowed;
  pointer-events: none;
}
.icon-btn i {
  line-height: 1;
}
.icon-btn.is-loading {
  pointer-events: none;
}
.icon-btn.is-loading i {
  animation: btn-spin 0.7s linear infinite;
}
.icon-btn[data-tone="primary"] {
  --tone-fg: var(--brand-dark);
  --tone-bg: var(--brand-soft);
  --tone-bd: #c3e6cd;
  --tone-fg-hover: #1d6f33;
  --tone-bg-hover: #dcf1e2;
  --tone-bd-hover: #9fd6ae;
}
.icon-btn[data-tone="warning"] {
  --tone-fg: var(--warn);
  --tone-bg: var(--warning-bg);
  --tone-bd: #f3d7a6;
  --tone-fg-hover: #92400e;
  --tone-bg-hover: #feeccb;
  --tone-bd-hover: #e8bd76;
}
.icon-btn[data-tone="danger"] {
  --tone-fg: var(--danger);
  --tone-bg: var(--danger-bg);
  --tone-bd: #f2c6c5;
  --tone-fg-hover: #b53b3a;
  --tone-bg-hover: #fbe2e2;
  --tone-bd-hover: #e7a3a2;
}

/* 行内操作列: 表头与单元格都加 col-actions, 按钮组放 .row-actions 里, 统一靠右 */
/* 加 :is(table) 抬一级权重, 压过后面 .table th 的 text-align:left */
:is(table) th.col-actions,
:is(table) td.col-actions {
  width: 1%;
  text-align: right;
  white-space: nowrap;
}
.row-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
}
.row-actions form {
  display: inline-flex;
  margin: 0;
}
/* 已禁用的行: 只把内容列置灰, 操作列保持正常 (否则「启用」按钮看起来也点不了) */
tr.is-disabled > td:not(.col-actions) {
  opacity: 0.5;
}

/* 类型徽章 / 类型筛选 tab 共用配色, 唯一定义处。类名 t-<tone> 由 page_handler.go asnTypeStyles 给出 */
.t-isp        { --c: #047857; --bg: #ecfdf5; --br: #a7f3d0; }
.t-hosting    { --c: #c2410c; --bg: #fff7ed; --br: #fed7aa; }
.t-cdn        { --c: #a16207; --bg: #fefce8; --br: #fde047; }
.t-business   { --c: #1d4ed8; --bg: #eff6ff; --br: #bfdbfe; }
.t-education  { --c: #6d28d9; --bg: #f5f3ff; --br: #ddd6fe; }
.t-government { --c: #475569; --bg: #f1f5f9; --br: #cbd5e1; } /* 灰: 中性说明, 不与 IDC 的琥珀混淆 (2026-09-13 用户定) */
.t-mobile     { --c: #0e7490; --bg: #ecfeff; --br: #a5f3fc; }
.t-risk       { --c: #b91c1c; --bg: #fef2f2; --br: #fecaca; }
.t-other      { --c: #475569; --bg: #f8fafc; --br: #e2e8f0; }
.badge.asn-type-badge {
  background: var(--bg);
  color: var(--c);
  border-color: var(--br);
}

/* 批处理进度条 (宽度由 JS 写 style.width) */
.progress-track {
  height: 8px;
  margin-bottom: 8px;
  overflow: hidden;
  background: var(--surface-muted);
  border-radius: var(--radius-pill);
}
.progress-fill {
  width: 0;
  height: 100%;
  background: var(--brand);
  transition: width 0.3s ease;
}

/* 表格单元格: 外链 (名称/ASN 跳转) 与副行文字 */
.ext-link {
  color: inherit;
  text-decoration: none;
}
.ext-link:hover {
  color: var(--brand-dark);
}
.ext-link i {
  margin-left: 4px;
  font-size: 10px;
  color: var(--text-faint);
}
.cell-sub {
  color: var(--text-muted);
  font-size: 12px;
}
.cell-flag {
  width: 16px;
  height: 12px;
  margin-right: 8px;
  object-fit: cover;
  vertical-align: -1px;
  box-shadow: 0 0 0 1px var(--border);
}
.table th[data-sort] {
  cursor: pointer;
  user-select: none;
}
.table td.nowrap {
  white-space: nowrap;
}
.pager-nav .pager-pp {
  width: auto;
  min-width: 96px;
  margin-left: 8px;
}

/* 区块标题旁的数量 "(N)" */
.section-count {
  color: var(--text-muted);
  font-family: var(--viga);
  font-weight: 400;
  font-variant-numeric: tabular-nums;
}

/* 编辑弹窗: 头部以下每一块 (填充条/字段组/文本框) 统一间距 */
.fb-modal .modal-block {
  margin-top: 16px;
}

/* 编辑弹窗底部按钮区: 分隔线 + 左侧状态文字 */
.fb-modal-actions.is-footer {
  align-items: center;
  margin-top: 24px;
  padding-top: 16px;
  border-top: 1px solid var(--border-soft);
}
.fb-modal-actions .modal-msg {
  margin-right: auto;
  color: var(--text-muted);
  font-size: 13px;
}

.btn-primary {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}

.btn-primary:hover {
  background: var(--brand-dark);
  border-color: var(--brand-dark);
}

.btn-secondary {
  background: var(--surface);
  border-color: var(--border);
}

.btn-secondary:hover {
  background: var(--surface-muted);
  border-color: var(--border);
}

.btn-ghost {
  background: var(--surface);
  border-color: var(--border);
  color: var(--text-muted);
}

/* ---- 新建/新增 按钮 (Uiverse 风格, 品牌蓝): 默认 文字 + 右侧加号(竖线分隔);
   hover 文字淡出、加号区横向展开铺满整钮。适配变长文字(加号绝对定位靠右)。 ---- */
.btn-add {
  position: relative;
  display: inline-flex;
  align-items: center;
  height: 40px;
  padding: 0 50px 0 16px;
  background: var(--brand);
  border: none;
  border-radius: 6px;
  box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.15);
  color: #fff;
  font-weight: 700;
  font-size: 13px;
  white-space: nowrap;
  cursor: pointer;
  overflow: hidden;
  transition: background-color 200ms ease;
}
.btn-add .text {
  transition: opacity 200ms ease;
}
.btn-add .icon {
  position: absolute;
  top: 0;
  right: 0;
  width: 38px;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  border-left: 1px solid rgba(255, 255, 255, 0.28);
  transition: width 200ms ease, border-color 200ms ease;
}
.btn-add .icon i {
  color: #fff;
  font-size: 13px;
  transition: transform 200ms ease;
}
.btn-add:hover {
  background: var(--brand-dark);
}
.btn-add:hover .text {
  opacity: 0;
}
.btn-add:hover .icon {
  width: 100%;
  border-left-color: transparent;
}
.btn-add:active .icon i {
  transform: scale(0.82);
}
.btn-add:focus {
  outline: none;
}

.btn-ghost:hover {
  background: var(--surface-muted);
  color: var(--text);
}

.btn-danger {
  background: var(--danger);
  border-color: var(--danger);
  color: #fff;
}

.btn-danger:hover {
  background: #c23f3f;
  border-color: #c23f3f;
}

.btn .btn-spinner {
  display: none;
  width: 14px;
  height: 14px;
  border: 2px solid rgba(255, 255, 255, 0.55);
  border-top-color: #fff;
  border-radius: 50%;
  animation: btn-spin 0.75s linear infinite;
}

.btn.is-loading {
  cursor: progress;
  opacity: 0.82;
}

.btn.is-loading .btn-spinner {
  display: inline-block;
}

@keyframes btn-spin {
  to {
    transform: rotate(360deg);
  }
}

/* ============================================================
   Flash
   ============================================================ */
.flash {
  border-radius: var(--radius-md);
  padding: 12px 14px;
  margin-bottom: 18px;
  border: 1px solid var(--border);
}

.flash-success {
  background: var(--success-bg);
  border-color: #c5d8fb;
  color: var(--brand-dark);
}

.flash-error {
  background: var(--danger-bg);
  border-color: #efc7c7;
  color: #a93a3a;
}

.flash-warning {
  background: var(--warning-bg);
  border-color: #f0d394;
  color: #8f6214;
}

.ajax-status {
  margin: 12px 0 0;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  border: 1px solid var(--border-soft);
}

.ajax-status-info {
  background: var(--surface-soft);
  color: var(--brand-dark);
}

.ajax-status-success {
  background: var(--success-bg);
  color: var(--brand-dark);
}

.ajax-status-error {
  background: var(--danger-bg);
  color: var(--danger);
}

/* ============================================================
   Tables
   ============================================================ */
.table-scroll {
  overflow-x: auto;
}

.table {
  width: 100%;
  border-collapse: collapse;
}

.table th,
.table td {
  border-top: 1px solid var(--border-soft);
  padding: 12px 10px;
  text-align: left;
  vertical-align: middle;
}

.table thead th {
  border-top: none;
  color: var(--text-faint);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.07em;
}

.table tbody tr:hover {
  background: var(--surface-muted);
}

#ips-list-card {
  transition: opacity 0.15s ease;
}

#ips-list-card.is-ajax-loading {
  opacity: 0.58;
  pointer-events: none;
}

#ips-list-card [aria-disabled="true"] {
  pointer-events: none;
}

.ip-with-flag {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}

.flag-icon {
  width: 20px;
  height: 15px;
  flex: 0 0 20px;
  object-fit: cover;
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08);
}

/* ============================================================
   Misc content blocks
   ============================================================ */
.code-block {
  margin: 0;
  padding: 14px;
  overflow: auto;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  background: var(--surface-muted);
  color: var(--text);
  font: 12px/1.6 ui-monospace, SFMono-Regular, Menlo, monospace;
}





.muted-block {
  color: var(--text-muted);
  line-height: 1.7;
}

.plain-list {
  margin: 0;
  padding-left: 18px;
}

.plain-list li + li {
  margin-top: 6px;
}

.details summary {
  cursor: pointer;
  font-weight: 600;
  margin-bottom: 14px;
  color: var(--brand);
}

/* ============================================================
   Badges & flags
   ============================================================ */
.flag-wrap {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  background: var(--surface-soft);
  color: var(--brand-dark);
  font-size: 12px;
  font-weight: 600;
}

/* 统一 ASN 类别徽章: 图标比文字略小 */
.asn-type-badge i {
  font-size: 0.9em;
}

/* 类型徽章旁的风控命中标记 (VPN 标记 / 代理标记): 只描边不填底, 不与类型徽章混淆 */
.badge.ip-flag-badge {
  margin-left: 4px;
  background: transparent;
  color: #b91c1c;
  border-color: #fecaca;
  font-weight: 500;
}

.badge-safe {
  background: var(--surface-soft);
  border-color: #c5d8fb;
  color: var(--brand-dark);
}

.badge-info {
  background: #edf4ff;
  border-color: #c5d8fb;
  color: var(--brand);
}

.badge-muted {
  background: var(--surface-muted);
  border-color: var(--border);
  color: var(--text-muted);
}

.badge-caution,

.badge-danger,
.badge-block {
  background: #ffecec;
  border-color: #f0cbcb;
  color: #b43f3f;
}

/* 来源徽标: AI 蓝 / 人工 绿 / 中文源·内置 灰 */
.badge-ai {
  background: var(--brand-soft);
  border-color: #bcd2fb;
  color: var(--brand);
}

.badge-native {
  background: var(--surface-muted);
  border-color: var(--border);
  color: var(--text-muted);
}

.badge-admin {
  background: #e6f4ec;
  border-color: #b6e0c6;
  color: #1d7a46;
}

/* ============================================================
   Metrics & progress
   ============================================================ */








/* ============================================================
   Chip tabs（数据源/字段配置等的子标签，参考图筛选 chips）
   ============================================================ */
/* 分段控件: 浅灰容器内嵌药丸, 选中态白底浮起 (统一全站 tab) */
.tab-row {
  display: inline-flex;
  gap: 3px;
  flex-wrap: wrap;
  margin-bottom: 18px;
  padding: 3px;
  background: var(--surface-muted);
  border-radius: var(--radius-pill);
  max-width: 100%;
}

.tab-link {
  padding: 6px 14px;
  border-radius: var(--radius-pill);
  background: transparent;
  border: none;
  color: var(--text-muted);
  font-weight: 500;
  transition: background-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
}

.tab-link:hover {
  background: rgba(0, 0, 0, 0.045);
  color: var(--text);
}

.tab-link.is-active {
  background: var(--surface);
  color: var(--brand);
  font-weight: 500;
  box-shadow: 0 1px 2px rgba(16, 24, 40, 0.08);
}

/* 徽章式分类 tab: 未选=浅色徽章底(图标+配色), 选中=实色填充。颜色由内联 --c/--bg/--br 提供。 */
.tab-link.tab-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: var(--bg);
  color: var(--c);
  border: 1px solid var(--br);
}
.tab-link.tab-badge i {
  font-size: 0.9em;
}
.tab-link.tab-badge.is-active {
  background: var(--c);
  color: #fff;
  border-color: var(--c);
  box-shadow: none;
}

/* ============================================================
   数据源配置：卡片网格 + 每源「配置」弹窗 (复用 fb-modal 骨架)
   ============================================================ */
.src-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 12px;
}

.src-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 14px;
}

.src-card.is-off {
  opacity: 0.7;
}

.src-card-top {
  display: flex;
  align-items: center;
  gap: 9px;
}

.src-card-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.src-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface-muted);
  color: var(--text-muted);
  font-size: 11px;
  font-weight: 600;
}

.src-badge.is-paid {
  border-color: var(--warn);
  background: var(--warning-bg);
  color: var(--warn);
}

.src-badge.is-key {
  border-color: var(--brand);
  background: var(--brand-soft);
  color: var(--brand-dark);
}

.src-badge.is-muted {
  color: var(--text-faint);
}

.src-card-usage {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 12px;
}

.src-card-foot {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: auto;
}

.src-card-foot form {
  margin: 0;
}

.src-card-foot > .btn:first-child {
  flex: 1;
}

/* 配置弹窗内的表单 */
.src-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 16px;
}

.src-form-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.src-form-field > span {
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 600;
}

.src-form .cell-input {
  width: 100%;
  min-height: 34px;
  padding: 7px 10px;
  border-radius: var(--radius-sm);
  font-size: 13px;
}

.src-form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.src-form-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 2px;
}

.src-keys-wrap {
  margin-top: 14px;
  border-top: 1px solid var(--border-soft);
  padding-top: 12px;
}

.fb-modal-head h3 .src-id {
  margin-left: 4px;
  font-size: 11px;
  font-weight: 400;
  color: var(--text-faint);
}

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

.src-name-text {
  display: flex;
  flex-direction: column;
  line-height: 1.25;
}

.src-name-text strong {
  font-size: 13px;
}

.src-id {
  font-size: 11px;
  color: var(--text-faint);
}

.src-dot {
  width: 8px;
  height: 8px;
  flex: 0 0 8px;
  border-radius: 50%;
  background: var(--text-faint);
}

.src-dot.on {
  background: #16a34a;
}

/* 数据源能力矩阵 (替换原字段来源映射): 源 × 能力, 底行统计启用源数, 单点标红 */
.section-head-icon {
  margin-right: 8px;
  color: var(--text-faint);
}

.cap-matrix {
  min-width: 920px;
  table-layout: fixed; /* 源名称列定宽, 8 个能力列等分 (自动布局会把第一列撑到半屏) */
}

.cap-matrix thead th:first-child {
  width: 300px;
}

.cap-matrix th,
.cap-matrix td {
  padding-top: 8px;
  padding-bottom: 8px;
}

/* 行首是 th (语义), 但 .review-workspace .table th 会给所有 th 刷灰底 + 11px, 这里还原成普通行 */
.review-workspace .cap-matrix tbody th {
  background: transparent;
  color: var(--text);
  font-size: 13px;
}

.cap-matrix th.cap-col,
.cap-matrix td.cap-cell {
  text-align: center;
  white-space: nowrap;
}

.cap-matrix th.cap-col {
  cursor: help;
}

.cap-matrix .cap-src {
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cap-src-inner {
  display: flex;
  align-items: center;
  gap: 8px;
}

.cap-matrix tbody tr.is-off .cap-src-name,
.cap-matrix tbody tr.is-off .cap-yes {
  opacity: 0.45;
}

.cap-yes {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--brand);
}

.cap-matrix tfoot th,
.cap-matrix tfoot td {
  border-top: 1px solid var(--border);
  background: var(--surface-muted);
  font-size: 12px;
}

.cap-total {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  cursor: help;
}

.cap-total.is-single {
  background: var(--danger-bg);
  color: var(--danger);
}

.cap-total.is-single i {
  margin-right: 4px;
  font-size: 11px;
}

.cap-note {
  margin: 12px 0 0;
  font-size: 12px;
}

.cap-note i {
  margin-right: 4px;
  color: var(--danger);
}

.src-cap-tags {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-bottom: 12px;
  font-size: 12px;
}

.src-usage {
  font-variant-numeric: tabular-nums;
  font-size: 12.5px;
}

.fb-reply {
  margin-top: 10px;
  padding: 8px 10px;
  border-left: 3px solid #35a952;
  background: #f0fdf4;
  color: var(--text);
}

.fb-reply strong {
  color: #166534;
}

.fb-reply span {
  display: block;
  margin-top: 4px;
}

.fb-modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(20, 28, 40, 0.36);
}

.fb-modal-backdrop.is-open {
  display: flex;
}

.fb-modal {
  width: min(620px, 100%);
  max-height: min(760px, calc(100vh - 48px));
  overflow: auto;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  background: var(--surface);
  box-shadow: var(--shadow-float);
  padding: 22px;
}

.fb-modal-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

.fb-modal-head h3 {
  margin: 0;
  font-family: var(--sora);
  font-size: 18px;
  line-height: 1.25;
}

.fb-modal-head p {
  margin: 6px 0 0;
  color: var(--text-muted);
  font-size: 13px;
}

.fb-modal-close {
  width: 34px;
  height: 34px;
  flex: 0 0 34px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
  font-size: 22px;
  line-height: 1;
}

.fb-modal-close:hover {
  background: var(--surface-muted);
  color: var(--text);
}

.fb-modal-meta {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin-top: 18px;
}

.fb-modal-meta div {
  min-width: 0;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  background: var(--surface-muted);
  padding: 10px 12px;
}

.fb-modal-meta span {
  display: block;
  color: var(--text-faint);
  font-size: 11px;
  font-weight: 700;
}

.fb-modal-meta strong {
  display: block;
  margin-top: 3px;
  overflow: hidden;
  color: var(--text);
  font-size: 13px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.fb-modal-message {
  max-height: 160px;
  overflow: auto;
  margin-top: 12px;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  background: #fbfcfe;
  padding: 12px;
  color: var(--text-muted);
  font-size: 13px;
  white-space: pre-wrap;
  word-break: break-word;
}

.fb-modal-field {
  display: grid;
  gap: 8px;
  margin-top: 14px;
}

.fb-modal-field textarea {
  min-height: 150px;
  resize: vertical;
}

.fb-modal-error {
  min-height: 22px;
  margin-top: 10px;
  color: var(--danger);
  font-size: 13px;
}

.fb-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 6px;
}

/* 右下角堆叠 toast — 复刻 LiteNote 风格 */
.admin-toast-stack {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 2000;
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-end;
  width: auto;
  max-width: calc(100vw - 48px);
  pointer-events: none;
}

.admin-toast {
  display: inline-flex;
  gap: 8px;
  align-items: center;
  justify-content: flex-start;
  width: auto;
  max-width: 100%;
  min-height: 44px;
  padding: 10px 14px;
  overflow: hidden;
  font-size: 13px;
  font-weight: 600;
  color: #fff;
  pointer-events: auto;
  background: #0f172a;
  border: 1px solid rgba(15, 23, 42, 0.1);
  border-radius: 8px;
  box-shadow: 0 12px 28px rgba(15, 23, 42, 0.18);
  animation: toast-in 0.2s ease-out;
}

.admin-toast > svg {
  flex: 0 0 20px;
  width: 20px;
  height: 20px;
}

.admin-toast > .admin-toast-message {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.45;
  color: #fff;
  overflow-wrap: anywhere;
}

.admin-toast-success > svg {
  color: #22c55e;
}

.admin-toast-error > svg {
  color: #ef4444;
}

.admin-toast.is-leaving {
  animation: toast-out 0.18s ease-in forwards;
}

@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes toast-out {
  to {
    opacity: 0;
    transform: translateY(8px);
  }
}

.list-add-form {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.threat-pager-ctl {
  display: flex;
  gap: 12px;
  align-items: center;
  font-size: 13px;
}

.threat-pager-ctl select {
  width: auto;
  min-width: 64px;
  margin-left: 4px;
}

.fb-toast {
  position: fixed;
  top: 22px;
  right: 22px;
  z-index: 1100;
  display: none;
  max-width: min(420px, calc(100vw - 44px));
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-pop);
  padding: 12px 14px;
  color: var(--text);
  font-size: 13px;
}

.fb-toast.is-show {
  display: block;
}

.fb-toast.success {
  border-color: #86efac;
  background: #f0fdf4;
  color: #166534;
}

.fb-toast.warn {
  border-color: #f8d28b;
  background: var(--warning-bg);
  color: #8a5a00;
}

/* ============================================================
   Responsive
   ============================================================ */
@media (max-width: 1200px) {
  .grid-cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .three-col {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 720px) {
  .admin-shell {
    height: auto;
    min-height: 100vh;
    flex-direction: column;
    overflow: visible;
    padding: 12px;
  }

  .sidebar {
    flex: none;
    width: 100%;
    display: flex;
    flex-direction: column;
    overflow: visible;
  }

  .sidebar-nav {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 10px;
  }

  .nav-group {
    flex: 1 1 160px;
  }

  .content {
    padding: 20px 18px;
  }

  .two-col,
  .three-col,
  .grid-cards {
    grid-template-columns: 1fr;
  }
}

/* ============================================================
   缓存管理页 (/admin/cache) - 动态指标卡片
   - 4 张 hero 卡: 总键数 / 命中率(圆环) / 内存(圆环) / QPS
   - 6 张 sub-stat 卡: 客户端 / 驱逐 / 过期 / 片段化 / 版本 / Uptime
   - 数字 transition 0.5s 平滑过渡, 圆环 conic-gradient + @property 动画
   - 5s 轮询 /admin/api/cache/stats 时数字会"补间"而不是跳变
   ============================================================ */
@property --gauge-pct {
  syntax: '<number>';
  initial-value: 0;
  inherits: false;
}

.cache-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  margin-bottom: 20px;
}

@media (max-width: 1100px) {
  .cache-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

.cache-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 18px 20px;
  box-shadow: var(--shadow-card);
  display: flex;
  align-items: center;
  gap: 16px;
  min-height: 132px;
}

.cache-card-body {
  flex: 1;
  min-width: 0;
}

.cache-card-label {
  font-size: 12px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 0 0 6px;
}

.cache-card-value {
  font-size: 28px;
  font-weight: 600;
  color: var(--text);
  letter-spacing: -0.01em;
  line-height: 1.1;
  margin: 0;
  font-variant-numeric: tabular-nums;
  transition: color 0.3s ease;
}

.cache-card-hint {
  font-size: 12px;
  color: var(--text-faint);
  margin-top: 4px;
}

/* 圆形动态仪表盘. CSS 自定义属性 --gauge-pct (0~100) + conic-gradient 实现.
   --gauge-color 控制环色, hit-rate 用 brand, memory 按阈值切到 warning/danger. */
.gauge {
  --gauge-size: 96px;
  --gauge-pct: 0;
  --gauge-color: var(--brand);
  width: var(--gauge-size);
  height: var(--gauge-size);
  border-radius: 50%;
  background: conic-gradient(
    var(--gauge-color) calc(var(--gauge-pct) * 1%),
    var(--surface-muted) 0
  );
  display: grid;
  place-items: center;
  position: relative;
  flex-shrink: 0;
  transition: --gauge-pct 0.6s cubic-bezier(0.4, 0, 0.2, 1),
              background 0.3s ease;
}

.gauge::before {
  content: "";
  position: absolute;
  inset: 10px;
  background: var(--surface);
  border-radius: 50%;
}

.gauge-text {
  position: relative;
  font-size: 18px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

/* 状态色: 内存 / 命中率 越靠近 100% 越好/越糟看场景 */
.gauge.is-warn { --gauge-color: #f59e0b; }
.gauge.is-danger { --gauge-color: var(--danger); }
.gauge.is-low { --gauge-color: var(--danger); } /* 命中率低=红 */
.gauge.is-mid { --gauge-color: #f59e0b; }

/* gauge 中心 icon (替代原 emoji ⬢/⚡, 用于无百分比的装饰卡: 总键数 / 每秒操作) */
.gauge-text svg {
  width: 30px;
  height: 30px;
  stroke: var(--brand);
  display: block;
}
/* 装饰性满环 gauge (aria-hidden) 缓慢呼吸 + 中心 icon 脉动, 让缓存页有动态感 */
.gauge[aria-hidden="true"] {
  animation: gauge-breathe 3.2s ease-in-out infinite;
}
.gauge[aria-hidden="true"] .gauge-text svg {
  animation: gauge-icon-pulse 3.2s ease-in-out infinite;
}
@keyframes gauge-breathe {
  0%, 100% { opacity: 0.9; }
  50% { opacity: 1; filter: brightness(1.08); }
}
@keyframes gauge-icon-pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.12); }
}

/* 二级指标卡(更小, 紧凑) */
.cache-sub-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 12px;
  margin-bottom: 20px;
}

@media (max-width: 1100px) {
  .cache-sub-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (max-width: 640px) {
  .cache-sub-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

.cache-sub {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
}

.cache-sub-label {
  font-size: 11px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 0 0 4px;
}

.cache-sub-value {
  font-size: 17px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  transition: color 0.3s ease;
}

.cache-sub-value.is-warn { color: #b45309; }
.cache-sub-value.is-danger { color: var(--danger); }

/* DB 表格 */
.cache-db-table {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}

.cache-db-table th,
.cache-db-table td {
  padding: 10px 14px;
  text-align: left;
  border-bottom: 1px solid var(--border-soft);
}

.cache-db-table th {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  font-weight: 500;
}

.cache-db-table tbody tr:last-child td {
  border-bottom: 0;
}

/* 实时刷新指示器 + 上次更新时间 */
.cache-refresh-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 14px;
  color: var(--text-muted);
  font-size: 12px;
}

.cache-pulse {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #10b981;
  animation: cache-pulse 2s ease-in-out infinite;
}

@keyframes cache-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.5); }
  50% { box-shadow: 0 0 0 6px rgba(16, 185, 129, 0); }
}

/* 折叠原始 INFO */
.cache-raw-details {
  margin-top: 24px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 14px 18px;
}

.cache-raw-details summary {
  cursor: pointer;
  font-size: 13px;
  color: var(--text-muted);
  user-select: none;
}

.cache-raw-details summary:hover { color: var(--text); }

.cache-raw-details pre {
  margin: 12px 0 0;
  padding: 12px;
  background: var(--surface-muted);
  border-radius: var(--radius-sm);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 12px;
  line-height: 1.55;
  color: var(--text);
  white-space: pre-wrap;
  word-break: break-all;
  max-height: 360px;
  overflow-y: auto;
}

/* 危险操作分区 (清除缓存) */
.cache-danger-zone {
  margin-top: 20px;
  padding: 14px 18px;
  background: var(--danger-bg);
  border: 1px solid #f1c0bf;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.cache-danger-zone-text {
  font-size: 13px;
  color: var(--text);
}

.cache-danger-zone-text strong {
  color: var(--danger);
}

/* ============================================================
   系统概览增强: 页头/区块标题 icon + 付费源消费卡 + 本地库新鲜度
   ============================================================ */

/* 页头标题 icon (跟侧边栏同款 Font Awesome) */
.page-header h1 {
  display: inline-flex;
  align-items: center;
  gap: 9px;
}
.page-title-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  color: var(--brand);
  flex-shrink: 0;
}
.page-title-icon .nav-fa {
  width: 21px;
  font-size: 20px;
}

/* 区块标题 icon */
.section-head h2 {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.section-icon {
  width: 18px;
  font-size: 15px;
  text-align: center;
  line-height: 1;
  color: var(--brand);
  flex-shrink: 0;
}

/* 付费源消费卡 */
/* 数据源卡片: 每行一个, 卡片内部水平排布 (名称 | 数字 | 单价 | 进度条 | 柱图) */
/* ============================================================
   数据源用量卡 (sourcesUsageCards): 付费 / 免费多 key / 其他 三组共用一套
   卡片骨架 — 头部(名+徽章+健康点) · 今日大数字+近7天柱图 · 容量区(配额进度/
   剩余额度 或 多 key 可用数) · 脚注。三段色 ok/warn/crit 贯穿圆点与进度条。
   ============================================================ */
/* 顶部汇总条 */
.usage-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px;
  margin-bottom: 16px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.usage-summary .cell {
  background: var(--surface);
  padding: 13px 16px;
}
.usage-summary .k {
  margin-bottom: 5px;
  font-size: 12px;
  color: var(--text-muted);
}
.usage-summary .v {
  font-size: 22px;
  font-weight: 600;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.usage-summary .v small {
  margin-left: 3px;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-faint);
}
.usage-summary .v.is-warn {
  color: var(--warn);
}

/* 卡网格: 自适应平铺, 窄屏自动单列 */
.su-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 12px;
}
.su-card {
  display: flex;
  flex-direction: column;
  gap: 11px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px 12px;
  background: var(--surface);
  cursor: context-menu; /* 提示可右键打开配置弹窗 */
}

/* 头部 */
.su-head {
  display: flex;
  align-items: center;
  gap: 9px;
}
/* 卡头齿轮: 点击(或右键卡片)打开对应源的 srccfg 配置弹窗 */
.su-gear {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-faint);
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}
.su-gear:hover {
  color: var(--brand-dark);
  border-color: var(--brand);
  background: var(--surface-soft);
}
.su-gear svg {
  width: 14px;
  height: 14px;
}
.su-name {
  flex: 1;
  min-width: 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.su-badge {
  flex: 0 0 auto;
  padding: 2px 7px;
  border-radius: var(--radius-pill);
  font-size: 10.5px;
  font-weight: 600;
  white-space: nowrap;
}
.su-badge.paid {
  background: var(--surface-soft);
  color: var(--brand-dark);
}
.su-badge.free {
  background: var(--surface-muted);
  color: var(--text-muted);
}
.su-dot {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
}
.su-dot.ok { background: var(--brand); }
.su-dot.warn { background: var(--warn-fill); }
.su-dot.crit { background: var(--danger); }
.su-dot.off { background: var(--text-faint); }

/* 今日大数字 + 近 7 天柱图 */
.su-today {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 14px;
}
.su-today .big {
  font-size: 27px;
  font-weight: 600;
  line-height: 1;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.su-today .lbl {
  margin-top: 4px;
  font-size: 11px;
  color: var(--text-muted);
}
.su-trend {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
}
.su-bars {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 28px;
}
.su-bars i {
  display: block;
  width: 6px;
  border-radius: 2px 2px 0 0;
  background: color-mix(in srgb, var(--brand) 42%, transparent);
}
.su-bars i:last-child { /* 今日那根(最新)加深 */
  background: var(--brand);
}
.su-trend .cap {
  font-size: 10.5px;
  color: var(--text-faint);
}

/* 容量区: 配额进度 + 剩余额度绝对值 */
.su-cap {
  border-top: 1px solid var(--border-soft);
  padding-top: 10px;
}
.su-cap-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 7px;
  font-size: 12px;
  color: var(--text-muted);
}
.su-cap-row b {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.su-remain {
  font-weight: 600;
  white-space: nowrap;
}
.su-remain.ok { color: var(--brand-dark); }
.su-remain.warn { color: var(--warn); }
.su-remain.crit { color: var(--danger); }
.su-bar {
  height: 7px;
  border-radius: var(--radius-pill);
  background: var(--surface-muted);
  overflow: hidden;
}
.su-bar-fill {
  height: 100%;
  border-radius: var(--radius-pill);
  transition: width 0.4s ease;
}
.su-bar-fill.ok { background: var(--brand); }
.su-bar-fill.warn { background: var(--warn-fill); }
.su-bar-fill.crit { background: var(--danger); }

/* 容量区: 多 key 源「还有几把可用」+ 每 key chip */
.su-keys-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 9px;
}
.su-keys-head .big {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
}
.su-keys-head .big .avail { color: var(--brand-dark); }
.su-keys-head .big .avail.none { color: var(--danger); }
.su-keys-head .cap {
  font-size: 11px;
  color: var(--text-faint);
}
.su-keychips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.keychip {
  flex: 1 1 auto;
  min-width: 62px;
  padding: 6px 8px;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm);
  background: var(--surface-muted);
}
.keychip .m {
  font: 11px/1.3 ui-monospace, "SF Mono", Menlo, monospace;
  color: var(--text-faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.keychip .n {
  margin-top: 2px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.keychip .kb {
  height: 3px;
  margin-top: 5px;
  border-radius: var(--radius-pill);
  background: var(--surface);
  overflow: hidden;
}
.keychip .kb i {
  display: block;
  height: 100%;
  background: var(--brand);
  border-radius: var(--radius-pill);
}
.keychip.over {
  border-color: #f1c0bf;
  background: var(--danger-bg);
}
.keychip.over .n { color: var(--danger); }
.keychip.over .kb i { background: var(--danger); }

/* 脚注 */
.su-foot {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  border-top: 1px solid var(--border-soft);
  padding-top: 9px;
  font-size: 11px;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}
.su-foot .spend {
  color: var(--brand-dark);
  font-weight: 600;
}
.su-foot .paused {
  color: var(--warn);
  font-weight: 600;
}
.su-foot .sep { color: var(--border); }

/* 本地库新鲜度卡 */
.local-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 12px;
}
.local-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  background: var(--surface);
}
.local-card-name {
  font-weight: 600;
  font-size: 14px;
  color: var(--text);
  margin-bottom: 8px;
}
.local-card-stat {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 4px;
}
.local-date {
  font-size: 17px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.local-ago {
  font-size: 12px;
  color: var(--text-muted);
}
.local-ago.is-stale {
  color: var(--danger);
  font-weight: 600;
}
.local-card-size {
  font-size: 11px;
  color: var(--text-faint);
}
.local-missing {
  color: var(--danger);
  font-weight: 600;
  font-size: 14px;
}

/* ── 确认弹窗 ──
   替代浏览器原生 confirm(): 原生弹窗的外观由浏览器决定, 与后台的设计体系无关,
   且不能区分「删除」这类不可逆动作与普通确认 —— 用户看到的永远是同一个灰框。
   这里复用后台已有的 modal token (--surface / --border-soft / --shadow-float),
   危险操作用红色主按钮明示后果。 */
.cfm-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1200; /* 高于 fb-modal 的 1000: 确认框可能从已打开的弹窗里唤起 */
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(20, 28, 40, 0.36);
}
.cfm-backdrop.is-open { display: flex; }

.cfm-box {
  width: min(420px, 100%);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  background: var(--surface);
  box-shadow: var(--shadow-float);
  padding: 22px;
}
.cfm-box h3 {
  margin: 0 0 8px;
  font-family: var(--sora);
  font-size: 17px;
  line-height: 1.3;
}
.cfm-box p {
  margin: 0;
  color: var(--text-muted);
  font-size: 14px;
  line-height: 1.6;
  word-break: break-word;
}
.cfm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 20px;
}
/* 危险动作的主按钮用实心红: 弹窗文字可以不读, 按钮颜色一定看得见 */
.cfm-actions .btn-danger {
  background: #DC2626;
  border-color: #DC2626;
  color: #fff;
}
.cfm-actions .btn-danger:hover { background: #B91C1C; border-color: #B91C1C; }

/* ═══ 通用弹窗 ═══
   合作方页面(.modal / .modal-box / …)与表单双列栅格(.grid-2)一直没写样式 ——
   模板按这套类名写好了, CSS 从来没补上, 结果弹窗是裸的: 没有遮罩、不居中,
   直接铺在页面最底下, 表单也不分列。2026-08-31 补。

   与既有的 .fb-modal-* (反馈弹窗)是两套: 那套的类名带 fb- 前缀、绑死在反馈场景,
   这套是通用的, 后续页面直接复用。设计语言对齐 .fb-modal-*, 换皮不换风格。

   ⚠ .is-open 加在 .modal(遮罩层)本身, 不是内层 —— 模板的 JS 就是这么切的,
   改类名要同步 admin.gohtml 里的 openM/closeM。 */
.modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(20, 28, 40, 0.36);
}

.modal.is-open {
  display: flex;
}

.modal-box {
  display: flex;
  flex-direction: column;
  width: min(620px, 100%);
  max-height: calc(100vh - 48px);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  background: var(--surface);
  box-shadow: var(--shadow-float);
}

.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex: none;
  padding: 18px 22px;
  border-bottom: 1px solid var(--border-soft);
}

.modal-head h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: var(--text);
}

/* 只有中间这段滚动, 标题与按钮排始终可见 —— 合作方那个表单很长(20+ 个字段),
   整体滚动的话保存按钮会被推到看不见的地方。 */
.modal-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 20px 22px;
}

.modal-foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  flex: none;
  padding: 14px 22px;
  border-top: 1px solid var(--border-soft);
}

/* 预览链接推到最左, 与右侧的取消/保存分开 —— 它是"去别处看看"而不是提交动作 */
.modal-foot > :first-child {
  margin-right: auto;
}

.modal-x {
  width: 34px;
  height: 34px;
  flex: 0 0 34px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
  font-size: 22px;
  line-height: 1;
}

.modal-x:hover {
  border-color: var(--brand);
  color: var(--brand);
}

.modal-x:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}

/* 表单双列。窄屏塌成单列 —— 后台在笔记本上常开着侧栏, 内容区并不宽。 */
.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px 16px;
  margin-bottom: 12px;
}

@media (max-width: 720px) {
  .grid-2 {
    grid-template-columns: 1fr;
  }
}

.modal-body .field {
  margin-bottom: 12px;
}

.modal-body .field > label {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-muted);
}

.modal-body .field input[type="text"],
.modal-body .field input[type="number"],
.modal-body .field textarea {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 13.5px;
}

.modal-body .field textarea {
  resize: vertical;
  line-height: 1.55;
}

.modal-body .field input:focus,
.modal-body .field textarea:focus {
  outline: none;
  border-color: var(--brand);
}

/* 勾选框那一行是 label 包着 input, 不能让上面的 width:100% 把它撑开 */
.modal-body .field > label input[type="checkbox"] {
  width: auto;
  margin-right: 6px;
  vertical-align: -1px;
}

/* Spotlight management: stable position labels and one-line actions. */
.sp-table { table-layout: fixed; width: 100%; min-width: 1140px; }
.sp-table th, .sp-table td { padding: 10px 8px; text-align: left; }
.sp-table th { white-space: nowrap; }
.sp-table th:last-child { text-align: right; }
.sp-table td:nth-child(n+3):nth-child(-n+9) { white-space: nowrap; font-variant-numeric: tabular-nums; }
.sp-position { display: inline-flex; min-width: 28px; height: 28px; align-items: center; justify-content: center; border-radius: 7px; background: #f1f5f9; color: #475569; font-weight: 700; }
.sp-mobile-toggle:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.sp-mobile-toggle:disabled { opacity: .5; cursor: wait; }
.sp-mobile-toggle { display: inline-flex; align-items: center; gap: 5px; padding: 4px 0; border: 0; background: transparent; color: #64748b; font: inherit; font-size: 12px; cursor: pointer; white-space: nowrap; }
.sp-mobile-toggle > span { position: relative; width: 28px; height: 16px; border-radius: 12px; background: #cbd5e1; }
.sp-mobile-toggle > span::after { content: ''; position: absolute; top: 2px; left: 2px; width: 12px; height: 12px; border-radius: 50%; background: #fff; }
.sp-mobile-toggle[aria-checked="true"] { color: #15803d; }
.sp-mobile-toggle[aria-checked="true"] > span { background: #16a34a; }
.sp-mobile-toggle[aria-checked="true"] > span::after { left: 14px; }

/* 广告表「到期时间」: 距到期 15 天内橙、7 天内红, 已过期灰 —— 扫一眼就知道哪条该催续约。
   日期与剩余天数按北京时间算, 与展示/点击统计同一个日界。 */
.sp-due { white-space: nowrap; font-variant-numeric: tabular-nums; }
.sp-due__left { margin-left: 6px; font-size: 12px; opacity: .72; }
.sp-due--near { color: var(--warn); font-weight: 600; }
.sp-due--soon { color: var(--danger); font-weight: 600; }
.sp-due--over { color: #94a3b8; }
.sp-stats-start { margin-top: 12px; font-size: 12px; }
.sp-stats-start:empty { display: none; }

/* 往期投放: 已结束的投放期留档 (素材缩略图 + 投放期 + 期内统计), 只读。 */
.spc-table { table-layout: fixed; width: 100%; min-width: 1000px; }
.spc-table th, .spc-table td { padding: 10px 8px; text-align: left; vertical-align: middle; }
.spc-table th { white-space: nowrap; }
.spc-table th:last-child { text-align: right; }
.spc-table td:nth-child(n+4):nth-child(-n+8) { white-space: nowrap; font-variant-numeric: tabular-nums; }
.spc-ad { display: flex; align-items: center; gap: 8px; min-width: 0; }
.spc-ad > a { flex: none; }
.spc-thumb { display: block; width: 72px; height: 24px; object-fit: contain; border: 1px solid #e2e8f0; border-radius: 4px; background: #f8fafc; }
.spc-ad__text { min-width: 0; }
.spc-ad__text b,
.spc-url { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.spc-note { font-size: 12px; }
.spc-period { font-variant-numeric: tabular-nums; }
#sp-daily-tbody tr.spc-outside td { color: #94a3b8; }
.content:has(.sp-table) { grid-template-columns: minmax(0, 1fr); }

/* CleanIP brand uses outlined Sora SVG; no font loading is needed for the logo. */
.sidebar-wordmark { display:block; width:180px; max-width:100%; height:auto; }
.sidebar-brand-text { width:100%; gap:6px; }
.sidebar-sub { color:#91b29a; text-transform:none; padding-left:33px; font-size:10px; }
.login-wordmark { display:block; width:248px; max-width:100%; height:auto; margin:6px 0 0; }
.auth-body { --brand:#2faa50; --brand-dark:#23863e; --brand-soft:rgba(47,170,80,.16); }

/* Account settings */
/* ============================================================
   设置页通用 (账号设置 / 邮件配置 / AI 配置, 2026-09-13 重构)
   卡片 = 标题栏 (图标 + 标题 + 说明 + 右侧状态) / 表单行 (左标签右控件) / 底部操作栏。
   卡片变窄 (容器 < 560px) 时表单行自动改成上下排列。
   ============================================================ */
.stg { display:grid; gap:16px; min-width:0; }
.stg-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:16px; align-items:start; }
.stg-col { display:grid; gap:16px; min-width:0; }
.stg-grid.is-equal { align-items:stretch; }
.stg-grid.is-equal > .stg-card { height:100%; }
.stg-form { display:flex; flex-direction:column; flex:1; }
.ai-usage-body { padding:16px 20px 20px; }
.ai-usage-body #au-status { margin:0; }
.mail-subject { max-width:200px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* 数字卡片行 (邮件配置 / 订阅清单共用) */
.mk-row { display:grid; grid-template-columns:repeat(5,minmax(0,1fr)); gap:16px; margin-bottom:16px; }
.card.mk-card { display:flex; flex-direction:column; gap:4px; min-width:0; padding:16px 20px; }
.mk-label { display:flex; align-items:center; gap:8px; font-size:12px; line-height:1.5; color:var(--text-muted); white-space:nowrap; }
.mk-label i { width:16px; font-size:12px; text-align:center; color:var(--brand-dark); }
.mk-value { overflow:hidden; font-family:var(--viga); font-size:24px; font-weight:400; line-height:1.25; color:var(--text); font-variant-numeric:tabular-nums; white-space:nowrap; text-overflow:ellipsis; }
.mk-value small { margin-left:4px; font-family:inherit; font-size:12px; color:var(--text-muted); }
.mk-value.is-text { font-family:inherit; font-size:20px; font-weight:600; }
.mk-sub { overflow:hidden; font-size:12px; line-height:1.5; color:var(--text-faint); white-space:nowrap; text-overflow:ellipsis; }
.mk-sub.is-bad, .mk-sub .is-bad { color:var(--danger); }
.mk-sub.is-warn { color:var(--warn); }
@media (max-width:1280px) { .mk-row { grid-template-columns:repeat(3,minmax(0,1fr)); } }
@media (max-width:640px) { .mk-row { grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px; } }

/* 邮件配置: 左列 配置+测试, 右列 发信趋势+发信记录 (可展开看正文) */
.mail-trend .stg-aside { gap:8px; }
.mail-trend-body { display:grid; gap:12px; padding:16px 20px; }
.mail-trend-chart { position:relative; height:220px; }
.mail-kinds { display:flex; flex-wrap:wrap; gap:8px; margin:0; padding:12px 0 0; list-style:none; border-top:1px solid var(--border-soft); }
.mail-kinds li { display:inline-flex; align-items:center; gap:8px; padding:4px 12px; border-radius:var(--radius-pill); background:var(--surface-muted); font-size:12px; color:var(--text-muted); }
.mail-kinds b { font-family:var(--viga); font-weight:400; color:var(--text); font-variant-numeric:tabular-nums; }
.mail-kind-dot { width:8px; height:8px; border-radius:50%; background:var(--text-faint); }
.mail-kind-dot.k-report { background:#2faa50; } .mail-kind-dot.k-subscribe { background:#0ea5e9; } .mail-kind-dot.k-feedback { background:#f59e0b; } .mail-kind-dot.k-notice { background:#6a7382; } .mail-kind-dot.k-test { background:#c4c9d1; }
.link-btn { padding:0; border:0; background:none; font:inherit; color:var(--brand-dark); cursor:pointer; text-decoration:underline; text-underline-offset:2px; }
.link-btn:hover { color:var(--brand); }
.mail-log-card > .table-scroll { padding:0 0 8px; }
/* 右栏只放发信记录: 绝对定位不撑高整行, 高度跟左栏对齐, 记录在卡片内滚动 */
.mail-grid { align-items:stretch; }
.mail-log-col { position:relative; }
.mail-log-col > .mail-log-card { position:absolute; inset:0; display:flex; flex-direction:column; }
.mail-log-col > .mail-log-card > .table-scroll { flex:1; min-height:0; overflow:auto; }
.mail-log thead th { position:sticky; top:0; z-index:1; background:var(--surface); }
@media (max-width:1100px) {
  .mail-log-col > .mail-log-card { position:static; }
  .mail-log-col > .mail-log-card > .table-scroll { max-height:640px; }
}
.table.mail-log { table-layout:fixed; width:100%; }
.mail-log col.c-time { width:112px; } .mail-log col.c-to { width:38%; } .mail-log col.c-st { width:88px; }
.mail-log td { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.mail-log .mail-log-detail > td { white-space:normal; }
.mail-log th:first-child, .mail-log td:first-child { padding-left:20px; }
.mail-log th:last-child, .mail-log td:last-child { padding-right:20px; }
.mail-log-row { cursor:pointer; }
.mail-log-row:hover > td { background:var(--surface-muted); }
.mail-log-row:focus-visible { outline:2px solid var(--brand); outline-offset:-2px; }
.mail-log-row[aria-expanded="true"] > td { background:var(--brand-soft); border-bottom-color:transparent; }
.mail-log-detail > td { padding:0 20px 16px !important; background:var(--brand-soft); }
.mail-meta { display:grid; grid-template-columns:auto minmax(0,1fr); gap:4px 16px; margin:0 0 12px; font-size:12px; line-height:1.5; }
.mail-meta dt { color:var(--text-muted); }
.mail-meta dd { margin:0; color:var(--text); overflow-wrap:anywhere; }
.mail-err { color:var(--danger); }
.mail-body { border:1px solid var(--border); border-radius:var(--radius-sm); background:#fff; overflow:hidden; }
.mail-body iframe { display:block; width:100%; height:240px; border:0; background:#fff; }
.mail-text { margin:0; padding:12px 16px; max-height:480px; overflow:auto; font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace; color:#111827; white-space:pre-wrap; overflow-wrap:anywhere; }
.mail-empty { margin:0; padding:12px 16px; font-size:12px; }
.stg-card > .table-scroll { padding:0 20px 8px; }
.card.stg-card { display:flex; flex-direction:column; min-width:0; padding:0; overflow:hidden; container-type:inline-size; }
.stg-head { display:flex; align-items:center; gap:12px; padding:16px 20px; border-bottom:1px solid var(--border-soft); }
.stg-icon { display:grid; place-items:center; flex:none; width:36px; height:36px; border-radius:var(--radius); background:var(--brand-soft); color:var(--brand-dark); font-size:16px; }
.stg-icon img { display:block; width:20px; height:20px; }
.stg-head-text { min-width:0; }
.stg-head h2 { margin:0; font-size:16px; font-weight:600; line-height:1.25; color:var(--text); }
.stg-head p { margin:4px 0 0; font-size:12px; line-height:1.5; color:var(--text-muted); }
.stg-aside { display:flex; align-items:center; gap:8px; margin-left:auto; flex-wrap:wrap; justify-content:flex-end; }
.stg-aside form { margin:0; }
.stg-body { display:grid; padding:0 20px; }
.stg-body + .stg-body > .stg-row:first-child,
.stg-body + form > .stg-body > .stg-row:first-child { border-top:1px solid var(--border-soft); }
.stg-row { display:grid; grid-template-columns:180px minmax(0,1fr); gap:8px 24px; align-items:start; padding:16px 0; border-bottom:1px solid var(--border-soft); }
.stg-row:last-child { border-bottom:0; }
.stg-label { display:grid; gap:4px; padding-top:8px; font-size:14px; font-weight:600; color:var(--text); }
.stg-label small { font-size:12px; font-weight:400; line-height:1.5; color:var(--text-muted); }
.stg-control { display:grid; gap:8px; min-width:0; }
.stg-control > input:not([type=checkbox]):not([type=radio]):not([type=file]),
.stg-control > select { width:100%; height:40px; padding:8px 12px; border:1px solid #d1d5db; border-radius:var(--radius-sm); background:var(--surface); font-size:14px; color:var(--text); }
.stg-control > input:focus,
.stg-control > select:focus { outline:none; border-color:var(--brand); box-shadow:none; }
.stg-control > input[readonly] { background:var(--surface-muted); color:var(--text-muted); }
.stg-hint { margin:0; font-size:12px; line-height:1.5; color:var(--text-muted); overflow-wrap:anywhere; }
.stg-value { padding-top:8px; font-size:14px; color:var(--text); overflow-wrap:anywhere; }
.ai-ch-chips { display:flex; flex-wrap:wrap; gap:6px; }
.stg-value.is-mono { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; }
.stg-value img { width:16px; height:12px; margin-right:8px; vertical-align:-1px; object-fit:cover; box-shadow:0 0 0 1px var(--border); }
.stg-control .switch { min-height:40px; font-size:14px; color:var(--text); }
.stg-text { padding:16px 0; font-size:13px; line-height:1.7; color:var(--text-muted); }
.stg-text p { margin:0 0 8px; } .stg-text p:last-child { margin-bottom:0; }
.stg-foot { display:flex; align-items:center; justify-content:flex-end; gap:8px; margin-top:auto; padding:12px 20px; border-top:1px solid var(--border-soft); background:var(--surface-muted); }
.stg-foot-note { margin-right:auto; font-size:12px; color:var(--text-muted); }
.stg-foot .btn { min-height:36px; padding:0 16px; }
.stg-card .table { font-size:13px; }
/* 危险操作卡: 退出登录 */
.stg-danger .stg-icon { background:var(--danger-bg); color:var(--danger); }
.btn.btn-logout { background:#dc2626; border-color:#dc2626; color:#fff; gap:8px; }
.btn.btn-logout:hover { background:#b91c1c; border-color:#b91c1c; color:#fff; }
/* 分段按钮组 (AI 用量时间范围 / 指标) */
.stg-seg { display:inline-flex; padding:2px; border:1px solid var(--border); border-radius:var(--radius-sm); background:var(--surface-muted); }
.stg-seg .btn { min-height:28px; padding:0 12px; border:0; border-radius:4px; background:transparent; color:var(--text-muted); font-size:12px; box-shadow:none; }
.stg-seg .btn:hover { background:var(--surface); color:var(--text); }
.stg-seg .btn[aria-pressed="true"],.stg-seg .btn.btn-primary { background:var(--surface); color:var(--brand-dark); box-shadow:0 1px 2px rgba(20,28,40,.08); }
/* 账号: 头像 */
/* 账号设置: 头像固定 Gravatar, 只读展示 */
.account-id { display:flex; align-items:center; gap:16px; padding:24px 20px; border-bottom:1px solid var(--border-soft); }
.account-id img { flex:none; width:64px; height:64px; border-radius:50%; background:var(--surface-muted); object-fit:cover; }
.account-id-text { display:grid; gap:4px; min-width:0; }
.account-id-text strong { font-size:20px; font-weight:600; line-height:1.25; color:var(--text); }
.account-id-text span { font-size:14px; color:var(--text-muted); overflow-wrap:anywhere; }
.account-grid { grid-template-columns:minmax(0,1fr) minmax(0,2fr); }
/* Passkey 一行: 设备靠左 / 密钥居中 / 两个时间靠右 / 删除按钮最右; 各格不截断, 余量均分; 放不下就折两行 */
.account-passkeys .pk-row { display:grid; grid-template-columns:minmax(max-content,1fr) auto minmax(max-content,1fr) minmax(max-content,1fr) auto; align-items:center; gap:16px; padding:12px 16px; border:1px solid var(--border-soft); border-radius:var(--radius-sm); background:var(--surface-muted); }
.account-passkeys .pk-cell { display:grid; gap:4px; min-width:0; }
.account-passkeys .pk-cell small { font-size:12px; line-height:1.5; color:var(--text-muted); }
.account-passkeys .pk-cell span { overflow:hidden; font-size:14px; line-height:1.5; color:var(--text); white-space:nowrap; text-overflow:ellipsis; }
.account-passkeys .pk-name span { font-weight:600; }
.account-passkeys .pk-key { text-align:center; }
.account-passkeys .pk-key span { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:12px; line-height:1.75; color:var(--text-muted); }
.account-passkeys .pk-time { text-align:right; }
@container (max-width:660px) {
  .account-passkeys .pk-row { grid-template-columns:max-content minmax(0,1fr) minmax(0,1fr); }
  .account-passkeys .pk-name { grid-column:1 / 3; }
  .account-passkeys .pk-row > :last-child { grid-column:3; grid-row:1; justify-self:end; }
  .account-passkeys .pk-key { text-align:left; }
}
@container (max-width:420px) {
  .account-passkeys .pk-row { grid-template-columns:minmax(0,1fr) minmax(0,1fr); }
  .account-passkeys .pk-name { grid-column:1; }
  .account-passkeys .pk-row > :last-child { grid-column:2; }
  .account-passkeys .pk-key { grid-column:1 / -1; }
  .account-passkeys .pk-time { text-align:left; }
  .account-passkeys .pk-cell span { white-space:normal; }
}
#pk-list { display:grid; gap:8px; padding:16px 0; }
@container (max-width:560px) {
  .stg-row { grid-template-columns:minmax(0,1fr); }
  .stg-label { padding-top:0; }
}
@media (max-width:1100px) { .stg-grid { grid-template-columns:minmax(0,1fr); } }

/* Evaluation and calibration workspaces: scoped to these two admin tabs. */
.review-workspace{display:flex;flex-direction:column;gap:20px;min-width:0}
.review-workspace .card{margin:0;padding:24px;min-width:0;border:1px solid var(--border);border-radius:14px;box-shadow:none;scroll-margin-top:24px}
.review-intro{display:flex;align-items:center;justify-content:space-between;gap:20px;padding:4px 0 8px}
.review-intro h2{font-size:24px;letter-spacing:-.5px;margin:0 0 8px}
.review-intro p{margin:0;color:var(--text-muted);font-size:13px}
.review-intro nav{display:flex;flex-wrap:wrap;gap:6px}
.review-intro nav a{padding:8px 12px;border:1px solid var(--border);border-radius:8px;background:var(--surface);font-size:12px;color:var(--text-muted);text-decoration:none}
.review-intro nav a:hover{border-color:var(--brand);color:var(--brand-dark)}
.review-workspace .section-head{display:flex;flex-wrap:wrap;align-items:flex-start!important;gap:8px 18px;margin-bottom:20px}
.review-workspace .section-head h2{font-size:16px;line-height:1.5;margin:0;color:var(--text)}
.review-workspace .section-head p,.review-workspace .ai-hero-meta{font-size:12px;line-height:1.7;white-space:normal;margin:0;color:var(--text-muted)}
.review-workspace--eval .section-head{flex-direction:column}
.review-workspace .muted-block{font-size:12px;line-height:1.8}
.review-actions{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin:16px 0}
.review-workspace .btn,.review-workspace .calib-btn{min-height:36px;padding:8px 14px;border-radius:8px;font-size:12px;line-height:1.4;box-shadow:none}
.review-workspace .calib-btn-primary:not(:disabled){background:var(--brand);border-color:var(--brand);color:#fff}
.review-workspace .calib-btn-primary:hover:not(:disabled){background:var(--brand-dark);border-color:var(--brand-dark)}
.review-workspace .calib-chip.is-active{background:var(--brand-soft);border-color:var(--brand);color:var(--brand-dark)}
.review-workspace :is(button,a,input,select,summary):focus-visible{outline:2px solid var(--brand);outline-offset:3px}
.review-maintenance{border-top:1px solid var(--border-soft);padding-top:16px;display:flex;justify-content:space-between;align-items:center;gap:16px}
.review-maintenance strong{font-size:13px}.review-maintenance p{font-size:12px;color:var(--text-muted);margin:6px 0 0}.review-maintenance .review-actions{margin:0}
.review-workspace #sw-rows{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}
.weight-tile{display:grid;grid-template-columns:minmax(0,1fr) 70px 12px;align-items:center;gap:10px;background:var(--surface-muted);border:1px solid var(--border-soft);padding:16px;border-radius:10px}
.weight-title{font-size:13px;color:var(--text)}.weight-title .muted{display:inline-block;margin-top:4px}
.review-workspace .weight-input{width:70px;min-width:0;text-align:right;background:var(--surface);font-size:17px;font-variant-numeric:tabular-nums;font-weight:600}
.weight-unit{font-size:12px;color:var(--text-muted)}.weight-hint{grid-column:1/-1;font-size:12px;line-height:1.7;color:var(--text-muted)}
.review-workspace #su-rules{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:10px}
.rule-limit{grid-column:1/-1;display:flex;align-items:center;gap:18px;padding:16px 18px;background:var(--brand-soft);border-radius:10px;color:var(--brand-dark);font-size:13px}
.rule-limit strong{font-size:22px;font-variant-numeric:tabular-nums}.rule-limit small{margin-left:auto;color:var(--text-muted);font-size:12px}
.rule-tile{display:flex;justify-content:space-between;align-items:center;gap:8px;padding:14px;background:var(--surface-muted);border-radius:8px;font-size:12px}.rule-tile strong{white-space:nowrap;color:var(--text)}
.review-workspace #ev-cats{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
.review-workspace .ev-cat{padding:16px;border:1px solid var(--border);border-radius:10px;min-width:0}
.review-workspace .ev-cat-head{flex-wrap:wrap;gap:6px 10px}.review-workspace .ev-cat-head h3{font-size:13px}.review-workspace .ev-cat-fields{overflow-wrap:anywhere}
.review-workspace .ev-chain{gap:8px;margin-top:12px}.review-workspace .ev-chain select{max-width:100%}
.review-workspace .ev-grid{grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr))}.review-workspace .ev-src{border-radius:10px}
.review-workspace .query-search-line{max-width:720px;display:flex;gap:10px}.review-workspace .query-search-line input{flex:1;min-width:0}
.review-notice{display:flex;flex-wrap:wrap;gap:8px 16px;padding:14px 18px;border:1px solid #efdcb1;border-radius:10px;background:var(--warning-bg);color:#8c6220;font-size:12px;line-height:1.6}
.review-workspace .ai-grid{gap:14px;margin:0}.review-workspace .ai-grp{padding:20px;border:1px solid var(--border-soft);border-radius:10px;background:var(--surface-muted)}
.review-workspace .ai-grp-t{font-size:13px;color:var(--text-muted);margin-bottom:16px}.review-workspace .ai-grp-v{flex-wrap:wrap;gap:8px}.review-workspace .ai-grp-v b{font-size:28px}.review-workspace .ai-grp-s{margin-top:16px}
.review-fold{background:var(--surface);border:1px solid var(--border);border-radius:12px;min-width:0}
.review-fold>summary{cursor:pointer;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:18px 24px;font-size:13px;font-weight:600;list-style:none}
.review-fold>summary::-webkit-details-marker{display:none}.review-fold>summary small{display:inline-block;font-size:12px;font-weight:400;color:var(--text-muted);margin-left:14px}
.review-fold-hint{font-size:11px;color:var(--text-muted);font-weight:400}.review-fold[open]>.review-fold-hint{display:none}
.review-fold[open]>summary{border-bottom:1px solid var(--border-soft)}.review-fold>.card{border:0;border-radius:0;background:transparent}
.review-workspace .review-table-scroll{overflow:auto;max-width:100%}.review-workspace .table{font-size:12px;margin-top:12px}.review-workspace .table th{font-size:11px;background:var(--surface-muted);color:var(--text-muted);white-space:nowrap}.review-workspace .table :is(th,td){padding:12px;line-height:1.65}
.review-workspace .calib-selbar[hidden],.review-workspace .calib-filters[hidden]{display:none}
.review-workspace #geo-add[hidden]{display:none!important}.review-workspace #geo-add{flex-wrap:wrap!important}
.review-workspace .geo-toolbar{flex-wrap:wrap;gap:10px}.review-workspace .geo-toolbar .tab-row{flex-wrap:wrap}
.review-workspace .caliball-step{flex-wrap:wrap;line-height:1.7;padding:10px 12px;background:var(--surface-muted);border-radius:8px}
@media(max-width:1200px){.review-intro{align-items:flex-start;flex-direction:column}.review-workspace #sw-rows{grid-template-columns:repeat(2,minmax(0,1fr))}.review-workspace #su-rules{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media(max-width:700px){.review-workspace{gap:14px}.review-workspace .card{padding:18px 14px;border-radius:10px}.review-intro h2{font-size:21px}.review-intro nav{gap:6px}.review-intro nav a{padding:7px 9px}.review-workspace #sw-rows,.review-workspace #ev-cats{grid-template-columns:1fr}.review-workspace #su-rules{grid-template-columns:repeat(2,minmax(0,1fr))}.rule-limit{flex-wrap:wrap;gap:10px}.rule-limit small{flex-basis:100%;margin:0}.review-maintenance{align-items:flex-start;flex-direction:column}.review-workspace .ai-grid{grid-template-columns:1fr}.review-workspace .ai-grp{padding:16px}.review-fold>summary{padding:16px 14px}.review-fold>summary small{display:block;margin:5px 0 0}.review-workspace .section-head{margin-bottom:16px}.review-actions{gap:8px}.review-workspace #calib-prog,.review-workspace #gc-prog,.review-workspace #refill-prog{flex-basis:100%;overflow-wrap:anywhere}.review-workspace .calib-selbar-actions{flex-wrap:wrap}.review-workspace .query-search-line{flex-wrap:wrap}.review-workspace .query-search-line input{flex-basis:100%}}

.review-workspace .weight-tile{grid-template-columns:minmax(0,1fr) 86px 12px}
.review-workspace .weight-input{width:86px;padding:10px 8px}
.review-workspace #calib-table{min-width:800px}.review-workspace #gc-table{min-width:620px}.review-workspace #geo-library .table{min-width:760px}
.review-fold-hint::after{content:'展开'}.review-fold[open]>summary .review-fold-hint::after{content:'收起'}

.notes-detail-toolbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:16px;font-size:12px}
.notes-detail-toolbar label{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
.notes-feedback{padding:10px 14px;border:1px solid #cbe9d2;border-radius:8px;background:#edf8f0;color:#237f3c;font-size:13px}
.notes-feedback.is-error{background:#fdf1f1;border-color:#f2c9c9;color:#b83838}
.notes-feedback[hidden]{display:none}
#notes-detail .table{min-width:740px}
#notes-detail .table th,#notes-detail .table .badge{white-space:nowrap}
#notes-detail .table th:nth-child(2){min-width:220px}
#notes-detail #nd-clear:disabled{opacity:.4;cursor:not-allowed}
#notes-detail{min-width:0;max-width:100%;width:100%;box-sizing:border-box}
#notes-detail .table-scroll{min-width:0;max-width:100%;overflow-x:auto}
#ai-usage-card{min-width:0;max-width:100%}
#ai-usage-card .section-head{flex-wrap:wrap;gap:14px}
#ai-usage-card .section-head p{font-size:12px;margin:7px 0 0}
.ai-usage-controls{display:flex;gap:6px;flex-wrap:wrap}
#ai-usage-card .btn{min-height:34px;font-size:12px;padding:7px 12px}
#au-status,.ai-usage-caption{font-size:11px;color:var(--text-muted);line-height:1.8}
.ai-usage-metrics{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:18px 0 24px}
.ai-usage-metrics article{background:var(--surface-muted);border:1px solid var(--border-soft);border-radius:10px;padding:18px;min-width:0}
.ai-usage-metrics span,.ai-usage-metrics small{display:block;color:var(--text-muted);font-size:12px;line-height:1.6}
.ai-usage-metrics strong{display:block;font-size:28px;color:var(--brand-dark);font-variant-numeric:tabular-nums;line-height:1.3;margin:10px 0;overflow-wrap:anywhere}
.ai-usage-metrics small{font-size:11px}
.ai-usage-chart-head{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:18px}
.ai-usage-chart-head h3{font-size:14px;margin:0}.ai-usage-chart{height:280px;position:relative;min-width:0}
.ai-usage-details{margin-top:16px;padding-top:16px;border-top:1px solid var(--border-soft);font-size:12px;line-height:1.8;color:var(--text-muted)}
.ai-usage-details summary{cursor:pointer;color:var(--text);font-weight:600}.ai-usage-details .table{min-width:740px;font-size:12px}
@media(max-width:900px){.ai-usage-metrics{grid-template-columns:repeat(2,minmax(0,1fr))}.ai-usage-metrics article{padding:14px}.ai-usage-metrics strong{font-size:24px}}
@media(max-width:480px){#ai-usage-card{padding:16px 12px}.ai-usage-metrics{gap:8px}.ai-usage-metrics strong{font-size:21px}.ai-usage-chart{height:240px}}
/* Operational pages adopt the evaluation workspace hierarchy without changing actions. */
.ops-nav{display:flex;flex-wrap:wrap;gap:8px}
.ops-nav a{padding:8px 14px;border:1px solid var(--border);border-radius:8px;color:var(--text-muted);background:var(--surface);font-size:12px;text-decoration:none}
.ops-nav a:hover{color:var(--brand-dark);border-color:var(--brand)}
.ops-workspace .section-head{align-items:center!important}
.ops-workspace .section-head h2 .muted{font-size:12px;font-weight:400}
.ops-workspace .muted-block{margin:0 0 16px}
.ops-workspace .table-scroll{min-width:0;max-width:100%;overflow-x:auto}
.ops-workspace .table th{letter-spacing:0;text-transform:none}
.ops-workspace .table th,.ops-workspace .cg-table th{white-space:nowrap}
.ops-workspace .cg-table th{padding:12px;background:var(--surface-muted);border:0}
.ops-workspace .cg-table td{padding:14px 12px;line-height:1.6;border-color:var(--border-soft)}
.ops-workspace .cg-table td.wrap{min-width:180px;max-width:350px}
.ops-workspace .cg-actions{gap:8px}.ops-workspace .cg-actions input{min-width:0}
.ops-workspace .cg-grid{grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:16px 0}
.ops-workspace .cg-field{background:var(--surface-muted);border:1px solid var(--border-soft);border-radius:10px;padding:16px;gap:12px}
.ops-workspace .cg-field input{background:var(--surface);font-size:20px;padding:10px 12px;min-width:0}
.ops-help{border:1px solid var(--border-soft);border-radius:8px;margin:12px 0 18px;font-size:12px;line-height:1.8;color:var(--text-muted)}
.ops-help summary{cursor:pointer;padding:10px 14px;font-weight:600;color:var(--text-muted)}
.ops-help>p{padding:0 14px}.ops-help[open] summary{margin-bottom:8px}
.ops-workspace .ld-file{background:var(--surface-muted);padding:16px;border-radius:10px;margin-bottom:10px;gap:12px}
.ops-workspace .ld-job{background:var(--surface);padding:18px;margin-top:12px;margin-bottom:0;border:1px solid var(--border);border-radius:10px}
.ops-workspace .ld-job .section-head{margin-bottom:10px}.ops-workspace .ld-job h3{font-size:14px}
.ops-workspace .ld-job .ld-sched{font-size:12px;line-height:1.8;overflow-wrap:anywhere}
.ops-job-settings{margin-top:14px;border-top:1px solid var(--border-soft);padding-top:12px}
.ops-job-settings summary{font-size:12px;color:var(--brand-dark);font-weight:600;cursor:pointer}
.ops-workspace .ld-job .ld-grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}
.ops-workspace .ld-job input,.ops-workspace .ld-job select{min-width:0;max-width:100%}
.ops-local-data #ops-intel .table{min-width:750px}
.ops-spotlight .sp-table{min-width:1180px}
.ops-spotlight #ops-prices .table{min-width:680px}
@media(max-width:1000px){.ops-workspace .cg-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.ops-workspace .ld-file-upd{text-align:left;flex-basis:100%}.ops-workspace .ld-file-name{flex-basis:calc(100% - 40px)}.ops-workspace .ld-file-size,.ops-workspace .ld-file-rows{text-align:left;flex:1 1 120px}}
@media(max-width:600px){.ops-workspace .ld-job .ld-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.ops-workspace .cg-field{padding:12px}.ops-workspace .cg-field label{min-height:34px;line-height:1.5}.ops-workspace .ld-job .ld-foot{flex-wrap:wrap}.ops-workspace .cg-table{min-width:650px}.ops-workspace #ops-top .cg-table{min-width:480px}.ops-nav a{padding:8px 10px}.ops-workspace .ld-job .section-head>div{flex-wrap:wrap}}
/* Remaining configuration screens: independent edit groups and contained tables. */
.settings-workspace .section-head{align-items:center!important}
.settings-workspace .table-scroll{min-width:0;max-width:100%;overflow-x:auto}
.settings-workspace .tab-row{flex-wrap:wrap;gap:8px}
.settings-workspace .source-cards{display:block;margin:0}
.settings-workspace .source-cards>thead{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}
.settings-workspace .source-cards>tbody{display:grid;gap:14px}
.settings-workspace .source-cards .src-config-row{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;padding:18px;border:1px solid var(--border);border-radius:10px;background:var(--surface-muted)}
.settings-workspace .source-cards .src-config-row>td{display:block;padding:0;border:0;min-width:0;white-space:normal}
.settings-workspace .source-cards .src-config-row>td::before{content:attr(data-label);display:block;font-size:11px;color:var(--text-muted);margin-bottom:6px}
.settings-workspace .source-cards .src-config-row>td:first-child{grid-column:1/-1;border-bottom:1px solid var(--border);padding-bottom:12px}
.settings-workspace .source-cards .src-config-row>td:first-child::before{display:none}
.settings-workspace .source-cards .src-config-row>td:last-child{display:flex;gap:12px;align-items:center;justify-content:flex-end;grid-column:1/-1;border-top:1px solid var(--border);padding-top:12px}
.settings-workspace .source-cards .cell-input{width:100%;min-width:0;max-width:100%;background:var(--surface)}
.settings-workspace .source-cards .src-keys-row:not([hidden]){display:block}
.settings-workspace .source-cards .src-keys-row[hidden]{display:none}
.settings-workspace .source-cards .src-keys-row>td{display:block;padding:0;border:0;min-width:0}
.settings-workspace .src-keys{overflow-x:auto;max-width:100%}
.field-group-card{padding:18px;border:1px solid var(--border);border-radius:10px;min-width:0}
.field-group-card h2{margin:0 0 12px;font-size:14px}
.field-group-card select{min-width:150px;max-width:100%}
.field-group-card .table{min-width:580px}
.settings-save{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;padding-top:16px;border-top:1px solid var(--border)}
.settings-save .muted{font-size:12px}
.settings-threat-intel #threat-list-card .table{min-width:760px}
@media(max-width:700px){.settings-workspace .source-cards .src-config-row{grid-template-columns:repeat(2,minmax(0,1fr));padding:14px;gap:12px}.settings-workspace .source-cards .src-config-row>td:nth-child(2),.settings-workspace .source-cards .src-config-row>td:nth-child(3),.settings-workspace .source-cards .src-config-row>td:nth-child(9){grid-column:1/-1}.mail-field-grid{grid-template-columns:1fr}.field-group-card{padding:12px}.settings-save{align-items:flex-start;flex-direction:column}}
/* Prevent wide child tables from expanding the admin content grid. */
.content{grid-template-columns:minmax(0,1fr)}
.content>*{min-width:0}
#al-search-card .search-box,#ips-search-card .search-box{min-width:0}
#al-search-card input,#ips-search-card input{min-width:0;max-width:100%}
.al-filter-row .tab-row{flex-wrap:wrap;max-width:100%}
#um-wrap,#um-wrap>.two-col,#um-wrap .card{min-width:0}
@media(max-width:1100px){#um-wrap>.two-col{grid-template-columns:repeat(2,minmax(0,1fr))!important}#um-cards{grid-template-columns:repeat(3,minmax(0,1fr))!important}}
@media(max-width:600px){#um-wrap>.two-col{grid-template-columns:minmax(0,1fr)!important}#um-cards{grid-template-columns:repeat(2,minmax(0,1fr))!important}#um-range{flex-wrap:wrap}#um-wrap .stat-value{overflow-wrap:anywhere}}
@media(max-width:1100px){.section-head:has(#al-count){flex-wrap:wrap!important}.al-tabs-center{flex-basis:100%!important;order:3;justify-content:flex-start!important}.section-head:has(#al-count)>div:last-child{flex-wrap:wrap}#al-type-tabs{flex-wrap:wrap!important}}
.asn-maintenance-body{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px;padding:18px}
.asn-maintenance-body .card{min-width:0;box-shadow:none;padding:18px;background:var(--surface-muted)}
.asn-maintenance-body h2{font-size:14px}.asn-maintenance-body p{font-size:12px;line-height:1.8}
.maintenance-status{display:flex;gap:8px;flex-wrap:wrap;font-size:11px;color:var(--text-muted);font-weight:400}
.maintenance-status span{padding:5px 8px;background:var(--surface-muted);border-radius:6px}
.friend-workspace .fl-stats-row[hidden]{display:none}
.friend-workspace .fl-stat-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}
.fl-stat-grid>div{border:1px solid var(--border-soft);background:var(--surface-muted);padding:14px;border-radius:8px}
.fl-stat-grid span{display:block;font-size:11px;color:var(--text-muted)}
.fl-stat-grid strong{display:block;font-size:22px;margin-top:8px;font-variant-numeric:tabular-nums;color:var(--brand-dark)}
.friend-workspace .fl-stats-row p{font-size:11px;margin-bottom:0}
.friend-workspace .table-scroll{max-width:100%;min-width:0;overflow:auto}
@media(max-width:800px){.asn-maintenance-body{grid-template-columns:1fr;padding:12px}.asn-maintenance>summary{align-items:flex-start;flex-direction:column;gap:10px}}

/* Shared corner hierarchy: workspace 16, cards 12, inset groups 8, controls 6. */
:root{--radius-workspace:16px;--radius-card:12px;--radius-inset:8px;--radius-control:6px}
.content,.ajax-overlay{border-radius:var(--radius-workspace)}
.card,.review-workspace .card,.review-fold,.account-card,.cache-card,.fb-modal{border-radius:var(--radius-card)}
.fb-modal{border-radius:var(--radius-workspace)}
.review-workspace :is(.weight-tile,.ev-cat,.ev-src,.ai-grp,.ld-job,.ld-file,.cg-field),
.settings-workspace .source-cards .src-config-row,
.field-group-card,.ai-usage-metrics article,.fl-stat-grid>div,.ops-help,.ops-job-settings,
.asn-maintenance-body .card{border-radius:var(--radius-inset)}
.review-workspace .review-fold>.card{border-radius:0}
.btn,.review-workspace .btn,.review-workspace .calib-btn,.ops-nav a,.review-intro nav a,
.sp-position,
.cell-input,.field input:not([type=checkbox]):not([type=radio]),.field select,.field textarea,
.review-workspace .weight-input{border-radius:var(--radius-control)}

/* Native superellipse corners. Existing component selectors are aliases so
   server-rendered and AJAX-created controls share the same utility.
   Only corner properties change; !important beats legacy inline radii. */
:where(.squircle, button, .btn, .btn-add, .btn-search, .icon-btn,
.login-btn, .login-btn-alt, .tab-row, .tab-link, .stg-seg,
.ops-nav a, .review-intro nav a,
.content, .ajax-overlay, .card, .auth-card, .review-fold,
.account-card, .cache-card, .src-card, .su-card, .local-card,
.stat-tile, .fb-modal, .modal-box, .cfm-box, .srvs-box, .rb-box,
.srvp-modal-box, .dash-srv-menu, .dash-srv-opt, .dash-srv-top,
.weight-tile, .ev-cat, .ev-src, .ai-grp, .ld-job, .ld-file,
.cg-field, .field-group-card, .src-config-row,
.ai-usage-metrics article, .fl-stat-grid > div, .ops-help,
.ops-job-settings,
.badge, .dash-count, .dash-pill, .calib-chip, .ev-chip, .mon-pill,
.lm-flag, .cg-badge, .sbw-chip, .gz-tag, .acx-chip, .av-conf,
.community-admin-official-badge, .cst-new, .ptw-dirty,
.srvp-card, .acx-box, .fbx-box, .ptw-box, .nr-dialog,
.nr-fact, .nr-evidence, .rule-tile, .fb-modal-message,
.fb-modal-meta div, .search-box) { --sq-r: 15px; }
.btn, .btn-search, .login-btn, .login-btn-alt { --sq-r: 19px; }
.btn-add { --sq-r: 18px; }
.btn-small, .pager .btn, .icon-btn { --sq-r: 15px; }
.review-workspace .btn, .review-workspace .calib-btn { --sq-r: 17px; }
.ops-nav a, .review-intro nav a { --sq-r: 16px; }
.content, .ajax-overlay, .auth-card { --sq-r: 22px; }
.card, .review-fold, .account-card, .cache-card, .src-card,
.su-card, .local-card, .fb-modal, .modal-box, .cfm-box,
.srvs-box, .rb-box, .srvp-modal-box { --sq-r: 18px; }
.stat-card, .stat-tile, .asn-maintenance-body .card { --sq-r: 15px; }
/* Tabs have 3px padding; settings segments have 2px padding. */
.tab-row { --sq-r: 18px; }
.tab-row > .tab-link, .tab-row > button { --sq-r: calc(18px - 3px); }
.stg-seg { --sq-r: 16px; }
.stg-seg > .btn { --sq-r: calc(16px - 2px); }
/* Floating server menu has 4px padding. Its hover surfaces are concentric. */
.dash-srv-menu { --sq-r: 18px; }
.dash-srv-menu > .dash-srv-opt { --sq-r: calc(18px - 4px); }
.dash-srv-btn { --sq-r: 13px; }
.dash-srv-go, .srvs-chip-x { --sq-r: 10px; }
/* Fold contents deliberately have no independent corners. */
.review-fold > .card { --sq-r: 0px; }

:is(.squircle, button, .btn, .btn-add, .btn-search, .icon-btn,
.login-btn, .login-btn-alt, .tab-row, .tab-link, .stg-seg,
.ops-nav a, .review-intro nav a,
.content, .ajax-overlay, .card, .auth-card, .review-fold,
.account-card, .cache-card, .src-card, .su-card, .local-card,
.stat-tile, .fb-modal, .modal-box, .cfm-box, .srvs-box, .rb-box,
.srvp-modal-box, .dash-srv-menu, .dash-srv-opt, .dash-srv-top,
.weight-tile, .ev-cat, .ev-src, .ai-grp, .ld-job, .ld-file,
.cg-field, .field-group-card, .src-config-row,
.ai-usage-metrics article, .fl-stat-grid > div, .ops-help,
.ops-job-settings,
.badge, .dash-count, .dash-pill, .calib-chip, .ev-chip, .mon-pill,
.lm-flag, .cg-badge, .sbw-chip, .gz-tag, .acx-chip, .av-conf,
.community-admin-official-badge, .cst-new, .ptw-dirty,
.srvp-card, .acx-box, .fbx-box, .ptw-box, .nr-dialog,
.nr-fact, .nr-evidence, .rule-tile, .fb-modal-message,
.fb-modal-meta div, .search-box) {
  border-radius: calc(var(--sq-r) * .54) !important;
}
@supports (corner-shape: squircle) {
  :is(.squircle, button, .btn, .btn-add, .btn-search, .icon-btn,
.login-btn, .login-btn-alt, .tab-row, .tab-link, .stg-seg,
.ops-nav a, .review-intro nav a,
.content, .ajax-overlay, .card, .auth-card, .review-fold,
.account-card, .cache-card, .src-card, .su-card, .local-card,
.stat-tile, .fb-modal, .modal-box, .cfm-box, .srvs-box, .rb-box,
.srvp-modal-box, .dash-srv-menu, .dash-srv-opt, .dash-srv-top,
.weight-tile, .ev-cat, .ev-src, .ai-grp, .ld-job, .ld-file,
.cg-field, .field-group-card, .src-config-row,
.ai-usage-metrics article, .fl-stat-grid > div, .ops-help,
.ops-job-settings,
.badge, .dash-count, .dash-pill, .calib-chip, .ev-chip, .mon-pill,
.lm-flag, .cg-badge, .sbw-chip, .gz-tag, .acx-chip, .av-conf,
.community-admin-official-badge, .cst-new, .ptw-dirty,
.srvp-card, .acx-box, .fbx-box, .ptw-box, .nr-dialog,
.nr-fact, .nr-evidence, .rule-tile, .fb-modal-message,
.fb-modal-meta div, .search-box) {
    border-radius: var(--sq-r) !important;
    corner-shape: squircle;
  }
}

/* Compact labels use the same native corner utility.
   Circular status dots, avatars, and progress tracks intentionally stay round. */
.badge, .acx-chip, .calib-chip, .ev-chip, .mon-pill, .cg-badge,
.sbw-chip, .gz-tag, .av-conf, .community-admin-official-badge { --sq-r: 12px; }
.dash-count, .dash-pill, .lm-flag, .cst-new, .ptw-dirty { --sq-r: 10px; }
.nr-dialog { --sq-r: 18px; }
.search-box { --sq-r: 19px; }

/* Square flags and sidebar selection backgrounds, per the admin design. */
img[src*="/flags/"], .sidebar .nav-link, .sidebar .nav-glider::after {
  border-radius: 0 !important;
  corner-shape: round;
}

/* Single-site statistics: range filter in the page header, five independent KPIs. */
#um-cards { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.um-card-sub { margin: 0; font-size: 12px; color: var(--text-muted); }
.page-header:has(#um-range) { align-items: center; }

/* Compact only the website statistics cards, retaining their horizontal spacing. */
#um-cards > .stat-card {
  padding-block: 16px;
  gap: 4px;
  align-content: start;
}
#um-cards > .stat-card .stat-value {
  margin: 4px 0 0;
  transform: translateY(10px);
}

/* Only visible while a data-backed panel is switching or failed to load. */
.admin-tab-pending { position: relative !important; }
.admin-tab-loading { position:absolute;inset:0;z-index:40;display:flex;align-items:flex-start;justify-content:center;padding:24px 12px;background:rgba(248,250,252,.78);backdrop-filter:blur(1.5px);border-radius:inherit;corner-shape:inherit;pointer-events:none; }
.admin-tab-status { position:sticky;top:12px;display:inline-flex;align-items:center;gap:8px;padding:8px 12px;background:#fff;color:#64748b;border-radius:8px;font-size:13px;box-shadow:0 2px 12px rgba(20,28,40,.08); }
.admin-tab-spinner { width:16px;height:16px;border:2px solid #dcebe0;border-top-color:#2faa50;border-radius:50%;animation:admin-tab-spin .7s linear infinite; }
@keyframes admin-tab-spin { to { transform:rotate(360deg); } }
.admin-layout-bar { display:inline-block;height:14px;max-width:100%;vertical-align:middle;border-radius:4px;background:linear-gradient(90deg,#eef2f7 25%,#e4e9f0 37%,#eef2f7 63%);background-size:400% 100%;animation:admin-layout-shimmer 1.3s ease infinite; }
[data-layout-skeleton] { pointer-events:none; }
.admin-layout-line { padding:8px 0; }
.mk-value[data-layout-metric] { position:relative;color:transparent; }
.mk-value[data-layout-metric]::after { content:"";position:absolute;left:0;top:50%;transform:translateY(-50%);width:70%;height:18px;border-radius:4px;background:linear-gradient(90deg,#eef2f7 25%,#e4e9f0 37%,#eef2f7 63%);background-size:400% 100%;animation:admin-layout-shimmer 1.3s ease infinite; }
.cst-axis:empty::before { content:"\00a0"; }
@keyframes admin-layout-shimmer { from { background-position:100% 0; } to { background-position:0 0; } }
@media(prefers-reduced-motion:reduce) { .admin-tab-spinner { animation:none; } }
@media(prefers-reduced-motion:reduce) { .admin-layout-bar { animation:none; } }

/* Match the overview KPIs to the compact website statistics height. */
.dash-kpis > .stat-card {
  min-height: 126px;
  padding-block: 16px;
  gap: 4px;
  align-content: start;
}
.dash-kpis > .stat-card .stat-value {
  margin: 4px 0 0;
}

/* Page headings and top-level navigation share one compact row. */
.page-header { align-items: center; }
.page-header > .ops-nav, .page-header > .tab-row { margin: 0 0 0 auto; }
.section-head { flex-wrap: wrap; align-items: center; }
/* Suppress descriptive heading copy while retaining live counts and statuses. */
.page-sub, .stg-head-text > p, .review-intro > div > p,
.section-head > p:not([id]):not([role]),
.section-head > div > p:not([id]):not([role]),
.section-head > .srvp-sub,
.section-head + p.muted-block:not([id]):not([role]),
.cst-title > p:not([id]), .srvp-head > .srvp-sub {
  display: none !important;
}
.dash-kpis > .stat-card .stat-value { margin-top: 14px; }

/* Shared immediate black tooltip; native titles are migrated by admin-ui.js. */
.admin-tooltip {
  --sq-r: 10px;
  position: fixed;
  z-index: 100000;
  max-width: min(360px, calc(100vw - 24px));
  padding: 7px 11px;
  background: #000;
  color: #fff;
  font: 12px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", sans-serif;
  white-space: pre-line;
  overflow-wrap: anywhere;
  box-shadow: 0 3px 12px rgba(0,0,0,.2);
  pointer-events: none;
}
.admin-tooltip[hidden] { display: none; }
.mon-day::after { display: none !important; }

/* Descriptions directly following nested card titles use the same rule. */
.content h2 + p:not([id]):not([role]):not(.trial-place),
.content h3 + p:not([id]):not([role]):not(.trial-place),
#cst-trend-note, #sp-daily-sub, #ft-pv-sub {
  display: none !important;
}

/* ============================================================
   赞助位编辑弹窗 (#sp-modal .sp-editor) —— 紧凑排版
   2026-10-17 用户要求: 整张表单一屏放下, 不出现内部滚动条, 不放说明文字。
   - 短字段按行分组 (标签在上); URL 类字段标签在左、一行一个, 方便直接粘贴
   - 控件统一 32px 高; 文本域按内容自动长高 (field-sizing), 不支持的浏览器可手动拖
   ============================================================ */
.sp-editor {
  width: min(880px, 100%);
  max-height: calc(100vh - 48px);
  padding: 18px 22px 16px;
}
.sp-editor .fb-modal-head { align-items: center; }
.sp-editor .fb-modal-head h3 { font-size: 17px; }
.sp-form { display: grid; gap: 10px; margin-top: 12px; }
.sp-form .field { gap: 4px; min-width: 0; }
.sp-form label { font-size: 12px; line-height: 1.3; white-space: nowrap; }
.sp-form input:not([type="checkbox"]):not([type="radio"]):not([type="color"]),
.sp-form select,
.sp-form textarea {
  padding: 6px 10px;
  font-size: 13px;
  line-height: 1.4;
}
.sp-form select { padding-right: 30px; background-position: right 9px center; background-size: 13px; }
.sp-form textarea {
  min-height: 32px;
  max-height: 120px;
  resize: vertical;
  field-sizing: content;
}
.sp-row { display: grid; gap: 10px; align-items: start; }
.sp-row--base { grid-template-columns: 1.4fr 1fr 1.15fr 0.75fr 0.75fr; }
.sp-row--text { grid-template-columns: 1fr 2fr 0.8fr; }
.sp-row--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.sp-row--end { grid-template-columns: 1fr 1fr 2.2fr; }
/* 整图模式只剩 alt 一个文案字段, 让它占满一行而不是缩在左边 1/3 */
.sp-form.is-img .sp-row--text { grid-template-columns: 1fr; }
.sp-urls {
  display: grid;
  gap: 8px;
  padding: 8px 12px;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-inset);
  background: var(--surface-muted);
}
.sp-form .sp-url {
  grid-template-columns: 84px minmax(0, 1fr);
  align-items: center;
  gap: 0 10px;
}
.sp-url-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 14px; }
.sp-form.is-img .sp-url-pair { grid-template-columns: 1fr; }
.sp-inline { display: flex; align-items: center; gap: 8px; min-width: 0; }
.sp-inline > input { min-width: 0; }
.sp-inline > .muted { white-space: nowrap; }
/* Chrome 的日期框内部多 2px, 压回与文本框同高 */
.sp-form input[type="date"] { padding-top: 5px; padding-bottom: 5px; }
.sp-inline-short { flex: 0 1 200px; }
.sp-slug-preview {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  color: var(--text-muted);
  font-size: 12px;
  text-overflow: ellipsis;
  white-space: nowrap;
  user-select: all;
}
.sp-color-pick {
  width: 32px;
  height: 32px;
  flex: 0 0 32px;
  padding: 2px;
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  background: var(--surface);
  cursor: pointer;
}
.sp-warn { color: var(--warn); font-size: 12px; white-space: nowrap; }
.sp-editor .fb-modal-actions { margin-top: 14px; padding-top: 12px; }
@media (max-width: 720px) {
  .sp-row--base, .sp-row--text, .sp-row--2, .sp-row--end, .sp-url-pair { grid-template-columns: 1fr; }
  .sp-form .sp-url { grid-template-columns: 1fr; gap: 4px; }
}
