/* ============================================================
   MaxMind 控制台 · 后台管理样式表（admin.css）
   Full iOS 外壳（tier=ultra，来自会话档位设置）。

   三条不可违反的规则：
     1) 本文件所有选择器都以 .adm / body.adm-mode 开头，绝不外泄到聊天界面；
        也绝不修改 styles.css 里的既有规则（用更高特异性覆盖）。
     2) 玻璃（backdrop-filter）只给「导航栏 / Tab 栏 / 分段控件 / 弹层」——
        内容卡片一律用不透明材质。给卡片加毛玻璃是这套设计最容易犯的错。
     3) 颜色只有一套强调色（沿用本站黑白单色墨水）+ 四个语义色（状态用），
        不引入蓝色主题色，否则后台会和整个控制台割裂。
   ============================================================ */

/* ============ 1. 设计令牌 ============ */
:root {
  /* 材质：暗色底改【深灰】。
     原先写的是「用真黑（OLED）」，用户 2026-09-16 明确否掉了：
     「页面底部的那个色，不要用纯黑，用灰色」。
     两个理由：① 纯黑下内容短时下半屏是一片无边的黑，像没加载完；
     ② OLED 省电这条在这里不成立 —— 页面大部分时间被卡片盖着。
     底(#121214) < 表面(#1c1c1e) < 二级(#2c2c2e) < 三级(#3a3a3c)，
     与主站 styles.css 的 --bg-* 用同一套灰阶，两套界面切换时不会一跳一跳。 */
  --adm-bg: #121214;
  --adm-bg-a: rgba(18, 18, 20, 0.82);
  --adm-surface: #1c1c1e;
  --adm-surface-2: #2c2c2e;
  --adm-surface-3: #3a3a3c;
  --adm-glass: rgba(30, 30, 32, 0.72);
  --adm-glass-strong: rgba(22, 22, 24, 0.86);

  /* 阴影：深浅必须各一套。旧代码在 chat.css 里把 rgba(0,0,0,.6) 写死了，
     浅色主题下就是在白底上糊一圈脏灰 —— 「弹层/输入框没适配浅色」十之八九
     就是这个，不是背景色的问题。
     注意：底色抬灰之后，深色阴影要【更重】才立得起来。
     rgba(0,0,0,.5) 压在 #000 上几乎看不见（黑上叠黑），压在 #121214 上
     才有对比 —— 原来那几个值是按纯黑调的，别因为「看着没变」就以为白改了。
       · --adm-shadow-pop   弹层（菜单/浮层）：贴边一圈内发丝线 + 一层大扩散 + 一层贴身
       · --adm-shadow-raise 浮起表面（输入区这种）：只给一层向下的柔和投影 */
  --adm-shadow-pop:
    0 0 0 0.5px rgba(255, 255, 255, 0.06) inset,
    0 18px 48px -16px rgba(0, 0, 0, 0.72),
    0 3px 10px -3px rgba(0, 0, 0, 0.50);
  --adm-shadow-raise: 0 10px 30px -18px rgba(0, 0, 0, 0.60);

  --adm-label: #ffffff;
  --adm-label-2: rgba(235, 235, 245, 0.60);
  --adm-label-3: rgba(235, 235, 245, 0.30);
  --adm-label-4: rgba(235, 235, 245, 0.18);
  --adm-sep: rgba(84, 84, 88, 0.65);
  --adm-sep-soft: rgba(84, 84, 88, 0.34);
  --adm-fill: rgba(120, 120, 128, 0.36);
  --adm-fill-2: rgba(120, 120, 128, 0.24);
  --adm-fill-3: rgba(120, 120, 128, 0.14);

  /* 强调色：沿用本站单色墨水（浅色=黑，深色=白） */
  --adm-accent: #ffffff;
  --adm-on-accent: #000000;
  --adm-accent-soft: rgba(255, 255, 255, 0.14);

  /* 语义色：fill 用亮值，-text 用可读值（正文对比度必须 ≥4.5:1） */
  --adm-ok: #30d158;      --adm-ok-text: #30d158;
  --adm-warn: #ff9f0a;    --adm-warn-text: #ffd60a;
  --adm-bad: #ff453a;     --adm-bad-text: #ff6961;
  --adm-info: #64d2ff;    --adm-info-text: #64d2ff;

  /* 圆角：同心递增（外层 = 内层 + 内边距） */
  --adm-r-sm: 8px;
  --adm-r-md: 12px;
  --adm-r-lg: 20px;
  --adm-r-xl: 28px;
  --adm-r-full: 999px;

  /* 字号：Apple Dynamic Type（Large），一律 rem，跟随用户字号设置 */
  --adm-t-largetitle: 2.125rem;   /* 34 */
  --adm-t-title1: 1.75rem;        /* 28 */
  --adm-t-title2: 1.375rem;       /* 22 */
  --adm-t-title3: 1.25rem;        /* 20 */
  --adm-t-headline: 1.0625rem;    /* 17 / 600 */
  --adm-t-body: 1.0625rem;        /* 17 */
  --adm-t-callout: 1rem;          /* 16 */
  --adm-t-subhead: 0.9375rem;     /* 15 */
  --adm-t-footnote: 0.8125rem;    /* 13 */
  --adm-t-caption1: 0.75rem;      /* 12 */
  --adm-t-caption2: 0.6875rem;    /* 11 */

  /* 字距：小字收紧、大字放松（统一 letter-spacing 是「不像苹果」的铁证） */
  --adm-ls-lg: 0.0231rem;
  --adm-ls-title1: 0.0225rem;
  --adm-ls-title2: -0.0163rem;
  --adm-ls-title3: -0.0281rem;
  --adm-ls-body: -0.0256rem;
  --adm-ls-sub: -0.015rem;

  /* 动效：不用内置曲线（太弱，读起来不像有意为之） */
  --adm-ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --adm-ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --adm-ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);

  --adm-nav-h: 44px;
  --adm-font: 'Inter', -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI",
    Roboto, "PingFang SC", "Hiragino Sans GB", "Noto Sans SC", "Microsoft YaHei", sans-serif;
  --adm-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
    "Liberation Mono", monospace;
}

[data-theme="light"] {
  --adm-bg: #f2f2f7;
  --adm-bg-a: rgba(242, 242, 247, 0.82);
  --adm-surface: #ffffff;
  --adm-surface-2: #f2f2f7;
  --adm-surface-3: #e5e5ea;
  --adm-glass: rgba(255, 255, 255, 0.74);
  --adm-glass-strong: rgba(255, 255, 255, 0.90);

  /* 浅色弹层：不用「黑罩子」，用「淡而散」——低了近三档的不透明度，
     扩散半径也收一点，否则白底上会浮出一圈明显的灰晕。 */
  --adm-shadow-pop:
    0 0 0 0.5px rgba(0, 0, 0, 0.04) inset,
    0 16px 40px -16px rgba(0, 0, 0, 0.18),
    0 2px 8px -2px rgba(0, 0, 0, 0.08);
  --adm-shadow-raise: 0 10px 30px -18px rgba(0, 0, 0, 0.20);

  --adm-label: #000000;
  --adm-label-2: rgba(60, 60, 67, 0.60);
  --adm-label-3: rgba(60, 60, 67, 0.30);
  --adm-label-4: rgba(60, 60, 67, 0.18);
  --adm-sep: rgba(60, 60, 67, 0.29);
  --adm-sep-soft: rgba(60, 60, 67, 0.14);
  --adm-fill: rgba(120, 120, 128, 0.20);
  --adm-fill-2: rgba(120, 120, 128, 0.14);
  --adm-fill-3: rgba(120, 120, 128, 0.08);

  --adm-accent: #0a0b0d;
  --adm-on-accent: #ffffff;
  --adm-accent-soft: rgba(0, 0, 0, 0.07);

  --adm-ok: #34c759;      --adm-ok-text: #1c7c3f;
  --adm-warn: #ff9500;    --adm-warn-text: #8a5a00;
  --adm-bad: #ff3b30;     --adm-bad-text: #c0271d;
  --adm-info: #0a84ff;    --adm-info-text: #0060a8;
}

/* ============ 2. 全屏接管（进入后台时由 admin.js 加 body.adm-mode） ============ */
body.adm-mode .page-content { padding: 0; }
body.adm-mode .content-inner { max-width: none; }
/* 独立外壳：后台自带导航栏，聊天顶栏与历史侧栏整体让位 */
body.adm-mode .top-bar,
body.adm-mode .sidebar,
/* 对话页新外壳的构件（cx- 前缀）：后台自带导航栏，这些必须一起让位 */
body.adm-mode .cx-rail,
body.adm-mode .cx-nav,
body.adm-mode .cx-tabbar,
body.adm-mode .cx-largetitle,
body.adm-mode #cx-history-sheet { display: none !important; }
/* 光斑降亮度：数据页要干净，但整体调性不断层 */
body.adm-mode .bg-glow { opacity: 0.45; }
/* 弹层打开时锁滚动（滚动容器是 #page-content，不是 body） */
body.adm-sheet-open .page-content { overflow: hidden; }

/* ============ 3. 外壳 ============ */
.adm {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  min-height: 100%;
  background: var(--adm-bg);
  color: var(--adm-label);
  font-family: var(--adm-font);
  font-size: var(--adm-t-body);
  line-height: 1.41;
  letter-spacing: var(--adm-ls-body);
  text-align: left;
  -webkit-text-size-adjust: 100%;
}
.adm *, .adm *::before, .adm *::after { box-sizing: border-box; }
/* hidden 属性必须真的隐藏：下面若干构件用了 display:inline-block，会盖掉 UA 的 [hidden] */
.adm [hidden] { display: none !important; }
.adm-main { min-width: 0; display: flex; flex-direction: column; }
.adm-col {
  width: 100%;
  padding: 0 16px calc(84px + env(safe-area-inset-bottom));
}
.adm-body {
  min-height: 120px;
  /* ── 切页时的入场（第十五轮）──────────────────────────────────────
     用 @starting-style 而不是 JS 加类：freshBody() 每次导航都换一个全新的
     #adm-body 节点，新元素首次渲染时正好触发 @starting-style —— 零 JS、
     零状态、不可能忘记清理。
     为什么是「淡入 + 上移 6px」而不是更花的：
       切页是几十次/天的操作，按动效分级属于"几乎察觉不到"那一档。
       它的唯一目的是**防止内容凭空跳出来**（bridge a jarring change），
       不是为了好看。160ms + 强 ease-out，看得见"变过来了"，但不挡路。
     ⚠️ 只动 opacity / transform，两者都走 GPU，不触发布局与重绘。 */
  opacity: 1;
  transform: translateY(0);
  transition: opacity 160ms var(--adm-ease-out), transform 160ms var(--adm-ease-out);

  @starting-style {
    opacity: 0;
    transform: translateY(6px);
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   3.0 手机基线 —— 把「这看起来是个网页」的痕迹逐条去掉
   （2026-09-17 第十五轮；依据 mobile-native）

   这些毛病在桌面浏览器和 Chrome 的设备模拟里**全都看不出来**，
   只有真机才暴露。所以它们不是"锦上添花"，是不做就一直错的地方。
   ══════════════════════════════════════════════════════════════════════════ */

/* 1) 点一下闪一下灰蓝 —— 全站最响的"我是网页"信号，而且它会盖住我们
      自己设计的按压反馈。设一次，全局生效。 */
body.adm-mode {
  -webkit-tap-highlight-color: transparent;
  -webkit-text-size-adjust: 100%;   /* 横屏时不许自动放大字号 */
}

/* 2) 页面滚到底不要把手势漏给浏览器：安卓会触发下拉刷新、iOS 会整页橡皮筋。
      后台是个 App 外壳，不是文档，这两种行为都不该出现。
      ⚠️ 根节点用 none、内层滚动容器用 contain —— 这是标准搭配。
         内层留 contain 是为了保住它自己的回弹手感（那是"像原生"的部分），
         只切断往外的传递。 */
body.adm-mode .page-content {
  overscroll-behavior-y: none;
}

/* 3) 点击延迟：浏览器会等一等看你是不是要双击缩放。声明不做双击缩放之后，
      click 立刻触发。配合 :active（下面那条）才有"按下即响应"的手感。 */
body.adm-mode button,
body.adm-mode a,
body.adm-mode [role="button"],
body.adm-mode label,
body.adm-mode summary {
  touch-action: manipulation;
}

/* 4) 长按选中按钮文字 / 弹出复制菜单 —— 原生控件不会这样。
      只管"控件"，正文必须保持可选：用户要复制账号、IP、错误信息。 */
body.adm-mode button,
body.adm-mode [role="button"],
body.adm-mode label,
body.adm-mode summary,
body.adm-mode .adm-tab,
body.adm-mode .rk-chip {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* 5) iOS 聚焦到字号 <16px 的输入框时会把整页放大，而且失焦不还原 ——
      用户看到的是一张被裁掉、还飘着的页面。
      参数页有一堆 12~13px 的小数字框，正是重灾区。
      修法是**把输入框字号提到 16px**，不是禁掉缩放（那是无障碍事故）。
      只在触摸设备上提，桌面端保持原来紧凑的排版。 */
@media (pointer: coarse) {
  body.adm-mode input,
  body.adm-mode select,
  body.adm-mode textarea {
    font-size: 16px;
  }
}

/* 6) 刘海 / 灵动岛 / 底部横条：页面已经用 viewport-fit=cover 铺满整屏，
      所以内容必须自己避开这些区域，否则顶部标题会被状态栏压住。
      env() 在浏览器里是 0，只在 PWA / 全面屏下才起作用 —— 写了不会有害。 */
.adm-nav {
  padding-top: env(safe-area-inset-top, 0px);
}
.adm-col {
  padding-left: max(16px, env(safe-area-inset-left, 0px));
  padding-right: max(16px, env(safe-area-inset-right, 0px));
}
/* 吸顶偏移要把顶部安全区一起算进去，否则导航栏会被安全区分开 */
.adm-segwrap { top: calc(var(--adm-nav-h) + env(safe-area-inset-top, 0px)); }
.adm-tabbar {
  bottom: calc(10px + env(safe-area-inset-bottom, 0px));
  padding-left: max(6px, env(safe-area-inset-left, 0px));
  padding-right: max(6px, env(safe-area-inset-right, 0px));
}

/* 7) 按压反馈统一走 :active 而不是 click —— 手指一落下就响应，
      而不是等抬起来。100~160ms、ease-out，和 emil 的按压规范一致。
      （:active 不需要 hover 能力查询：触摸和鼠标都有这个态。） */
.adm-btn,
.adm-iconbtn,
.adm-rail-btn,
.adm-tab,
.rk-chip,
.rk-prof {
  transition-duration: 120ms;
  transition-timing-function: var(--adm-ease-out);
}

/* 减动效：**不是**全部关掉。
   淡入保留（它帮人看懂"内容换过了"），去掉位移 ——
   会让人不适的是位移，不是透明度。这是"更少更温和"，不是"零"。 */
@media (prefers-reduced-motion: reduce) {
  .adm-body {
    transition: opacity 160ms ease;

    @starting-style {
      opacity: 0;
      transform: none;
    }
  }
}

/* --- 3.1 导航栏（玻璃，仅 chrome） --- */
.adm-nav {
  position: sticky;
  top: 0;
  z-index: 20;
  background: transparent;
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
  transition: background-color 200ms var(--adm-ease-out), box-shadow 200ms var(--adm-ease-out);
}
.adm-nav.is-scrolled {
  background: var(--adm-glass);
  /* 用卷边阴影代替 1px 硬分割线：内容从玻璃条下方穿过时是渐隐而不是被切断 */
  box-shadow: 0 0.5px 0 var(--adm-sep-soft) inset, 0 6px 18px -14px rgba(0, 0, 0, 0.5);
}
.adm-nav-inner {
  height: var(--adm-nav-h);
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 0 8px 0 4px;
}
.adm-nav-back {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 44px;                 /* 至少 44pt 命中区，别用 36px 的「好看但点不准」 */
  padding: 0 14px 0 8px;
  border: 0;
  border-radius: var(--adm-r-full);
  background: transparent;
  color: var(--adm-label);
  font: inherit;
  font-size: var(--adm-t-subhead);
  letter-spacing: var(--adm-ls-sub);
  cursor: pointer;
  transition: background-color 160ms var(--adm-ease-out), transform 160ms var(--adm-ease-out);
}
.adm-nav-back:active { transform: scale(0.97); background: var(--adm-fill-3); }
.adm-nav-back svg { flex: 0 0 auto; }
.adm-nav-title {
  flex: 1;
  min-width: 0;
  font-size: var(--adm-t-headline);
  font-weight: 600;
  letter-spacing: var(--adm-ls-body);
  text-align: center;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 180ms var(--adm-ease-out), transform 180ms var(--adm-ease-out);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  pointer-events: none;
}
.adm-nav.is-scrolled .adm-nav-title { opacity: 1; transform: none; }
.adm-nav-actions { display: flex; align-items: center; gap: 2px; flex: 0 0 auto; }

/* --- 3.2 大标题 --- */
.adm-head { padding: 4px 0 14px; }
.adm-h1 {
  margin: 0;
  font-size: var(--adm-t-largetitle);
  font-weight: 700;
  letter-spacing: var(--adm-ls-lg);
  line-height: 1.2;
  color: var(--adm-label);
}
.adm-head-sub {
  margin: 4px 0 0;
  font-size: var(--adm-t-footnote);
  letter-spacing: -0.005rem;
  color: var(--adm-label-2);
}

/* --- 3.3 Tab 栏：手机=底部胶囊，桌面=左侧栏（同一份 DOM） --- */
.adm-tabbar {
  position: fixed;
  left: 12px;
  right: 12px;
  bottom: calc(10px + env(safe-area-inset-bottom));
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 2px;
  height: 60px;
  padding: 0 6px;
  border-radius: var(--adm-r-full);
  background: var(--adm-glass-strong);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
  backdrop-filter: blur(24px) saturate(180%);
  box-shadow: 0 10px 30px -12px rgba(0, 0, 0, 0.6), 0 0 0 0.5px var(--adm-sep-soft) inset;
}
.adm-tabbar-title { display: none; }
.adm-tab {
  flex: 1 1 0;
  min-width: 0;
  height: 46px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  border: 0;
  border-radius: var(--adm-r-full);
  background: transparent;
  color: var(--adm-label-2);
  font: inherit;
  font-size: var(--adm-t-caption2);
  letter-spacing: 0.0044rem;
  cursor: pointer;
  transition: color 160ms var(--adm-ease-out), background-color 160ms var(--adm-ease-out),
    transform 160ms var(--adm-ease-out);
}
.adm-tab:active { transform: scale(0.96); }
.adm-tab-ico { display: block; height: 24px; position: relative; }
.adm-tab-ico svg { display: block; width: 24px; height: 24px; }
/* Tab 上的角标（绝对定位在图标右上，避免撑开 Tab 宽度） */
.adm-tab .adm-tab-badge-dot {
  position: absolute;
  top: -5px;
  right: -9px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: var(--adm-r-full);
  background: var(--adm-bad);
  color: #ffffff;
  font-size: var(--adm-t-caption2);
  font-weight: 700;
  line-height: 16px;
  text-align: center;
  margin: 0;
}
.adm-tab-label { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.adm-tab.is-active {
  color: var(--adm-label);
  background: var(--adm-accent-soft);
  font-weight: 600;
}

/* --- 3.4 分段控件（子页切换；滑动指示块） --- */
.adm-segwrap {
  position: sticky;
  top: var(--adm-nav-h);
  z-index: 15;
  padding: 4px 0 12px;
  background: var(--adm-bg-a);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
}
.adm-seg {
  position: relative;
  display: flex;
  gap: 2px;
  padding: 2px;
  border-radius: var(--adm-r-md);
  background: var(--adm-fill-3);
  /* ⚠️ 这里以前是 overflow-x: auto。后果：在触摸设备上，横向可滚动容器会把
     「按下 + 轻微移动」判定成滚动手势，从而**吞掉 click** —— 表现就是最右边那几个
     （贴着可滚动边缘的）按钮「点不动」，而桌面鼠标完全正常、jsdom 也测不出来。
     现在改成等分自适应 + 文字省略：永远不会超出容器，也就不需要横向滚动。 */
  overflow: hidden;
  scrollbar-width: none;
}
.adm-seg-thumb {
  position: absolute;
  top: 0;
  left: 0;
  /* 宽高与位置**全部**由 JS 设定：offsetLeft/offsetTop 是相对内边距边的，
     top/left 归零后坐标系一致 —— 这样分组模式换行（多行）时纵坐标才跟得对。 */
  border-radius: 10px;              /* 外层 12 − 内边距 2 = 10（同心圆角） */
  background: var(--adm-surface);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.28), 0 0 0 0.5px var(--adm-sep-soft);
  pointer-events: none;
}
/* 过渡只在首次定位之后开启，否则指示块会从最左侧滑进来（看着像 bug） */
.adm-seg.is-ready .adm-seg-thumb {
  transition: transform 220ms var(--adm-ease-out), width 220ms var(--adm-ease-out),
    height 220ms var(--adm-ease-out);
}
[data-theme="light"] .adm-seg-thumb { background: #ffffff; }
.adm-seg-btn {
  position: relative;
  z-index: 1;
  flex: 1 1 0;              /* 等分：4 个也能塞进 320px 宽的手机 */
  min-width: 0;
  height: 40px;             /* 34 → 40，触摸目标更大（外层 44 由 padding 补足） */
  padding: 0 10px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--adm-label);
  font: inherit;
  font-size: var(--adm-t-footnote);
  font-weight: 500;
  letter-spacing: -0.005rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
  transition: color 160ms var(--adm-ease-out), transform 160ms var(--adm-ease-out);
}
.adm-seg-btn:active { transform: scale(0.97); }
/* 视觉 34px，命中区补到 44px */
.adm-seg-btn::after { content: ''; position: absolute; inset: -5px 0; border-radius: inherit; }
.adm-seg-btn .adm-tab-badge-dot {
  display: inline-block;
  min-width: 16px;
  height: 16px;
  margin-left: 5px;
  padding: 0 4px;
  border-radius: var(--adm-r-full);
  background: var(--adm-bad);
  color: #ffffff;
  font-size: var(--adm-t-caption2);
  font-weight: 700;
  line-height: 16px;
  text-align: center;
  vertical-align: 1px;
}

/* --- 3.4b 分组式分段控件（风控中心专用） ---
   7 个子页按「监控 / 判定 / 处置」三个阶段分三簇，每簇一个小标签，
   簇之间一条 1px 分隔线。这样一眼能看出「这些页在流程的哪一段」——
   老版把 7 项平铺成一行，用户原话是「逻辑都是乱掉的，我都看不懂」。

   ⚠️ 这里**没有** overflow-x: auto（虽然看起来像需要）。原因见上面 .adm-seg
   的注释：横向可滚动容器会吞掉触摸设备上的 click，最右边那几个按钮会「点不动」，
   而桌面鼠标和 jsdom 都测不出来。所以宁可换行占两行，也不做横向滚动。

   改动只作用于 .is-grouped，其他目的地的分段控件观感完全不变。 */
.adm-seg.is-grouped {
  flex-wrap: wrap;
  width: fit-content;
  max-width: 100%;
  gap: 4px;
  padding: 4px;
}
.adm-seg-cluster {
  display: flex;
  align-items: center;
  gap: 2px;
  min-width: 0;
}
/* 组间分隔线：用 padding + border，不用 margin，免得换行时线掉到行首 */
.adm-seg-cluster + .adm-seg-cluster {
  margin-left: 2px;
  padding-left: 6px;
  border-left: 1px solid var(--adm-sep);
}
.adm-seg-glabel {
  flex: none;
  padding: 0 7px 0 3px;
  color: var(--adm-label-4);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  white-space: nowrap;
  user-select: none;
}
/* 内容自适应宽度：换行时若还等分，每一行会被拉成不同宽度，看着很乱 */
.adm-seg.is-grouped .adm-seg-btn {
  flex: 0 1 auto;
  padding: 0 12px;
}
@media (prefers-contrast: more) {
  .adm-seg-glabel { color: var(--adm-label); }
}

/* ============ 4. 分组 / 列表 / 行（iOS 主力构件） ============ */
.adm-group { margin-bottom: 26px; }
.adm-group-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 0 2px 8px;
}
.adm-group-title {
  margin: 0;
  font-size: var(--adm-t-footnote);
  font-weight: 600;
  letter-spacing: 0.004rem;
  text-transform: none;
  color: var(--adm-label-2);
}
.adm-group-note {
  margin: 8px 2px 0;
  font-size: var(--adm-t-caption1);
  line-height: 1.45;
  color: var(--adm-label-2);
}
.adm-list {
  border-radius: var(--adm-r-lg);
  background: var(--adm-surface);
  overflow: hidden;
  box-shadow: 0 0 0 0.5px var(--adm-sep-soft);
}
.adm-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 44px;
  padding: 11px 16px;
  border: 0;
  background: transparent;
  color: var(--adm-label);
  font: inherit;
  font-size: var(--adm-t-body);
  letter-spacing: var(--adm-ls-body);
  text-align: left;
}
.adm-row + .adm-row,
.adm-row + .adm-row-tap,
.adm-row-tap + .adm-row,
.adm-row-tap + .adm-row-tap,
.adm-list > * + * { box-shadow: 0 -0.5px 0 var(--adm-sep-soft); } /* iOS 式：行间发丝线 */
.adm-row-tap { cursor: pointer; transition: background-color 140ms var(--adm-ease-out), transform 140ms var(--adm-ease-out); }
.adm-row-tap:active { background: var(--adm-fill-3); transform: scale(0.995); }
.adm-row-label { flex: 0 0 auto; color: var(--adm-label-2); }
.adm-row-value {
  flex: 1 1 auto;
  min-width: 0;
  text-align: right;
  color: var(--adm-label);
  overflow-wrap: anywhere;
}
.adm-row-chevron { flex: 0 0 auto; color: var(--adm-label-3); display: flex; }
.adm-row-chevron svg { width: 14px; height: 14px; }
.adm-row-stack { flex-direction: column; align-items: flex-start; gap: 3px; }
.adm-row-stack .adm-row-label { font-size: var(--adm-t-footnote); }
.adm-row-stack .adm-row-value { text-align: left; font-size: var(--adm-t-subhead); }
.adm-row-danger .adm-row-label,
.adm-row-danger .adm-row-value { color: var(--adm-bad-text); }
.adm-row-title { font-weight: 600; }

/* ============ 5. 卡片 / 瓦片 ============ */
.adm-card {
  border-radius: var(--adm-r-lg);
  background: var(--adm-surface);
  padding: 16px;
  box-shadow: 0 0 0 0.5px var(--adm-sep-soft);
  margin-bottom: 16px;
}
.adm-card:last-child { margin-bottom: 0; }
.adm-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
}
.adm-card-title { margin: 0; font-size: var(--adm-t-headline); font-weight: 600; letter-spacing: var(--adm-ls-body); }
.adm-card-sub { margin: 3px 0 0; font-size: var(--adm-t-footnote); color: var(--adm-label-2); }
.adm-card-body > *:last-child { margin-bottom: 0; }
.adm-card-foot {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 14px;
  padding-top: 14px;
  box-shadow: 0 -0.5px 0 var(--adm-sep-soft);
}
.adm-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 10px;
  margin-bottom: 22px;
}
.adm-tile {
  border-radius: var(--adm-r-md);
  background: var(--adm-surface);
  padding: 13px 14px;
  box-shadow: 0 0 0 0.5px var(--adm-sep-soft);
}
.adm-tile-label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--adm-t-caption1);
  color: var(--adm-label-2);
  margin-bottom: 6px;
}
.adm-tile-label svg { width: 13px; height: 13px; flex: 0 0 auto; }
.adm-tile-value {
  font-size: var(--adm-t-title2);
  font-weight: 700;
  letter-spacing: var(--adm-ls-title2);
  font-variant-numeric: tabular-nums;
  color: var(--adm-label);
}
.adm-tile-sub { margin-top: 3px; font-size: var(--adm-t-caption1); color: var(--adm-label-2); }
.adm-tile.is-ok .adm-tile-value { color: var(--adm-ok-text); }
.adm-tile.is-warn .adm-tile-value { color: var(--adm-warn-text); }
.adm-tile.is-bad .adm-tile-value { color: var(--adm-bad-text); }

/* ============ 6. 按钮 ============ */
.adm-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 44px;
  padding: 0 18px;
  border: 0;
  border-radius: var(--adm-r-full);
  background: var(--adm-fill);
  color: var(--adm-label);
  font: inherit;
  font-size: var(--adm-t-subhead);
  font-weight: 600;
  letter-spacing: var(--adm-ls-sub);
  text-decoration: none;
  cursor: pointer;
  transition: transform 160ms var(--adm-ease-out), background-color 160ms var(--adm-ease-out),
    opacity 160ms var(--adm-ease-out);
}
.adm-btn svg { width: 16px; height: 16px; flex: 0 0 auto; }
.adm-btn:active { transform: scale(0.97); }
.adm-btn[disabled], .adm-btn.is-busy { opacity: 0.5; pointer-events: none; }
.adm-btn.is-busy { cursor: progress; }
.adm-btn-primary { background: var(--adm-accent); color: var(--adm-on-accent); }
.adm-btn-danger { background: var(--adm-bad); color: #ffffff; }
[data-theme="light"] .adm-btn-danger { background: var(--adm-bad); color: #ffffff; }
.adm-btn-plain { background: transparent; color: var(--adm-label); padding: 0 10px; }
.adm-btn-sm {
  position: relative;
  min-height: 34px;
  padding: 0 13px;
  font-size: var(--adm-t-footnote);
}
/* 视觉 34px，命中区补到 44px（不让小按钮变成误触来源） */
.adm-btn-sm::after { content: ''; position: absolute; inset: -5px 0; border-radius: inherit; }
.adm-iconbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: var(--adm-r-full);
  background: transparent;
  color: var(--adm-label);
  cursor: pointer;
  transition: background-color 160ms var(--adm-ease-out), transform 160ms var(--adm-ease-out);
}
.adm-iconbtn svg { width: 20px; height: 20px; }
.adm-iconbtn:active { transform: scale(0.94); background: var(--adm-fill-3); }
.adm-iconbtn.is-danger { color: var(--adm-bad-text); }
.adm-iconbtn.is-busy { pointer-events: none; opacity: 0.6; }
.adm-iconbtn.is-busy svg { animation: admSpin 700ms linear infinite; }
@keyframes admSpin { to { transform: rotate(360deg); } }
.adm-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.adm-actions-end { justify-content: flex-end; }

/* ============ 7. 表单 ============ */
.adm-field { margin-bottom: 16px; }
.adm-field:last-child { margin-bottom: 0; }
.adm-label {
  display: block;
  margin-bottom: 6px;
  font-size: var(--adm-t-footnote);
  font-weight: 600;
  letter-spacing: 0.004rem;
  color: var(--adm-label-2);
}
.adm-input, .adm-select, .adm-textarea {
  width: 100%;
  min-height: 44px;
  padding: 10px 12px;
  border: 0;
  border-radius: var(--adm-r-md);
  background: var(--adm-fill-3);
  color: var(--adm-label);
  font: inherit;
  font-size: max(16px, 1rem);      /* 必须 ≥16px，否则 iOS Safari 聚焦时整页缩放；max() 保证用户缩小字号时仍不触发缩放 */
  letter-spacing: -0.02rem;
  transition: box-shadow 160ms var(--adm-ease-out), background-color 160ms var(--adm-ease-out);
}
.adm-textarea { min-height: 96px; line-height: 1.5; resize: vertical; }
.adm-select { appearance: none; padding-right: 34px;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 18px) 50%, calc(100% - 13px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
.adm-input:focus-visible, .adm-select:focus-visible, .adm-textarea:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--adm-accent-soft), 0 0 0 1px var(--adm-label-4) inset;
  background: var(--adm-fill-2);
}
.adm-input::placeholder, .adm-textarea::placeholder { color: var(--adm-label-3); }
.adm-input-wrap { position: relative; }
.adm-input-wrap .adm-input { padding-right: 52px; }
.adm-input-btn {
  position: absolute;
  top: 0; right: 0;
  width: 44px; height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; background: transparent; color: var(--adm-label-2); cursor: pointer;
}
.adm-input-btn svg { width: 18px; height: 18px; }
.adm-hint { margin: 6px 0 0; font-size: var(--adm-t-caption1); line-height: 1.45; color: var(--adm-label-2); }
.adm-hint.is-error { color: var(--adm-bad-text); }
.adm-form-actions { display: flex; gap: 8px; margin-top: 18px; }
.adm-form-actions .adm-btn { flex: 1; }

/* 开关（iOS toggle 51×31） */
.adm-switch { position: relative; display: inline-flex; flex: 0 0 auto; }
.adm-switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.adm-switch-track {
  width: 51px; height: 31px; border-radius: var(--adm-r-full);
  background: var(--adm-fill); position: relative;
  transition: background-color 200ms var(--adm-ease-out);
}
.adm-switch-track::after {
  content: ''; position: absolute; top: 2px; left: 2px;
  width: 27px; height: 27px; border-radius: 50%;
  background: #ffffff; box-shadow: 0 3px 8px rgba(0, 0, 0, 0.15), 0 1px 1px rgba(0, 0, 0, 0.16);
  transition: transform 200ms var(--adm-ease-out);
}
.adm-switch input:checked + .adm-switch-track { background: var(--adm-ok); }
.adm-switch input:checked + .adm-switch-track::after { transform: translateX(20px); }
.adm-switch input:focus-visible + .adm-switch-track { box-shadow: 0 0 0 3px var(--adm-accent-soft); }
.adm-switch input:disabled + .adm-switch-track { opacity: 0.5; }
.adm-switch input:active + .adm-switch-track::after { transform: scale(0.94); }
.adm-switch input:checked:active + .adm-switch-track::after { transform: translateX(20px) scale(0.94); }

/* 单选行 / 复选行 */
.adm-check-row { display: flex; align-items: flex-start; gap: 12px; width: 100%; min-height: 44px; padding: 12px 16px; }
.adm-check-row input { flex: 0 0 auto; width: 20px; height: 20px; margin: 1px 0 0; accent-color: var(--adm-label); }
.adm-check-row .adm-switch { margin-left: auto; }
.adm-check-text { min-width: 0; }
.adm-check-title { font-size: var(--adm-t-body); letter-spacing: var(--adm-ls-body); }
.adm-check-desc { margin-top: 2px; font-size: var(--adm-t-caption1); color: var(--adm-label-2); }

/* ============ 8. 数据表格（≤768px 自动变卡片列表） ============ */
.adm-table-wrap {
  border-radius: var(--adm-r-lg);
  background: var(--adm-surface);
  box-shadow: 0 0 0 0.5px var(--adm-sep-soft);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.adm-table { width: 100%; border-collapse: collapse; font-size: var(--adm-t-subhead); }
.adm-table th {
  padding: 11px 14px;
  font-size: var(--adm-t-caption1);
  font-weight: 600;
  letter-spacing: 0.004rem;
  color: var(--adm-label-2);
  text-align: left;
  white-space: nowrap;
}
.adm-table td {
  padding: 12px 14px;
  color: var(--adm-label);
  vertical-align: middle;
  box-shadow: 0 -0.5px 0 var(--adm-sep-soft);
}
.adm-table tbody tr:first-child td { box-shadow: none; }
.adm-table td.adm-td-actions { white-space: nowrap; }
.adm-table .adm-mono, .adm-table .adm-num { font-size: var(--adm-t-footnote); }

/* ============ 9. 语义构件 ============ */
.adm-num { font-variant-numeric: tabular-nums; }
.adm-mono {
  font-family: var(--adm-mono);
  font-size: var(--adm-t-footnote);
  overflow-wrap: anywhere;
  word-break: break-word;
}
.adm-muted { color: var(--adm-label-2); }
.adm-small { font-size: var(--adm-t-footnote); }
.adm-tiny { font-size: var(--adm-t-caption1); }
.adm-strong { font-weight: 600; }
.adm-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 20px;
  padding: 0 8px;
  border-radius: var(--adm-r-full);
  background: var(--adm-fill-2);
  color: var(--adm-label-2);
  font-size: var(--adm-t-caption2);
  font-weight: 600;
  letter-spacing: 0.004rem;
  white-space: nowrap;
}
.adm-badge.is-ok { background: color-mix(in srgb, var(--adm-ok) 22%, transparent); color: var(--adm-ok-text); }
.adm-badge.is-warn { background: color-mix(in srgb, var(--adm-warn) 22%, transparent); color: var(--adm-warn-text); }
.adm-badge.is-bad { background: color-mix(in srgb, var(--adm-bad) 22%, transparent); color: var(--adm-bad-text); }
.adm-badge.is-info { background: color-mix(in srgb, var(--adm-info) 22%, transparent); color: var(--adm-info-text); }
.adm-dot {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--adm-label-3);
  flex: 0 0 auto;
}
.adm-dot.is-ok { background: var(--adm-ok); }
.adm-dot.is-warn { background: var(--adm-warn); }
.adm-dot.is-bad { background: var(--adm-bad); }
.adm-bar {
  height: 8px;
  border-radius: var(--adm-r-full);
  background: var(--adm-fill-3);
  overflow: hidden;
}
.adm-bar-fill {
  display: block;
  height: 100%;
  border-radius: var(--adm-r-full);
  background: var(--adm-ok);
  transform-origin: left center;
  transition: width 400ms var(--adm-ease-out), background-color 200ms var(--adm-ease-out);
}
.adm-bar-fill.is-warn { background: var(--adm-warn); }
.adm-bar-fill.is-bad { background: var(--adm-bad); }
.adm-banner {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  margin-bottom: 16px;
  border-radius: var(--adm-r-md);
  background: var(--adm-fill-3);
  font-size: var(--adm-t-footnote);
  line-height: 1.5;
  color: var(--adm-label);
}
.adm-banner svg { width: 16px; height: 16px; flex: 0 0 auto; margin-top: 1px; }
.adm-banner.is-ok { background: color-mix(in srgb, var(--adm-ok) 16%, transparent); }
.adm-banner.is-warn { background: color-mix(in srgb, var(--adm-warn) 16%, transparent); }
.adm-banner.is-bad { background: color-mix(in srgb, var(--adm-bad) 16%, transparent); }
.adm-banner.is-info { background: color-mix(in srgb, var(--adm-info) 16%, transparent); }
.adm-banner-body { min-width: 0; }
.adm-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  height: 32px;
  padding: 0 10px;
  border-radius: var(--adm-r-full);
  background: var(--adm-fill-3);
  font-size: var(--adm-t-caption1);
  color: var(--adm-label-2);
}
.adm-chip.is-on { background: var(--adm-fill-2); color: var(--adm-label); }
.adm-chip-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.adm-chip-x {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; margin-right: -5px;
  border: 0; border-radius: 50%; background: transparent;
  color: var(--adm-label-2); font: inherit; font-size: 0.75rem; cursor: pointer;
}
.adm-chip-x::after { content: ''; position: absolute; inset: -10px; border-radius: 999px; }  /* 命中区 44px */
.adm-chip-x:active { background: var(--adm-bad); color: #ffffff; }
.adm-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.adm-kv { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: var(--adm-t-footnote); color: var(--adm-label-2); }
.adm-kv b { color: var(--adm-label); font-weight: 600; font-variant-numeric: tabular-nums; }

/* ============ 10. 空态 / 骨架 / 错误 / 预格式 ============ */
.adm-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 40px 20px;
  border-radius: var(--adm-r-lg);
  background: var(--adm-surface);
  box-shadow: 0 0 0 0.5px var(--adm-sep-soft);
  text-align: center;
}
.adm-empty svg { width: 28px; height: 28px; color: var(--adm-label-3); }
.adm-empty-title { font-size: var(--adm-t-body); font-weight: 600; }
.adm-empty-desc { font-size: var(--adm-t-footnote); color: var(--adm-label-2); max-width: 34ch; line-height: 1.5; }
.adm-skel {
  height: 14px;
  border-radius: 7px;
  background: var(--adm-fill-3);
  margin-bottom: 10px;
  animation: admSkelPulse 1.1s var(--adm-ease-in-out) infinite;
}
.adm-skel.is-title { height: 18px; width: 40%; }
@keyframes admSkelPulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }
.adm-error-box {
  padding: 14px;
  border-radius: var(--adm-r-md);
  background: var(--adm-fill-3);          /* 老浏览器回落（不支持 color-mix 时不至于没底色） */
  background: color-mix(in srgb, var(--adm-bad) 14%, transparent);
  color: var(--adm-bad-text);
  font-size: var(--adm-t-footnote);
  line-height: 1.5;
}
.adm-empty-action { margin-top: 6px; display: flex; justify-content: center; gap: 8px; }
.adm-pre {
  margin: 0;
  padding: 12px;
  border-radius: var(--adm-r-md);
  background: var(--adm-fill-3);
  color: var(--adm-label);
  font-family: var(--adm-mono);
  font-size: var(--adm-t-caption1);
  line-height: 1.6;
  overflow-x: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* ============ 11. 弹层（底部抽屉 / 居中弹窗） ============ */
.adm-sheet-overlay {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: rgba(0, 0, 0, 0);
  transition: background-color 220ms var(--adm-ease-out);
}
.adm-sheet-overlay.is-open { background: rgba(0, 0, 0, 0.45); }
/* 「后台菜单」面板：两列网格的子页入口（第二十八轮） */
.adm-menu-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.adm-menu-item {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  min-height: 46px; padding: 10px 13px;
  border-radius: var(--adm-r-md, 12px);
  border: 1px solid var(--adm-border, rgba(255,255,255,0.08));
  background: var(--adm-surface-2, transparent);
  color: inherit; font-size: 0.95rem; text-align: left;
}
.adm-menu-item.is-active {
  border-color: var(--adm-accent, #4c8dff);
  color: var(--adm-accent, #4c8dff);
  font-weight: 600;
}

/* 全屏抽屉（第二十八轮）：编辑模型 / 套餐这类长表单不再挤在小抽屉里，
   手机上整页铺开、桌面端居中窄栏，头部毛玻璃 + 吸顶 */
.adm-sheet-full {
  max-width: 720px;
  height: 100dvh;
  max-height: 100dvh;
  border-radius: var(--adm-r-xl) var(--adm-r-xl) 0 0;
}
.adm-sheet-full .adm-sheet-head {
  position: sticky;
  top: 0;
  z-index: 2;
  background: color-mix(in srgb, var(--adm-surface) 72%, transparent);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  backdrop-filter: blur(18px) saturate(1.4);
  border-bottom: 1px solid var(--adm-border, rgba(255,255,255,0.08));
}
@media (min-width: 760px) {
  .adm-sheet-full {
    max-width: 720px;
    height: auto;
    max-height: 94dvh;
    border-radius: var(--adm-r-xl);
    margin-bottom: 3dvh;
  }
}

.adm-sheet {
  width: 100%;
  max-width: 640px;
  max-height: 88dvh;
  display: flex;
  flex-direction: column;
  border-radius: var(--adm-r-xl) var(--adm-r-xl) 0 0;
  background: var(--adm-surface);
  box-shadow: 0 -12px 40px -16px rgba(0, 0, 0, 0.7);
  transform: translateY(100%);
  transition: transform 320ms var(--adm-ease-drawer);
  will-change: transform;
  padding-bottom: env(safe-area-inset-bottom);
}
.adm-sheet.is-open { transform: translateY(0); }
.adm-sheet-grab {
  flex: 0 0 auto;
  width: 36px; height: 5px;
  margin: 8px auto 0;
  border-radius: var(--adm-r-full);
  background: var(--adm-label-4);
}
.adm-sheet-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px 10px;
}
.adm-sheet-titles { flex: 1 1 auto; min-width: 0; }
.adm-sheet-title { margin: 0; font-size: var(--adm-t-headline); font-weight: 600; letter-spacing: var(--adm-ls-body); }
.adm-sheet-sub { margin: 2px 0 0; font-size: var(--adm-t-caption1); color: var(--adm-label-2); }
.adm-sheet-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 4px 16px 16px; -webkit-overflow-scrolling: touch; }
.adm-sheet-actions {
  flex: 0 0 auto;
  display: flex;
  gap: 8px;
  padding: 12px 16px;
  box-shadow: 0 -0.5px 0 var(--adm-sep-soft);
}
.adm-sheet-actions .adm-btn { flex: 1; }

/* 动作面板（取代原生 confirm / 危险操作） */
.adm-actionsheet { padding: 14px 16px calc(14px + env(safe-area-inset-bottom)); }
.adm-actionsheet-title {
  margin: 0 0 4px;
  font-size: var(--adm-t-footnote);
  font-weight: 600;
  text-align: center;
  color: var(--adm-label);
}
.adm-actionsheet-msg {
  margin: 0 0 14px;
  font-size: var(--adm-t-footnote);
  line-height: 1.5;
  text-align: center;
  color: var(--adm-label-2);
  white-space: pre-line;
}
.adm-actionsheet-btns { border-radius: var(--adm-r-md); overflow: hidden; background: var(--adm-surface-2); }
.adm-sheet-btn {
  display: block;
  width: 100%;
  min-height: 50px;
  padding: 12px;
  border: 0;
  background: transparent;
  color: var(--adm-label);
  font: inherit;
  font-size: var(--adm-t-body);
  cursor: pointer;
  transition: background-color 140ms var(--adm-ease-out);
}
.adm-sheet-btn + .adm-sheet-btn { box-shadow: 0 -0.5px 0 var(--adm-sep); }
.adm-sheet-btn:active { background: var(--adm-fill-3); }
.adm-sheet-btn.is-primary { color: var(--adm-label); font-weight: 700; }
.adm-sheet-btn.is-danger { color: var(--adm-bad-text); font-weight: 600; }
.adm-sheet-btn.is-cancel { margin-top: 8px; border-radius: var(--adm-r-md); background: var(--adm-surface); font-weight: 600; }

/* ============ 12. 后台内的 toast 皮肤（复用 core.js 的 showToast） ============ */
body.adm-mode .toast-container {
  top: auto;
  bottom: calc(84px + env(safe-area-inset-bottom));
  left: 50%;
  right: auto;
  transform: translateX(-50%);
  align-items: center;
  width: max-content;
  max-width: min(92vw, 420px);
}
body.adm-mode .toast {
  border-radius: var(--adm-r-full);
  border: 0;
  background: var(--adm-glass-strong);
  color: var(--adm-label);
  font-size: var(--adm-t-footnote);
  letter-spacing: -0.005rem;
  box-shadow: 0 8px 24px -10px rgba(0, 0, 0, 0.6), 0 0 0 0.5px var(--adm-sep-soft);
  animation: admToastIn 200ms var(--adm-ease-out);
  text-align: center;
}
body.adm-mode .toast.success { border-left: 0; box-shadow: 0 8px 24px -10px rgba(0, 0, 0, 0.6), 0 0 0 1.5px var(--adm-ok) inset; }
body.adm-mode .toast.error { border-left: 0; box-shadow: 0 8px 24px -10px rgba(0, 0, 0, 0.6), 0 0 0 1.5px var(--adm-bad) inset; }
body.adm-mode .toast.info { border-left: 0; box-shadow: 0 8px 24px -10px rgba(0, 0, 0, 0.6), 0 0 0 0.5px var(--adm-sep) inset; }
@keyframes admToastIn { from { opacity: 0; transform: translateY(8px) scale(0.97); } to { opacity: 1; transform: none; } }

/* ============ 13. 悬停（只在真指针设备上） ============ */
@media (hover: hover) and (pointer: fine) {
  .adm-btn:hover { background: var(--adm-fill-2); }
  .adm-btn-primary:hover { background: var(--adm-accent); filter: brightness(1.12); }
  .adm-btn-danger:hover { background: var(--adm-bad); filter: brightness(1.08); }
  .adm-btn-plain:hover { background: var(--adm-fill-3); }
  .adm-btn-sm:hover { background: var(--adm-fill-2); }
  .adm-iconbtn:hover { background: var(--adm-fill-3); }
  .adm-row-tap:hover { background: var(--adm-fill-3); }
  .adm-tab:hover { color: var(--adm-label); }
  .adm-table tbody tr:hover td { background: var(--adm-fill-3); }
  .adm-sheet-btn:hover { background: var(--adm-fill-3); }
}

/* ============ 14. 无障碍：三档系统偏好必须响应 ============ */
@media (prefers-reduced-motion: reduce) {
  .adm *, .adm *::before, .adm *::after,
  body.adm-mode .toast, body.adm-mode .toast-container {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
  /* 保留帮助理解的透明度/颜色变化；位移靠 1ms 过渡变成「瞬时」而不是「删除」——
     这里若写成 transform: none，会连隐藏态（translateY(100%)）一起干掉，抽屉会闪一下。
     同时把骨架屏的呼吸动画停掉（闪烁对前庭敏感人群不友好）。 */
  .adm-skel { animation: none; }
}
@media (prefers-reduced-transparency: reduce) {
  .adm-nav, .adm-nav.is-scrolled, .adm-tabbar, .adm-segwrap, body.adm-mode .toast {
    background: var(--adm-surface);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  .adm-segwrap { background: var(--adm-bg); }
  body.adm-mode .bg-glow { opacity: 0; }
}
@media (prefers-contrast: more) {
  :root { --adm-sep: currentColor; --adm-sep-soft: currentColor; --adm-label-2: var(--adm-label); }
  .adm-list, .adm-card, .adm-table-wrap, .adm-empty, .adm-tile { box-shadow: 0 0 0 1px currentColor; }
  .adm-badge, .adm-chip { box-shadow: 0 0 0 1px currentColor; }
}

/* ============ 15. 响应式 ============ */
/* 手机：表格 → 卡片列表 */
@media (max-width: 768px) {
  .adm-table-wrap { background: transparent; box-shadow: none; border-radius: 0; overflow: visible; }
  .adm-table, .adm-table tbody, .adm-table tr, .adm-table td { display: block; width: 100%; }
  .adm-table thead { display: none; }
  .adm-table tr {
    margin-bottom: 10px;
    padding: 12px 14px;
    border-radius: var(--adm-r-lg);
    background: var(--adm-surface);
    box-shadow: 0 0 0 0.5px var(--adm-sep-soft);
  }
  .adm-table td {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 5px 0;
    text-align: right;
    box-shadow: none;
  }
  .adm-table td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    max-width: 45%;
    text-align: left;
    font-size: var(--adm-t-footnote);
    color: var(--adm-label-2);
  }
  .adm-table td:not([data-label])::before, .adm-table td[data-label=""]::before { content: none; }
  .adm-table td:first-child {
    display: block;
    padding: 0 0 8px;
    margin-bottom: 6px;
    text-align: left;
    font-size: var(--adm-t-headline);
    font-weight: 600;
    box-shadow: 0 0.5px 0 var(--adm-sep-soft);
  }
  .adm-table td:first-child::before { content: none; }
  .adm-table td.adm-td-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 8px;
    padding-top: 12px;
    margin-top: 6px;
    box-shadow: 0 -0.5px 0 var(--adm-sep-soft);
  }
  .adm-table td.adm-td-actions::before { content: none; }
  .adm-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .adm-tile-value { font-size: var(--adm-t-title3); }
  .adm-group { margin-bottom: 22px; }
}
@media (max-width: 420px) {
  .adm-col { padding-left: 12px; padding-right: 12px; }
  .adm-card { padding: 14px; }
  .adm-h1 { font-size: var(--adm-t-title1); }
  .adm-tile { padding: 11px 12px; }
  .adm-tile-value { font-size: var(--adm-t-title3); }
  .adm-tab { font-size: 0.625rem; }
  .adm-tab-ico, .adm-tab-ico svg { height: 22px; width: 22px; }
}

/* 桌面 / 平板：Tab 栏变左侧栏（iPadOS 分栏），弹层居中 */
@media (min-width: 769px) {
  .adm { grid-template-columns: 236px minmax(0, 1fr); align-items: start; }
  .adm-tabbar {
    position: sticky;
    top: 0;
    left: auto;
    right: auto;
    bottom: auto;
    z-index: 25;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    height: 100dvh;
    padding: 14px 10px;
    border-radius: 0;
    background: var(--adm-bg);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    box-shadow: none;
    border-right: 0.5px solid var(--adm-sep-soft);
  }
  .adm-tabbar-title {
    display: block;
    padding: 4px 12px 12px;
    font-size: var(--adm-t-caption1);
    font-weight: 600;
    letter-spacing: 0.004rem;
    color: var(--adm-label-2);
  }
  .adm-tab {
    flex: 0 0 auto;
    flex-direction: row;
    justify-content: flex-start;
    gap: 10px;
    height: 44px;
    padding: 0 12px;
    border-radius: var(--adm-r-md);
    font-size: var(--adm-t-subhead);
    letter-spacing: var(--adm-ls-sub);
  }
  .adm-tab-ico, .adm-tab-ico svg { height: 20px; width: 20px; }
  .adm-tab.is-active { background: var(--adm-fill-2); }
  .adm-tab-label { font-weight: inherit; }
  .adm-col { max-width: 1120px; margin: 0 auto; padding: 0 32px 64px; }
  .adm-nav-inner { max-width: 1184px; margin: 0 auto; padding: 0 32px; }
  .adm-nav-back { padding-left: 4px; }
  .adm-sheet-overlay { align-items: center; padding: 24px; }
  .adm-sheet {
    max-width: 520px;
    max-height: 84dvh;
    border-radius: var(--adm-r-lg);
    padding-bottom: 0;
    transform: scale(0.96);
    opacity: 0;
    transition: transform 220ms var(--adm-ease-out), opacity 200ms var(--adm-ease-out);
    box-shadow: 0 24px 60px -20px rgba(0, 0, 0, 0.7), 0 0 0 0.5px var(--adm-sep-soft);
  }
  .adm-sheet.is-open { transform: none; opacity: 1; }
  .adm-sheet-grab { display: none; }
  .adm-sheet-head { padding-top: 16px; }
  .adm-actionsheet { padding: 18px 18px 18px; }
  .adm-seg { max-width: 420px; }
  body.adm-mode .toast-container { bottom: 24px; left: auto; right: 24px; transform: none; align-items: flex-end; }
}


/* ══════════════════════════════════════════════════════════════
   后台 · 「限速 / 下游限速」分区
   ══════════════════════════════════════════════════════════════ */
.rl-chart {
  color: var(--adm-accent);
  background: var(--adm-fill);
  border-radius: var(--adm-r-md);
  padding: 10px 6px 6px;
  margin: 4px 0 12px;
}
.rl-svg {
  display: block;
  width: 100%;
  height: 132px;
}
.rl-modes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(158px, 1fr));
  gap: 8px;
  margin: 2px 0 10px;
}
.rl-mode {
  appearance: none;
  text-align: left;
  padding: 10px 12px;
  border-radius: var(--adm-r-md);
  border: 1px solid var(--adm-sep);
  background: var(--adm-surface-2);
  color: var(--adm-label);
  font-family: var(--adm-font);
  font-size: var(--adm-t-footnote);
  line-height: 1.35;
  cursor: pointer;
  transition: border-color .18s var(--adm-ease-out),
              background-color .18s var(--adm-ease-out),
              transform .18s var(--adm-ease-out);
}
.rl-mode:hover {
  border-color: var(--adm-accent);
  transform: translateY(-1px);
}
.rl-mode.is-active {
  border-color: var(--adm-accent);
  background: var(--adm-accent-soft);
  color: var(--adm-accent);
}
.rl-mode-t {
  display: block;
  font-size: var(--adm-t-caption1);
  letter-spacing: var(--adm-ls-body);
}
@media (prefers-reduced-motion: reduce) {
  .rl-mode { transition: none; }
  .rl-mode:hover { transform: none; }
}

/* ============================================================================
   ★ 说明句里的 <b>：不加粗、跟正文同色（2026-09-16 用户要求，别再改回去）
   ----------------------------------------------------------------------------
   用户原话：「我是说这种解释词，[开启后本账号的 API 调用不再受下行限速约束…]，
             像这种词，这里面就有加粗的文字，它不需要加粗，然后把它变成灰色就行了。
             并不是网站里的所有东西的加粗都给我取消」。

   所以这里**只针对「说明/解释性文字」这一个语境**：
     · 里面的 <b> / <strong> 既不加粗，也不再用高亮色，直接继承所在段落的颜色
       （这些段落本来就是灰的：.u-meta 用 --u-muted、.adm-hint 用 --adm-label-2…）；
     · 标题、卡片标题、按钮、数据值（.adm-kv 的右列）、徽标……**一律照旧**，不受影响。

   ⚠️ 曾经误做过一次「全站压平所有 font-weight」（css/no-bold.css），
      那是理解错了 —— 标题也跟着塌掉，整个界面失去层次。已删除，别再复活。
      判据很简单：**这个 <b> 是在一句话里当语气强调用的，还是在展示一个值？**
      是前者 → 归到下面这份名单里；是后者 → 不要动。
   ============================================================================ */
.u-meta b, .u-meta strong,
.u-sub b, .u-sub strong,
.u-count b, .u-count strong,
.speed-note b, .speed-note strong,
.up-done-desc b, .up-done-desc strong,
.up-req-warn b, .up-req-warn strong,
.pr-modal-sub b, .pr-modal-sub strong,
.adm-hint b, .adm-hint strong,
.adm-group-note b, .adm-group-note strong,
.adm-card-sub b, .adm-card-sub strong,
.adm-empty b, .adm-empty strong,
.adm-banner-body b, .adm-banner-body strong,
.adm-field-hint b, .adm-field-hint strong,
.cx-quota-meta b, .cx-quota-meta strong {
  font-weight: 400;
  color: inherit;
}

/* ── 卡片头部的 flex 子项必须能收缩（2026-09-16 修）─────────────────────────
   .adm-card-head 是 `display:flex; justify-content:space-between`，
   左边是「标题 + 副标题」的 div、右边是徽标组。
   flex 子项默认 `min-width:auto` = **不小于内容宽度** —— 于是标题一长
   （用户名、模型名都可能是长串），左边这个 div 就不肯收缩，
   把右边的徽标整个顶出卡片外面。用户在「高速申请」页看到的就是这个。
   加 min-width:0 让它可以收缩，再配 overflow-wrap 让它换行而不是溢出。 */
.adm-card-head > * { min-width: 0; }
.adm-card-title,
.adm-card-sub { overflow-wrap: anywhere; }

/* 卡片正文里段落之间的统一间距。
   全局 `* { margin: 0 }` 已经把 <p> 的默认外边距清掉了，所以正文里每个段落
   都得自己声明间距 —— 以前是在 JS 里到处写内联 style="margin:0 0 8px"，
   既不统一也不好改。现在由这一条统一给（第一个子元素除外，
   它上面的间距由 .adm-card-head 的 margin-bottom 负责）。 */
.adm-card-body > * + * { margin-top: 8px; }

/* ══════════════════════════════════════════════════════════════════════════
   风控中心（2026-09-17 第九轮）
   ──────────────────────────────────────────────────────────────────────────
   动效纪律：这个页面一天会被看几十次，所以**只留两处**动效，且都近乎察觉不到：
     1) 分数条/分布条在**首次渲染**时从左长出来（240ms ease-out）—— 状态指示；
     2) 高危等级一个呼吸点 —— 状态指示，且 prefers-reduced-motion 下直接静止。
   数字不跳、列表不飘、没有视差。这两处之外加动效都属于「看着热闹、用着烦」。
   ══════════════════════════════════════════════════════════════════════════ */

.rk-meter {
  display: inline-block; vertical-align: middle;
  width: 92px; height: 6px; border-radius: 3px;
  background: var(--adm-fill-2); overflow: hidden;
}
.rk-meter-fill {
  display: block; height: 100%; border-radius: 3px; background: var(--adm-info);
  transform-origin: left center;
  animation: rkGrow 240ms var(--adm-ease-out) both;
}
.rk-meter-fill.is-warn { background: var(--adm-warn); }
.rk-meter-fill.is-bad { background: var(--adm-bad); }
@keyframes rkGrow { from { transform: scaleX(0); } to { transform: scaleX(1); } }

.rk-score { margin-left: 8px; font-size: 0.85rem; }

/* 高危的呼吸点：只做透明度，不做位移 —— 余光里有动静，读数字时不被打断 */
.rk-pulse {
  display: inline-block; width: 6px; height: 6px; margin-left: 5px;
  border-radius: 50%; background: currentColor; vertical-align: middle;
  animation: rkPulse 1.8s ease-in-out infinite;
}
@keyframes rkPulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }

.rk-dist-row { display: flex; align-items: center; gap: 10px; }
.rk-dist-row + .rk-dist-row { margin-top: 10px; }
.rk-dist-label { flex: 0 0 84px; font-size: 0.85rem; color: var(--adm-label); }
.rk-dist-num { flex: 0 0 40px; text-align: right; }

/* 计划时间线 */
.rk-plan { display: grid; gap: 12px; }
.rk-plan-item {
  border-left: 2px solid var(--adm-sep);
  padding: 2px 0 2px 14px;
}
.rk-plan-item.is-active { border-left-color: var(--adm-warn); }
.rk-plan-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.rk-plan-phase { font-size: 0.75rem; color: var(--adm-label-2); letter-spacing: 0.04em; }
.rk-plan-title { font-size: 0.95rem; font-weight: 600; }
.rk-plan-list { margin: 6px 0 0; padding-left: 18px; }
.rk-plan-list li {
  font-size: 0.85rem; line-height: 1.7; color: var(--adm-label-2);
  overflow-wrap: anywhere;
}

.rk-ev-detail {
  margin-top: 4px; font-size: 0.8rem; line-height: 1.6;
  color: var(--adm-label-2); overflow-wrap: anywhere;
  font-weight: 400;
}
.rk-warn-text { color: var(--adm-warn-text); }
.rk-bd-bar {
  margin-top: 6px; height: 5px; border-radius: 3px;
  background: var(--adm-fill-2); overflow: hidden;
}
.rk-bd-bar > span {
  display: block; height: 100%; background: var(--adm-warn);
  transform-origin: left center; animation: rkGrow 240ms var(--adm-ease-out) both;
}

.rk-filter { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.rk-chip {
  border: 1px solid var(--adm-sep); background: transparent; color: var(--adm-label);
  border-radius: var(--adm-r-full); padding: 6px 14px; font-size: 0.82rem;
  cursor: pointer; transition: background-color 160ms var(--adm-ease-out),
    color 160ms var(--adm-ease-out), transform 160ms var(--adm-ease-out);
}
.rk-chip.is-on { background: var(--adm-fill); color: var(--adm-label); }
.rk-chip:active { transform: scale(0.96); }

.rk-save-row { margin: 20px 0 8px; }

/* 减动效：保留「值变了」这件事的可读性，去掉位移与脉冲 */
@media (prefers-reduced-motion: reduce) {
  .rk-meter-fill, .rk-bd-bar > span { animation: none; }
  .rk-pulse { animation: none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   IP 信誉（2026-09-17 第十轮）
   ──────────────────────────────────────────────────────────────────────────
   新增的只有「统计卡片」一种排版：一排数字，一眼看清「有没有人打我」。
   动效：**零新增** —— 分数条与呼吸点复用上面的 .rk-meter / .rk-pulse，
   卡片本身不动（数字变了就变了，不需要过渡：用户要的是读数，不是看动画）。
   ══════════════════════════════════════════════════════════════════════════ */

.rk-stats {
  display: grid; gap: 10px; margin-bottom: 18px;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
}
.rk-stat {
  border: 1px solid var(--adm-sep); border-radius: var(--adm-r-md);
  padding: 12px 14px; background: var(--adm-surface);
}
.rk-stat-v {
  font-size: 1.5rem; line-height: 1.2; font-variant-numeric: tabular-nums;
  color: var(--adm-label);
}
.rk-stat-l { margin-top: 4px; font-size: 0.8rem; color: var(--adm-label-2); }
.rk-stat-h { margin-top: 2px; font-size: 0.72rem; color: var(--adm-label-3); }
/* 色彩只上在数字上：卡片边框保持中性，一排看过去不吵 */
.rk-stat.is-bad .rk-stat-v { color: var(--adm-bad); }
.rk-stat.is-warn .rk-stat-v { color: var(--adm-warn-text); }

/* 「被拒次数」是这一页最该被看到的数字：给它一点颜色，但仍然不加动效 */
.rk-hot { color: var(--adm-warn-text); }

@media (max-width: 640px) {
  .rk-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ══════════════════════════════════════════════════════════════════════════
   风控 · 系统身份卡 + 引擎卡 + 折叠面板（2026-09-17 第十四轮）
   ──────────────────────────────────────────────────────────────────────────
   用户原话：「这是一个卡片，长方形的，然后带圆角的，然后里面是一些图片，
   然后里面就写上字，比如说长河风控系统，就是你自己命名这样子的，就有大厂
   的感觉」。

   所以这里是「星垣」的身份卡：圆角长方形、左侧徽记（内联 SVG）、中间名字
   与模块芯片、右侧四个实时数字。

   动效纪律：后台一天看几十次 → 这一整块**零动效**。徽记不转、数字不跳、
   卡片不浮起来。唯一保留的是按钮的 :active 缩放（已有全局约定）。
   唯一会动的元素是折叠面板的箭头，且只改 transform，200ms。
   ══════════════════════════════════════════════════════════════════════════ */

.rk-hero {
  position: relative;
  display: flex;
  align-items: center;
  gap: 18px;
  margin-bottom: 26px;
  padding: 20px 22px;
  border-radius: var(--adm-r-lg);
  border: 1px solid var(--adm-sep);
  background:
    linear-gradient(135deg, rgba(56, 189, 248, 0.10), rgba(37, 99, 235, 0.02) 46%, transparent 70%),
    var(--adm-surface);
  overflow: hidden;
}
/* 右上角一层极淡的光晕，让卡片不像一块死平的色块。
   它**不动**（不是 animated glow）—— 常看的页面不该有东西在呼吸。 */
.rk-hero-glow {
  position: absolute;
  top: -70px; right: -50px;
  width: 230px; height: 230px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(56, 189, 248, 0.20), transparent 68%);
  pointer-events: none;
}
.rk-hero-emblem {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 68px; height: 68px;
  border-radius: var(--adm-r-md);
  background: var(--adm-fill-2);
  box-shadow: inset 0 0 0 1px var(--adm-sep-soft);
}
.rk-emblem-svg { display: block; }
.rk-hero-main { flex: 1 1 auto; min-width: 0; }
.rk-hero-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.rk-hero-name {
  font-size: 1.55rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--adm-label);
}
.rk-hero-codename {
  font-family: var(--adm-mono);
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  color: var(--adm-label-3);
}
.rk-hero-ver {
  padding: 1px 6px;
  border-radius: var(--adm-r-sm);
  background: var(--adm-fill-2);
  font-size: 0.7rem;
  font-variant-numeric: tabular-nums;
  color: var(--adm-label-3);
}
.rk-hero-state {
  margin-left: 2px;
  padding: 2px 9px;
  border-radius: var(--adm-r-full);
  font-size: 0.72rem;
  font-weight: 600;
}
.rk-hero-state.is-ok { background: rgba(48, 209, 88, 0.16); color: var(--adm-ok-text); }
.rk-hero-state.is-warn { background: rgba(255, 159, 10, 0.16); color: var(--adm-warn-text); }
.rk-hero-state.is-bad { background: rgba(255, 69, 58, 0.16); color: var(--adm-bad-text); }

.rk-hero-tagline {
  margin: 5px 0 0;
  font-size: var(--adm-t-subhead);
  letter-spacing: -0.01em;
  color: var(--adm-label-2);
}
.rk-hero-desc {
  margin: 3px 0 0;
  font-size: var(--adm-t-caption1);
  color: var(--adm-label-3);
}
.rk-hero-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.rk-chip-mod {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 9px 2px 7px;
  border-radius: var(--adm-r-full);
  background: var(--adm-fill-2);
  font-size: 0.72rem;
  color: var(--adm-label-3);
}
/* 亮起的模块：给一点冷色，和「熄灭的」灰块拉开距离 */
.rk-chip-mod.is-on { background: rgba(56, 189, 248, 0.14); color: var(--adm-info-text); }

.rk-hero-stats {
  flex: none;
  display: grid;
  grid-template-columns: repeat(2, minmax(84px, auto));
  gap: 10px 22px;
  padding-left: 22px;
  border-left: 1px solid var(--adm-sep);
}
.rk-hero-stat { display: flex; flex-direction: column; gap: 1px; }
.rk-hero-stat-k { font-size: 0.72rem; color: var(--adm-label-3); }
.rk-hero-stat-v {
  font-size: 1.2rem;
  line-height: 1.25;
  font-variant-numeric: tabular-nums;
  color: var(--adm-label);
}
.rk-hero-stat-v i {
  margin-left: 3px;
  font-size: 0.72rem;
  font-style: normal;
  color: var(--adm-label-3);
}

/* 正文里的强调：用户要求**不要加粗**，改用灰色弱化对比。
   （不是全局取消加粗 —— 只作用于 .rk-em 这些地方。） */
.rk-em { color: var(--adm-label-2); }

/* --- 两台引擎卡 --- */
.rk-engine {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 16px 16px 12px;
  border: 1px solid var(--adm-sep);
  border-radius: var(--adm-r-md);
  background: var(--adm-surface);
}
.rk-engine.is-off { opacity: 0.62; }
.rk-engine-head { display: flex; align-items: center; gap: 8px; }
.rk-engine-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px; height: 26px;
  border-radius: var(--adm-r-sm);
  background: var(--adm-fill-2);
  color: var(--adm-label-2);
}
.rk-engine-name { flex: 1 1 auto; font-size: 0.98rem; font-weight: 600; }
.rk-engine-role {
  margin: 8px 0 10px;
  font-size: var(--adm-t-caption1);
  line-height: 1.5;
  color: var(--adm-label-3);
}
.rk-engine .adm-list { flex: 1 1 auto; }
.rk-engine .adm-row-label { font-size: var(--adm-t-caption1); }
.rk-engine .adm-row-value { font-size: var(--adm-t-caption1); }
.rk-engine-foot {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--adm-sep);
}

/* --- 折叠面板（原生 details，零 JS） --- */
.rk-fold {
  margin-bottom: 26px;
  border: 1px solid var(--adm-sep);
  border-radius: var(--adm-r-md);
  background: var(--adm-surface);
  overflow: hidden;
}
.rk-fold-sum {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 13px 16px;
  font-size: var(--adm-t-subhead);
  font-weight: 600;
  color: var(--adm-label);
  cursor: pointer;
  list-style: none;
  -webkit-tap-highlight-color: transparent;
}
.rk-fold-sum::-webkit-details-marker { display: none; }
.rk-fold-sum:active { transform: scale(0.995); }
.rk-fold-chev {
  flex: none;
  width: 9px; height: 9px;
  border-right: 1.7px solid var(--adm-label-3);
  border-bottom: 1.7px solid var(--adm-label-3);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform 200ms var(--adm-ease-out);
}
.rk-fold[open] .rk-fold-chev { transform: rotate(-135deg) translate(-2px, -2px); }
.rk-fold-body { padding: 2px 16px 16px; }
.rk-fold-body > .adm-group { margin-bottom: 0; }

/* --- 名单中心的添加表单 --- */
.rk-add {
  display: grid;
  gap: 12px;
  grid-template-columns: 140px minmax(0, 1fr) auto;
  align-items: end;
}
.rk-add-btn { margin-bottom: 2px; }
.rk-chip-mini {
  display: inline-block;
  padding: 0 5px;
  border-radius: var(--adm-r-sm);
  background: var(--adm-fill-2);
  font-size: 0.68rem;
  color: var(--adm-label-3);
  vertical-align: 1px;
}
.rk-filter-tail { align-self: center; margin-left: auto; }

@media (max-width: 720px) {
  .rk-hero { flex-direction: column; align-items: flex-start; gap: 14px; padding: 18px; }
  .rk-hero-stats {
    width: 100%;
    padding-left: 0;
    padding-top: 14px;
    border-left: 0;
    border-top: 1px solid var(--adm-sep);
  }
  .rk-add { grid-template-columns: minmax(0, 1fr); }
  .rk-add-btn { margin-bottom: 0; }
}

/* 减动效：折叠箭头的旋转保留（它是状态指示，不是装饰位移），其余本就没有动效 */
@media (prefers-reduced-motion: reduce) {
  .rk-fold-chev { transition-duration: 0ms; }
}

/* ══════════════════════════════════════════════════════════════════════════
   3.4c 左侧竖导航（风控中心专用，2026-09-17 第十五轮）

   为什么把第十四轮的「横排 + 组标签」换成竖排：
     第十四轮给风控 7 个子页分了「监控 / 判定 / 处置」三组，但仍是**一行横排**。
     第十五轮子页涨到 14 个，横排要折三行，每组那个小标签反而变成噪声 ——
     读者还是得从左到右把 14 项全扫一遍才能找到目标页。
     竖排之后「工作区」是真的分组标题，眼睛可以直接跳到那一段：
     分类变细了，扫视成本反而降低。这是这一轮真正的改动动机。

   触发方式：目的地的 segments 上只要有 group 就自动走竖导航
   （见 admin.js renderSeg），其它模块往数据里加个 group 就能切过来。

   ⚠️ 手机端**不做**横向滚动，也**不做**抽屉：只做一块 aria-expanded
      控制的可折叠面板。老教训很明确 —— 横向可滚动容器会把「按下 + 轻微
      移动」判成滚动手势，从而吞掉 click，触摸屏上最右边那几个按钮直接
      点不动，而桌面端和 jsdom 全都测不出来。
   ══════════════════════════════════════════════════════════════════════════ */

/* 有竖导航时，主体改成两栏（标题跨两栏）；其它目的地完全不受影响 */
@media (min-width: 901px) {
  .adm-col.is-railed {
    display: grid;
    grid-template-columns: 196px minmax(0, 1fr);
    grid-template-areas:
      "head head"
      "rail body";
    column-gap: 22px;
    row-gap: 0;
    align-items: start;
    padding-right: 24px;
  }
  .adm-col.is-railed > .adm-head { grid-area: head; }
  .adm-col.is-railed > .adm-segwrap { grid-area: rail; }
  .adm-col.is-railed > .adm-body { grid-area: body; min-width: 0; }
  /* 竖导航自带底色，不需要横排那层的吸顶毛玻璃 */
  .adm-col.is-railed > .adm-segwrap {
    position: sticky;
    top: calc(var(--adm-nav-h) + 12px);
    padding: 0;
    background: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    z-index: 10;
    /* ⚠️ 这里**绝不能**加 overflow-y: auto + max-height（第十五轮踩过的坑）。
       加了就等于在页面滚动容器（#page-content）里再套一个独立的滚动容器：
       手指落在左侧导航上往下滑时，滚的是导航自己，右侧内容区纹丝不动；
       必须等导航滚到底了，页面才开始滚。实测就是「滑动判定有问题」。
       而且 overscroll-behavior: contain 会把滚动链彻底切断，连到底都传不下去。
       侧栏本来就是随页面一起滚的（原生 App 全都这样），所以这里让它自然流动。 */
    max-height: none;
    overflow: visible;
  }
  /* 侧栏比视口还高时，sticky 元素底部会被切掉（sticky 不会自动滚到底），
     所以不设 max-height：让它随页面自然滚完。
     同时明确交出纵向手势：touch-action 默认就允许纵向平移，
     这里写出来是为了防止以后有人给侧栏加 pan-x / none 又把这个 bug 引回来。 */
  .adm-col.is-railed > .adm-segwrap > .adm-rail {
    touch-action: pan-y;
  }
}

/* 桌面端窗口不够高时，侧栏不再吸顶。
   ────────────────────────────────────────────────────────────────
   吸顶元素一旦**比视口还高**，它就会永久钉在顶部，超出视口的那截再怎么滚
   也露不出来 —— 风控侧栏有 14 项 + 5 个组标题，实测约 580px；加上吸顶偏移
   （导航栏 + 12px）合计要 650px 上下。窗口高度不够时，「策略」那组
   （自动化台 / 账号规则 / IP 规则 / 自动化日志）就会被永久吞掉。
   这跟窄屏那边是同一条规律，只是触发条件是高度而不是宽度。
   窗口够高（≥720px）才吸顶 —— 那时它整根都看得见，吸顶才有意义。 */
@media (min-width: 901px) and (max-height: 719px) {
  .adm-col.is-railed > .adm-segwrap {
    position: static;
    top: auto;
  }
}

.adm-rail {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px;
  border-radius: var(--adm-r-lg);
  background: var(--adm-surface-2, var(--adm-fill-3));
  box-shadow: inset 0 0 0 0.5px var(--adm-sep-soft);
}
.adm-rail-group { display: flex; flex-direction: column; gap: 1px; }
.adm-rail-group + .adm-rail-group {
  margin-top: 8px;
  padding-top: 9px;
  border-top: 1px solid var(--adm-sep-soft);
}
.adm-rail-glabel {
  padding: 2px 8px 5px;
  color: var(--adm-label-4);
  font-size: var(--adm-t-caption2);
  font-weight: 600;
  letter-spacing: 0.1em;
  user-select: none;
}
.adm-rail-btn {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 34px;
  padding: 6px 9px;
  border: 0;
  border-radius: var(--adm-r-sm);
  background: transparent;
  color: var(--adm-label-2, var(--adm-label));
  font: inherit;
  font-size: var(--adm-t-footnote);
  font-weight: 500;
  letter-spacing: -0.004rem;
  text-align: left;
  cursor: pointer;
  transition: background-color 160ms var(--adm-ease-out),
              color 160ms var(--adm-ease-out),
              transform 120ms var(--adm-ease-out);
}
.adm-rail-btn:active { transform: scale(0.98); }
/* 左侧那道竖线是「当前页」的标记：颜色变化只 160ms，不扫视、不位移 */
.adm-rail-dot {
  flex: none;
  width: 3px;
  height: 14px;
  border-radius: var(--adm-r-full);
  background: transparent;
  transform: scaleY(0.35);
  opacity: 0;
  transition: transform 180ms var(--adm-ease-out), opacity 180ms var(--adm-ease-out),
              background-color 160ms var(--adm-ease-out);
}
.adm-rail-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.adm-rail-btn.is-active {
  background: var(--adm-accent-soft);
  color: var(--adm-label);
  font-weight: 600;
}
.adm-rail-btn.is-active .adm-rail-dot {
  background: var(--adm-accent);
  transform: scaleY(1);
  opacity: 1;
}
.adm-rail-btn .adm-tab-badge-dot {
  flex: none;
  min-width: 16px;
  height: 16px;
  margin-left: auto;
  padding: 0 4px;
  border-radius: var(--adm-r-full);
  background: var(--adm-bad);
  color: #ffffff;
  font-size: var(--adm-t-caption2);
  font-weight: 700;
  line-height: 16px;
  text-align: center;
}
@media (hover: hover) and (pointer: fine) {
  .adm-rail-btn:hover:not(.is-active) {
    background: var(--adm-fill-2, var(--adm-fill-3));
    color: var(--adm-label);
  }
}

/* 折叠开关与箭头已经整块删掉（第十五轮第四稿）。
   栏目改成平铺网格之后不再有"展开/收起"这回事，留着这两个选择器只会让人
   以为还能折叠。JS 那边 renderRail 也不再输出那个开关节点了。
   ⚠️ 下面这段注释刻意不写那个类名 —— deploy_ui_fix.py 用「类名是否还存在」
      当自检条件，注释里带一次就会让自检误判成"没删干净"。 */

/* 常驻下拉条与下拉层**只属于窄屏**；宽屏用左侧竖导航。
   放顶层而不是藏在媒体查询里：宽屏必须保证它们彻底不出现。 */
.adm-rail-toggle,
.adm-rail-sheet { display: none; }

/* 下拉面板展开时锁住底下的页面。
   ⚠️ 这一条是整套方案的前提，不是可选项：不锁的话页面和面板**都能滚**，
   手指落在哪儿就滚哪个 —— 这正是前面几稿反复翻车的根因。
   锁死之后全场只剩面板一个滚动容器，滑动判定不再有歧义。 */
body.adm-rail-open .page-content { overflow: hidden; }

/* 手机 / 窄屏：栏目收成一条「下拉条」，点开是从顶部滑下来的面板。
   ────────────────────────────────────────────────────────────────
   这一块的动画是刻意做成**非对称**的，两个方向用的曲线和时长都不同：
     进场  460ms · cubic-bezier(0.32, 0.72, 0, 1)  ← iOS 抽屉曲线
     退场  220ms · cubic-bezier(0.23, 1, 0.32, 1)  ← 干脆利落
   为什么非对称：进场是"界面在铺开给你看"，慢一点带惯性才显得有分量；
   退场是"你已经决定走了"，任何延迟都是挡路。这是动效里最划算的一条规则。
   里面 14 个格子再按 90ms + n×18ms 错峰落下（见 --ri），
   让整块面板像"抖开"而不是"啪一下出现"。总共约 324ms，在面板滑完前收尾。 */
@media (max-width: 900px) {
  .adm-rail {
    position: relative;
    z-index: 12;
    display: flex;
    flex-direction: row;   /* 覆盖桌面端的 column：窄屏这里只剩那颗药丸 */
    flex-wrap: wrap;
    gap: 0;
    padding: 0;
    border-radius: var(--adm-r-md);
    background: transparent;
    box-shadow: none;
  }

  /* 带下拉条的栏目（风控），窄屏**不吸顶**。
     ────────────────────────────────────────────────────────────────
     `.adm-segwrap` 基础样式是 position: sticky，用来把横向分段控件钉在顶部。
     但那对"下拉条"是错的：它会把这条永久固定在那儿，一直是可见的一行，
     用户的原话就是「不要固定放在那，占用的空间太多」。
     药丸本来就该跟着页面一起滚 —— 它只是个"我现在在哪"的指示器，
     不是常驻工具条。顺手把它那层毛玻璃也去掉：不吸顶就不需要。
     ⚠️ 只对 `.is-railed` 生效，别的模块的横向分段控件照旧吸顶。 */
  .adm-col.is-railed > .adm-segwrap {
    position: static;
    top: auto;
    background: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  /* ── 常驻的下拉条：一颗小药丸 ─────────────────────────────────
     刻意**不做满宽**。满宽 50px 的横条会长期占掉一整条版面高度，
     而它九成时间只是个「我现在在哪」的指示器 —— 用户的原话是
     「不要固定放在那，占用的空间太多」。
     改成贴着内容宽度的小药丸：`border-radius: 999px` 是真正的椭圆端头
     （不是圆角矩形），高度压到 34px，纵向占用只有原来的一半不到。 */
  .adm-rail-toggle {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    width: auto;
    max-width: 100%;
    min-height: 34px;
    padding: 0 5px 0 11px;
    border: 0;
    border-radius: 999px;
    background: var(--adm-surface-2, var(--adm-fill-3));
    color: var(--adm-label);
    font: inherit;
    font-size: var(--adm-t-footnote);
    font-weight: 600;
    text-align: left;
    cursor: pointer;
    box-shadow: inset 0 0 0 0.5px var(--adm-sep-soft);
    touch-action: manipulation;
    -webkit-user-select: none;
    user-select: none;
    transition: background-color 160ms var(--adm-ease-out),
                transform 120ms var(--adm-ease-out);
  }
  /* 按压反馈必须在手指落下的瞬间给，不能等抬起 —— 那是"卡"的主要来源 */
  .adm-rail-toggle:active { transform: scale(0.96); }
  .adm-rail-toggle-txt {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .adm-rail-toggle-dest { color: var(--adm-label-3); font-weight: 500; }
  .adm-rail-toggle-sep { margin: 0 6px; color: var(--adm-label-4); }
  .adm-rail-toggle-cur { color: var(--adm-label); }
  .adm-rail-caret {
    flex: none;
    width: 7px;
    height: 7px;
    /* 药丸是贴着内容宽的，这里不需要 margin-left:auto 去顶开 */
    margin-left: 1px;
    margin-right: 4px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(45deg) translate(-2px, -2px);   /* 朝下 = 可以往下拉 */
    transition: transform 240ms var(--adm-ease-out);
  }
  .adm-rail.is-open .adm-rail-caret { transform: rotate(225deg) translate(-2px, -2px); }

  /* ── 下拉层 ─────────────────────────────────────────────────── */
  .adm-rail-sheet {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 80;
    visibility: hidden;
    /* 收起时等动画放完再真正隐藏。visibility 是离散属性，直接切换会让面板
       "啪"地消失；用 0s 的延迟过渡来精确控制隐藏时机。 */
    transition: visibility 0s linear 260ms;
  }
  .adm-rail.is-open .adm-rail-sheet {
    visibility: visible;
    transition: visibility 0s linear 0s;
  }

  .adm-rail-scrim {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    opacity: 0;
    transition: opacity 200ms var(--adm-ease-out);   /* 退场：跟着一起快 */
  }
  .adm-rail.is-open .adm-rail-scrim {
    opacity: 1;
    transition: opacity 380ms var(--adm-ease-out);   /* 进场：比面板慢，收尾更柔 */
  }

  /* 面板：从顶部滑下来的那块板。
     两个方向刻意**不对称** —— 进场慢、带惯性（界面在铺开给你看），
     退场快、干脆（你已经决定走了，任何延迟都是挡路）。 */
  .adm-rail-panel {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    display: flex;
    flex-direction: column;
    max-height: 82vh;
    max-height: 82dvh;              /* dvh：地址栏收起/展开时高度才跟得对 */
    padding-top: env(safe-area-inset-top, 0px);
    /* 椭圆圆角：底部两个角给得很大，顶部贴边所以是 0 —— 这样它读起来像
       「从屏幕顶端拉出来的一张卡片」，而不是一条被切平的横幅。 */
    border-radius: 0 0 30px 30px;
    background: var(--adm-bg);
    /* 顶部一道亮边 = 光打在这块材料的上沿（Apple 的 material 手感）。
       再配一条向下的深阴影，把底下的页面推远。 */
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06),
                0 24px 60px -24px rgba(0, 0, 0, 0.9);
    transform: translateY(-100%);
    opacity: 0;
    transition: transform 200ms var(--adm-ease-out),      /* 退场 */
                opacity 160ms var(--adm-ease-out);
    will-change: transform;
  }
  .adm-rail.is-open .adm-rail-panel {
    transform: translateY(0);
    opacity: 1;
    /* 进场：440ms + iOS 抽屉曲线。opacity 比位移短，画面先"淡进来"、
       位置再慢慢落定 —— 这就是用户说的「渐显」。 */
    transition: transform 440ms var(--adm-ease-drawer),
                opacity 260ms var(--adm-ease-out);
  }
  /* will-change 常驻（见上面 .adm-rail-panel 里的说明）。
     这一条原本是"只在展开时挂上、收起就撤"，现在改成常驻：
     面板只有窄屏才存在（宽屏 display:none），全场就这一个元素，
     单独占一层合成的代价可以忽略；换来的是**收起的动画也保证不掉帧** ——
     原来撤销 will-change 后立刻播收起动画，第一帧是没提层的。 */

  .adm-rail-phead {
    flex: none;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 14px 10px;
  }
  .adm-rail-ptitle {
    flex: 1 1 auto;
    color: var(--adm-label);
    font-size: var(--adm-t-title3);
    font-weight: 700;
    letter-spacing: var(--adm-ls-title3);
  }
  .adm-rail-close {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border: 0;
    border-radius: var(--adm-r-full);
    background: var(--adm-fill-3);
    color: var(--adm-label-2, var(--adm-label));
    cursor: pointer;
    touch-action: manipulation;
    transition: transform 120ms var(--adm-ease-out),
                background-color 160ms var(--adm-ease-out);
  }
  .adm-rail-close:active { transform: scale(0.92); }

  /* 唯一允许滚动的那一层 */
  .adm-rail-in {
    flex: 1 1 auto;
    min-height: 0;                  /* flex 子项默认 min-height:auto，不归零滚不动 */
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;   /* 滚到底不要把手势漏给后面的页面 */
    padding: 4px 14px calc(24px + env(safe-area-inset-bottom, 0px));
    /* 底边渐隐：内容滚到底之前，最后一行是"化开"的，不是被硬切一刀。
       它同时在告诉用户"下面还有东西"。渐隐落在 padding 里，
       所以最后一项的正文永远不会被吃掉。
       ⚠️ 用 mask 而不是盖一层渐变 —— 盖层会挡住点击。 */
    -webkit-mask-image: linear-gradient(to bottom,
      #000 0, #000 calc(100% - 30px), transparent 100%);
    mask-image: linear-gradient(to bottom,
      #000 0, #000 calc(100% - 30px), transparent 100%);
  }

  /* ── 面板里的栏目：按工作区分组平铺 ───────────────────────────── */
  .adm-rail-group {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));
    gap: 8px;
  }
  .adm-rail-group + .adm-rail-group {
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--adm-sep-soft);
  }
  .adm-rail-glabel {
    grid-column: 1 / -1;            /* 组标题独占一行，不参与格子排布 */
    padding: 0 2px 2px;
    font-size: var(--adm-t-caption2);
    opacity: 0;
    transition: opacity 240ms var(--adm-ease-out);
  }
  .adm-rail.is-open .adm-rail-glabel { opacity: 1; transition-delay: 60ms; }

  .adm-rail-dot { display: none; }  /* 格子里那条竖线没意义，用底色表示选中 */
  .adm-rail-btn {
    justify-content: center;
    min-height: 46px;
    padding: 8px 10px;
    /* 椭圆圆角：比 --adm-r-sm 明显更圆，跟上面那颗药丸下拉条是一套语言 */
    border-radius: 14px;
    background: var(--adm-surface-2, var(--adm-fill-3));
    color: var(--adm-label-2, var(--adm-label));
    font-size: var(--adm-t-footnote);
    line-height: 1.3;
    text-align: center;
    box-shadow: inset 0 0 0 0.5px var(--adm-sep-soft);
    touch-action: manipulation;
    -webkit-user-select: none;
    user-select: none;
    /* 入场起点：向上错开 8px + 全透明 —— 这就是「渐显」。
       只动 opacity / transform，两个都在合成层，不触发布局也不重绘。 */
    opacity: 0;
    transform: translateY(-8px);
    transition: opacity 220ms var(--adm-ease-out),
                transform 220ms var(--adm-ease-out),
                background-color 160ms var(--adm-ease-out),
                color 160ms var(--adm-ease-out),
                box-shadow 160ms var(--adm-ease-out);
  }
  /* 按下即反馈（不是等手指抬起）*/
  .adm-rail-btn:active { transform: scale(0.96); }
  .adm-rail.is-open .adm-rail-btn {
    opacity: 1;
    transform: translateY(0);
    /* 错峰：第 n 格比前一格晚 16ms，基准 80ms（先让面板滑下来一点再铺开格子，
       否则看起来是"面板和格子同时出现"，没有层次）。
       四个延迟要和上面四个可过渡属性的顺序**一一对应**，末尾的 box-shadow 显式
       给 0 —— 否则按下时底色会跟着延迟，点下去半天不变色，手感发木。 */
    transition-delay: calc(80ms + var(--ri, 0) * 16ms),
                      calc(80ms + var(--ri, 0) * 16ms),
                      0ms, 0ms, 0ms;
  }
  .adm-rail-label { overflow-wrap: anywhere; }
  .adm-rail-btn.is-active {
    background: var(--adm-accent-soft);
    color: var(--adm-label);
    box-shadow: inset 0 0 0 1.5px var(--adm-accent);
  }
  .adm-rail-btn.is-active .adm-rail-label { font-weight: 600; }
  /* 点过的格子给一次"按住"的确认感 —— 面板马上要关了，这是最后一眼 */
  .adm-rail-btn.is-active:active { transform: scale(0.96); }

  /* ⚠️ 这一步最容易漏，漏了整个下拉层就是"假"的：
     .adm-segwrap 基础样式带 backdrop-filter，而 backdrop-filter 会给
     position: fixed 的**后代**另建一个包含块 —— 面板的 inset: 0 就变成
     "铺满 .adm-segwrap 那个小盒子"而不是铺满视口，整层被卡在顶部一条里。
     同时把 sticky 也取消：固定定位不需要它，留着还会多一层层叠上下文。 */
  body.adm-rail-open .adm-col.is-railed > .adm-segwrap {
    position: static;
    z-index: auto;
    background: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  /* 包含块保险：position: fixed 的参照物是「最近的会建立包含块的祖先」。
     transform / filter / backdrop-filter / contain / perspective / will-change
     任意一个出现在祖先链上，全屏层就会被缩进那个祖先的框里。
     已知 .adm-segwrap 带 backdrop-filter（上面单独处理过）。这里再把整条祖先链
     一次性清掉，免得以后有人给 .adm 或 .page-content 加个 transform 做动效，
     就把这个面板悄悄弄坏 —— 那种 bug 极难查。只在展开期间生效。 */
  body.adm-rail-open .adm,
  body.adm-rail-open .adm-main,
  body.adm-rail-open .adm-col,
  body.adm-rail-open .page-content {
    transform: none;
    filter: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    contain: none;
    perspective: none;
    will-change: auto;
  }
}

/* 减动效：**不是**全部关掉。淡入保留（它帮人看懂"面板开了"），
   去掉位移和错峰 —— 会让人不适的是位移，不是透明度。 */
@media (max-width: 900px) and (prefers-reduced-motion: reduce) {
  .adm-rail-panel,
  .adm-rail.is-open .adm-rail-panel {
    transform: none;
    opacity: 0;
    transition: opacity 200ms ease;
    will-change: auto;
  }
  .adm-rail.is-open .adm-rail-panel { opacity: 1; }
  .adm-rail-btn,
  .adm-rail.is-open .adm-rail-btn {
    transform: none;
    opacity: 1;
    transition-delay: 0ms;
  }
  .adm-rail-glabel,
  .adm-rail.is-open .adm-rail-glabel {
    opacity: 1;
    transition-delay: 0ms;
  }
  .adm-rail-scrim,
  .adm-rail.is-open .adm-rail-scrim { transition: opacity 200ms ease; }
  .adm-rail-caret { transition: none; }
}

@media (prefers-contrast: more) {
  .adm-rail-glabel { color: var(--adm-label); }
}

@media (prefers-reduced-motion: reduce) {
  .adm-rail-btn:active { transform: none; }
  .adm-rail-toggle:active { transform: none; }
  .adm-rail-dot { transform: none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   风控中心 第十五轮：新增页面的构件
   （品牌条 / 档位台 / 信号族滑杆 / 实时流水 / 待办 / 对象详情 / 日志）
   ══════════════════════════════════════════════════════════════════════════ */

/* --- 品牌小条：每个风控页面顶部的「我在星垣里」锚点 --- */
.rk-brandhead {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 0 0 10px;
  color: var(--adm-label-3);
  font-size: var(--adm-t-footnote);
  font-weight: 500;
}
.rk-brandhead-mark { display: inline-flex; }
.rk-brandhead-mark .rk-emblem-svg { display: block; }
.rk-brandhead-name { color: var(--adm-label); font-weight: 600; }
.rk-brandhead-sep { color: var(--adm-label-4); }
.rk-brandhead-page { color: var(--adm-label-2); }

/* --- 通用：说明块（正文不加粗，灰字） --- */
.rk-hint {
  margin: 0 0 14px;
  padding: 11px 13px;
  border-radius: var(--adm-r-md);
  background: var(--adm-fill-2, var(--adm-fill-3));
  color: var(--adm-label-3);
  font-size: var(--adm-t-footnote);
  line-height: 1.6;
}

/* --- 通用：筛选 chips（手机上也铺满整行，不做横向滚动） --- */
.rk-filter {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 0 0 12px;
}
.rk-chip {
  min-height: 32px;
  padding: 0 12px;
  border: 0;
  border-radius: var(--adm-r-full);
  background: var(--adm-fill-3);
  color: var(--adm-label-2, var(--adm-label));
  font: inherit;
  font-size: var(--adm-t-footnote);
  font-weight: 500;
  cursor: pointer;
  transition: background-color 160ms var(--adm-ease-out), color 160ms var(--adm-ease-out),
    transform 120ms var(--adm-ease-out);
}
.rk-chip:active { transform: scale(0.97); }
.rk-chip.is-active { background: var(--adm-accent-soft); color: var(--adm-label); font-weight: 600; }
.rk-filter-note,
.rk-chip-mini { color: var(--adm-label-4); font-size: var(--adm-t-caption1); }
.rk-filter-tail { padding-bottom: 10px; }
@media (hover: hover) and (pointer: fine) {
  .rk-chip:hover:not(.is-active) { background: var(--adm-fill-2, var(--adm-fill-3)); color: var(--adm-label); }
}

/* --- 档位台 --- */
.rk-profbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 14px;
  padding: 12px 14px;
  border-radius: var(--adm-r-md);
  background: var(--adm-surface-2, var(--adm-fill-3));
  box-shadow: inset 0 0 0 0.5px var(--adm-sep-soft);
}
.rk-profbar-main { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; min-width: 0; }
.rk-profbar-k { color: var(--adm-label-4); font-size: var(--adm-t-caption1); }
.rk-profbar-v { color: var(--adm-label); font-size: var(--adm-t-headline); font-weight: 600; }
.rk-profbar-note { flex: 1 1 100%; color: var(--adm-label-3); font-size: var(--adm-t-caption1); line-height: 1.55; }

/* ⚠️ 档位格子**必须**给列一个真实最小宽度，不能写 minmax(0, 1fr)。
   minmax(0, 1fr) 允许列被压到比 min-content 还窄，中文没有「词」的概念、
   任何位置都能断行，于是「全自动」被压成三个字各占一行 —— 而格子本身
   还是被撑到容器外，整页横向溢出。窄屏正确行为是**换行**（一行放得下几个
   就放几个），不是把每个格子挤扁。auto-fit + 真实 min 就是这个语义。 */
.rk-profrow {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
  gap: 8px;
}
.rk-prof {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  min-height: 84px;
  padding: 11px 10px;
  border: 0;
  border-radius: var(--adm-r-md);
  background: var(--adm-fill-3);
  color: var(--adm-label-2, var(--adm-label));
  font: inherit;
  text-align: left;
  cursor: pointer;
  box-shadow: inset 0 0 0 1px transparent;
  transition: background-color 180ms var(--adm-ease-out), color 180ms var(--adm-ease-out),
    box-shadow 180ms var(--adm-ease-out), transform 120ms var(--adm-ease-out);
}
.rk-prof:active { transform: scale(0.98); }
.rk-prof-name {
  font-size: var(--adm-t-subhead);
  font-weight: 600;
  color: var(--adm-label);
  line-height: 1.25;
  overflow-wrap: anywhere;
}
.rk-prof-sub {
  font-size: var(--adm-t-caption1);
  color: var(--adm-label-3);
  line-height: 1.35;
  overflow-wrap: anywhere;
}
.rk-prof-effect {
  margin-top: auto;
  font-size: var(--adm-t-caption2);
  color: var(--adm-label-4);
  line-height: 1.3;
  overflow-wrap: anywhere;
}
.rk-prof.is-active {
  background: var(--adm-accent-soft);
  box-shadow: inset 0 0 0 1.5px var(--adm-accent);
}
.rk-prof.is-active .rk-prof-name { color: var(--adm-accent-text, var(--adm-label)); }
/* 全自动档是「最强也最危险」的那一个：给它一个持续的语义色边，不当装饰用 */
.rk-prof.is-warn .rk-prof-effect { color: var(--adm-warn-text); }
.rk-prof.is-bad .rk-prof-effect { color: var(--adm-bad-text); }
.rk-prof-desc {
  margin: 12px 0 0;
  color: var(--adm-label-3);
  font-size: var(--adm-t-footnote);
  line-height: 1.6;
}
.rk-auto-actions { margin-top: 14px; }

.rk-eng-state { color: var(--adm-label-3); font-size: var(--adm-t-footnote); }
.rk-eng-state.is-on { color: var(--adm-ok-text); font-weight: 600; }
.rk-eng-meta { margin-left: 8px; color: var(--adm-label-4); font-size: var(--adm-t-caption1); }
.rk-sg-ratio { font-size: var(--adm-t-headline); font-weight: 600; color: var(--adm-ok-text); }
.rk-sg-ratio.is-over { color: var(--adm-bad-text); }
.rk-log-title { display: block; color: var(--adm-label); font-weight: 500; }
.rk-log-detail { color: var(--adm-label-3); font-size: var(--adm-t-caption1); line-height: 1.5; }

/* --- 信号族卡片 + 滑杆 --- */
.rk-fams { display: flex; flex-direction: column; gap: 10px; margin-bottom: 16px; }
.rk-fam {
  padding: 13px 14px;
  border-radius: var(--adm-r-md);
  background: var(--adm-surface-2, var(--adm-fill-3));
  box-shadow: inset 0 0 0 0.5px var(--adm-sep-soft);
}
.rk-fam-head { display: flex; align-items: center; gap: 8px; }
.rk-fam-name { color: var(--adm-label); font-size: var(--adm-t-headline); font-weight: 600; }
.rk-fam-state {
  padding: 1px 8px;
  border-radius: var(--adm-r-full);
  background: var(--adm-fill-3);
  color: var(--adm-label-4);
  font-size: var(--adm-t-caption2);
  font-weight: 600;
}
.rk-fam-state.is-on { background: var(--adm-ok-soft, var(--adm-fill-3)); color: var(--adm-ok-text); }
.rk-fam-guard { margin: 6px 0 0; color: var(--adm-label-2, var(--adm-label)); font-size: var(--adm-t-footnote); line-height: 1.55; }
.rk-fam-impact { margin: 3px 0 0; color: var(--adm-label-4); font-size: var(--adm-t-caption1); line-height: 1.5; }
.rk-fam .rk-fold { margin-top: 10px; }

.rk-slider { margin-top: 11px; }
.rk-slider-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 7px; }
.rk-slider-label { color: var(--adm-label-3); font-size: var(--adm-t-footnote); font-weight: 500; }
.rk-slider-hint { color: var(--adm-label-4); font-size: var(--adm-t-caption1); }
.rk-slider-state { margin-left: auto; color: var(--adm-ok-text); font-size: var(--adm-t-caption1); font-weight: 600; }
.rk-slider.is-off .rk-slider-state { color: var(--adm-label-4); }
.rk-slider-body { display: flex; align-items: center; gap: 12px; margin-top: 7px; }
.rk-range {
  flex: 1 1 auto;
  min-width: 0;
  height: 26px;                 /* 提高触摸命中区，视觉仍是细条 */
  margin: 0;
  accent-color: var(--adm-accent);
  background: transparent;
  cursor: pointer;
}
.rk-slider.is-off .rk-range { accent-color: var(--adm-label-4); }
.rk-num {
  flex: none;
  width: 74px;
  min-height: 34px;
  padding: 0 9px;
  border: 0;
  border-radius: var(--adm-r-sm);
  background: var(--adm-fill-3);
  color: var(--adm-label);
  font: inherit;
  font-size: var(--adm-t-footnote);
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.rk-num:focus-visible { outline: 2px solid var(--adm-accent); outline-offset: 1px; }
.rk-slider.is-off .rk-num { color: var(--adm-label-4); }
.rk-save-row { margin-top: 16px; }

/* --- 实时判定流水 --- */
.rk-live { margin: 0; padding: 0; list-style: none; }
/* ⚠️ 每一行都要有**自己的底色**（第十五轮修）：原来只有 is-warn / is-bad 才上色，
   而那两个色用的 --adm-warn-soft / --adm-bad-soft **根本没有定义**，
   兜底写的是 transparent —— 结果「正常」行和「警告」行全都是透明的一行字，
   用户看到的是一堆没框的文本，直说「那种小卡片都没出来」。
   现在无条件给卡面，语义色只负责左边那道竖条和一层淡染。 */
.rk-live-row {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 10px 12px;
  border-radius: var(--adm-r-md);
  background: var(--adm-surface-2, var(--adm-fill-3));
  box-shadow: inset 0 0 0 0.5px var(--adm-sep-soft);
  border-left: 2px solid transparent;
}
.rk-live-row + .rk-live-row { margin-top: 6px; }
.rk-live-row.is-warn {
  border-left-color: var(--adm-warn);
  background: var(--adm-warn-soft, rgba(255, 159, 10, 0.10));
}
.rk-live-row.is-bad {
  border-left-color: var(--adm-bad);
  background: var(--adm-bad-soft, rgba(255, 69, 58, 0.12));
}
.rk-live-dot {
  flex: none;
  width: 6px;
  height: 6px;
  margin-top: 7px;
  border-radius: var(--adm-r-full);
  background: var(--adm-label-4);
}
.rk-live-row.is-ok .rk-live-dot { background: var(--adm-ok); }
.rk-live-row.is-info .rk-live-dot { background: var(--adm-info); }
.rk-live-row.is-warn .rk-live-dot { background: var(--adm-warn); }
.rk-live-row.is-bad .rk-live-dot { background: var(--adm-bad); }
.rk-live-time {
  flex: none;
  color: var(--adm-label-4);
  font-size: var(--adm-t-caption1);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.rk-live-src {
  flex: none;
  padding: 1px 7px;
  border-radius: var(--adm-r-full);
  background: var(--adm-fill-3);
  color: var(--adm-label-3);
  font-size: var(--adm-t-caption2);
  font-weight: 600;
  white-space: nowrap;
}
.rk-live-main { flex: 1 1 auto; min-width: 0; }
.rk-live-title {
  color: var(--adm-label);
  font-size: var(--adm-t-footnote);
  overflow-wrap: anywhere;
}
.rk-live-detail {
  display: block;
  margin-top: 2px;
  color: var(--adm-label-3);
  font-size: var(--adm-t-caption1);
  line-height: 1.5;
  overflow-wrap: anywhere;
}
.rk-live-score {
  flex: none;
  color: var(--adm-label-2);
  font-size: var(--adm-t-footnote);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.rk-subj {
  padding: 0 2px;
  border: 0;
  background: none;
  color: var(--adm-accent-text, var(--adm-info-text));
  font: inherit;
  font-size: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: var(--adm-sep);
  text-underline-offset: 2px;
  cursor: pointer;
}
.rk-subj:active { opacity: 0.7; }

/* --- 待办 --- */
.rk-todos { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 8px; }
.rk-todo {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 13px;
  border-radius: var(--adm-r-md);
  background: var(--adm-fill-2, var(--adm-fill-3));
  border-left: 2px solid var(--adm-sep);
}
.rk-todo.is-bad { border-left-color: var(--adm-bad); }
.rk-todo.is-warn { border-left-color: var(--adm-warn); }
.rk-todo-main { flex: 1 1 auto; min-width: 0; }
.rk-todo-top { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; }
.rk-todo-title { color: var(--adm-label); font-size: var(--adm-t-subhead); font-weight: 600; }
.rk-todo-subj { margin-top: 3px; color: var(--adm-label-2, var(--adm-label)); font-size: var(--adm-t-footnote); font-weight: 500; }
.rk-todo-detail { margin: 4px 0 0; color: var(--adm-label-3); font-size: var(--adm-t-caption1); line-height: 1.55; }
.rk-todo-go { flex: none; align-self: center; }

/* --- 对象详情 --- */
.rk-entity-score { display: flex; align-items: center; gap: 8px; }
.rk-entity-num { color: var(--adm-label); font-size: var(--adm-t-title3); font-weight: 600; font-variant-numeric: tabular-nums; }
.rk-entity-ev { color: var(--adm-label-3); font-size: var(--adm-t-caption1); line-height: 1.5; }
.rk-entity-none { margin: 0; color: var(--adm-label-3); font-size: var(--adm-t-footnote); }
.rk-linked { margin: 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: 7px; }
.rk-linked-item {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 7px 11px;
  border-radius: var(--adm-r-full);
  background: var(--adm-fill-3);
}
.rk-linked-score { color: var(--adm-label); font-size: var(--adm-t-footnote); font-weight: 600; font-variant-numeric: tabular-nums; }
.rk-actbar { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }

@media (max-width: 720px) {
  /* 手机上「一行几个」交给 auto-fit 自己算：320px 的窄机是 2 个，
     390px 是 3 个。写死 repeat(2, …) 在超大字号下又会把格子压扁。 */
  .rk-profrow { grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); }
  .rk-prof { min-height: 74px; }
  .rk-todo { flex-direction: column; gap: 9px; }
  .rk-todo-go { align-self: flex-start; }
  .rk-slider-body { gap: 9px; }
  .rk-num { width: 64px; }
  .rk-live-row { flex-wrap: wrap; }
  .rk-live-main { flex: 1 1 100%; }
  .rk-live-score { margin-left: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .rk-prof:active, .rk-chip:active { transform: none; }
}

/* --- 决策首页：一键托管 + 待办条（第十五轮） --- */
.rk-decision {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
  padding: 14px 16px;
  border-radius: var(--adm-r-md);
  background: var(--adm-warn-soft, var(--adm-fill-2, var(--adm-fill-3)));
  box-shadow: inset 0 0 0 0.5px var(--adm-sep-soft);
  border-left: 3px solid var(--adm-warn);
}
/* 没有待办时不要用警告色 —— 没事干是好事，不该看起来像报警 */
.rk-decision.is-clear {
  background: var(--adm-surface-2, var(--adm-fill-3));
  border-left-color: var(--adm-ok);
}
.rk-decision-main { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; min-width: 0; }
.rk-decision-num { color: var(--adm-label); font-size: var(--adm-t-title2); font-weight: 600; font-variant-numeric: tabular-nums; }
.rk-decision-label { color: var(--adm-label); font-size: var(--adm-t-subhead); font-weight: 600; }
.rk-decision-sub {
  flex: 1 1 100%;
  color: var(--adm-label-3);
  font-size: var(--adm-t-caption1);
  line-height: 1.5;
}
.rk-quicklinks { display: flex; flex-wrap: wrap; gap: 6px; }

/* ══════════════════════════════════════════════════════════════════════════
   风控中心：横向溢出护栏（2026-09-17 第十五轮修）

   用户实测：「有时候它都超出屏幕了，整个排版都有全部大问题」。

   成因是一类，不是一处：风控页里到处是**外部数据**（账号名 / IP / UA /
   错误消息 / 运营写的中文长句）。中文可以在任意字符处断行，所以中文长句
   从来没出过事 —— 但英文账号名、IPv6、URL、长数字串不会断，它们会把
   所在的那一行撑宽，一行撑宽就把 flex/grid 容器顶开，最后整页横向溢出。

   三件事一起做才彻底：
     1) 容器 min-width: 0 —— flex/grid 子项的默认 min-width 是 auto
        （等于 min-content），不改成 0，子项永远拒绝变窄，断行根本没机会发生。
     2) 文本 overflow-wrap: anywhere —— 允许在超长串的任意位置断行。
     3) 兜底的 overflow-x: clip —— 万一还有漏网的，裁掉而不是让整页能横滑。
        （用 clip 不用 hidden：hidden 会新建滚动容器，正是侧栏那个 bug 的成因。）
   ══════════════════════════════════════════════════════════════════════════ */
.adm-card-body,
.adm-group,
.adm-list,
.adm-body,
.adm-actions,
.adm-row-value,
.rk-decision,
.rk-decision-main,
.rk-subj,
.rk-brandhead {
  min-width: 0;
}
.rk-eng-meta,
.rk-log-title,
.rk-log-detail,
.rk-fam-guard,
.rk-fam-impact,
.rk-fam-state,
.rk-todo-title,
.rk-todo-subj,
.rk-todo-detail,
.rk-entity-ev,
.rk-entity-none,
.rk-hint,
.rk-prof-desc,
.rk-slider-hint,
.rk-decision-sub,
.rk-linked-score,
.rk-sg-ratio {
  overflow-wrap: anywhere;
}
/* 最后一层保险：风控页的内容区永不出现横向滚动 */
.adm-col.is-railed > .adm-body { overflow-x: clip; }

/* ══════════════════════════════════════════════════════════════════════════
   风控中心 · 「算法决策」页（2026-09-17 新增）
   ──────────────────────────────────────────────────────────────────────────
   用户原话：「这个算法执行了哪些规定？我能不能看到？」

   为什么是卡片而不是表格：
     每条规则有两段**长度不定**的中文说明（"看什么" / "何时满格"），
     表格在手机上只能横向滚动，而那恰好是把这两段毁掉的做法。
     卡片天然纵向堆叠，手机上一条一屏、宽屏上自动分两列。
   圆角语言跟第十五轮 B 的下拉导航保持一致（14px），整站看起来是一套东西。
   ══════════════════════════════════════════════════════════════════════════ */

.rk-dec-loading {
  padding: 28px 4px;
  color: var(--adm-label-3);
  font-size: var(--adm-t-footnote);
  text-align: center;
}

/* 分级线：一条横向的对照表，告诉人"多少分意味着什么"。
   没有它，分数就只是个数字。手机上允许换行，不做横向滚动。 */
.rk-dec-note {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 4px 0 14px;
  color: var(--adm-label-3);
  font-size: var(--adm-t-caption1);
}
.rk-dec-lv {
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--adm-fill-2, var(--adm-surface-2));
  box-shadow: inset 0 0 0 0.5px var(--adm-sep-soft);
  white-space: nowrap;
}

/* ── 规则卡网格 ───────────────────────────────────────────────────── */
.rk-rule-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(268px, 1fr));
  gap: 10px;
}
.rk-rule-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  padding: 12px 13px;
  border-radius: 14px;
  background: var(--adm-surface-2, var(--adm-fill-3));
  box-shadow: inset 0 0 0 0.5px var(--adm-sep-soft);
}
.rk-rule-card.is-off { opacity: 0.55; }

.rk-rule-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  min-width: 0;
}
.rk-rule-name {
  min-width: 0;
  color: var(--adm-label);
  font-size: var(--adm-t-subhead);
  font-weight: 600;
  overflow-wrap: anywhere;
}
.rk-rule-score { flex: none; white-space: nowrap; }
.rk-rule-w {
  color: var(--adm-accent);
  font-size: var(--adm-t-subhead);
  font-weight: 700;
}
.rk-rule-unit {
  margin-left: 1px;
  color: var(--adm-label-3);
  font-size: var(--adm-t-caption1);
}
.rk-rule-off {
  color: var(--adm-label-3);
  font-size: var(--adm-t-caption1);
}

/* 「看什么 / 何时满格」两行：左侧一个固定宽的小标签，右侧说明。
   标签列固定宽度是为了让多张卡的说明文字左边缘对齐 —— 不齐的话
   一屏扫下来眼睛要重新找起点，这是列表可读性里最便宜的一个改进。 */
.rk-rule-look,
.rk-rule-full {
  display: flex;
  gap: 8px;
  min-width: 0;
  color: var(--adm-label-2, var(--adm-label));
  font-size: var(--adm-t-footnote);
  line-height: 1.45;
  overflow-wrap: anywhere;
}
.rk-rule-k {
  flex: none;
  width: 3.6em;
  color: var(--adm-label-4);
  font-size: var(--adm-t-caption1);
  line-height: 1.7;
}

.rk-rule-foot {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 2px;
  padding-top: 7px;
  border-top: 1px solid var(--adm-sep-soft);
}
.rk-rule-hit {
  flex: 1 1 auto;
  min-width: 0;
  color: var(--adm-warn-text, var(--adm-label-2));
  font-size: var(--adm-t-caption1);
  overflow-wrap: anywhere;
}
.rk-rule-hit.is-zero { color: var(--adm-label-4); }
.rk-rule-code {
  flex: none;
  color: var(--adm-label-4);
  font-family: var(--adm-mono);
  font-size: var(--adm-t-caption2);
}

/* ── 决策流水条目 ─────────────────────────────────────────────────── */
.rk-dec-item {
  padding: 12px 13px;
  border-radius: 14px;
  background: var(--adm-surface-2, var(--adm-fill-3));
  box-shadow: inset 0 0 0 0.5px var(--adm-sep-soft);
}
.rk-dec-item + .rk-dec-item { margin-top: 9px; }

.rk-dec-head {
  display: flex;
  flex-wrap: wrap;          /* 手机上宁可换行也不要横向滚动 */
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.rk-dec-who {
  min-width: 0;
  color: var(--adm-label);
  font-weight: 600;
  overflow-wrap: anywhere;
}
.rk-dec-score {
  color: var(--adm-label);
  font-size: var(--adm-t-footnote);
  font-weight: 600;
}
.rk-dec-time {
  margin-left: auto;        /* 时间靠右，跟左边那组信息分开 */
  flex: none;
  color: var(--adm-label-4);
  font-size: var(--adm-t-caption1);
}

.rk-dec-title {
  margin-top: 6px;
  color: var(--adm-label-2, var(--adm-label));
  font-size: var(--adm-t-footnote);
  font-weight: 600;
}
.rk-dec-detail {
  margin-top: 3px;
  color: var(--adm-label-3);
  font-size: var(--adm-t-footnote);
  line-height: 1.5;
  overflow-wrap: anywhere;
}

/* 证据链：哪几条规则、各贡献多少分。这是"凭什么"的答案 */
.rk-dec-rules {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}
.rk-dec-rule {
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--adm-accent-soft);
  color: var(--adm-label-2, var(--adm-label));
  font-size: var(--adm-t-caption1);
  white-space: nowrap;
}

/* ══════════════════════════════════════════════════════════════
   第十七轮 · 对象详情：「判决解释」与「信号归属」
   --------------------------------------------------------------
   为什么不用动效：这一页是排查现场，数字和结论一秒都不能飘。
   信息层级靠边框/底色/字重表达，不靠位移。这与 admin.css 里
   「排查类页面不做动画」的既定纪律一致。
   ══════════════════════════════════════════════════════════════ */

/* 判决解释：紧跟总分，一句话回答「为什么是这个分、为什么还没动手」 */
.rk-verdict {
  margin: 0 0 14px;
  padding: 12px 14px;
  border-radius: var(--adm-r-md);
  background: var(--adm-fill-3);
  border-left: 3px solid var(--adm-label-4);
}
.rk-verdict.is-warn { border-left-color: var(--adm-warn); }
.rk-verdict.is-bad  { border-left-color: var(--adm-bad); }
.rk-verdict-head { display: flex; align-items: center; gap: 8px; }
.rk-verdict-dot {
  width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto;
  background: var(--adm-label-3);
}
.rk-verdict.is-warn .rk-verdict-dot { background: var(--adm-warn); }
.rk-verdict.is-bad  .rk-verdict-dot { background: var(--adm-bad); }
.rk-verdict-title {
  color: var(--adm-label);
  font-size: var(--adm-t-subhead);
  font-weight: 600;
  letter-spacing: var(--adm-ls-sub);
}
.rk-verdict-list { margin: 8px 0 0; padding: 0 0 0 15px; list-style: none; }
.rk-verdict-list li {
  position: relative;
  color: var(--adm-label-2);
  font-size: var(--adm-t-footnote);
  line-height: 1.62;
}
.rk-verdict-list li + li { margin-top: 4px; }
.rk-verdict-list li::before {
  content: "";
  position: absolute; left: -15px; top: 0.58em;
  width: 4px; height: 4px; border-radius: 50%;
  background: var(--adm-label-4);
}
.rk-verdict-list li.is-warn { color: var(--adm-warn-text); }
.rk-verdict-list li.is-warn::before { background: var(--adm-warn); }

/* 分数构成条：一眼看出「这个人的分几乎全来自哪一族」 */
.rk-fbar-wrap { margin: 0 0 14px; }
.rk-fbar {
  display: flex;
  height: 10px;
  border-radius: var(--adm-r-full);
  overflow: hidden;
  background: var(--adm-fill-3);
}
.rk-fbar-seg { height: 100%; background: var(--adm-fill); }
.rk-fbar-seg + .rk-fbar-seg { box-shadow: -1px 0 0 0 var(--adm-surface); }
.rk-fbar-seg.f-identity { --rk-fam-c: var(--adm-info); }
.rk-fbar-seg.f-network  { --rk-fam-c: var(--adm-warn); }
.rk-fbar-seg.f-velocity { --rk-fam-c: var(--adm-ok); }
.rk-fbar-seg.f-behavior { --rk-fam-c: #bf5af2; }
.rk-fbar-seg.f-graph    { --rk-fam-c: var(--adm-bad); }
.rk-fbar-seg.f-content  { --rk-fam-c: var(--adm-info); }
.rk-fbar-seg { background: var(--rk-fam-c, var(--adm-fill)); }
.rk-fbar-legend {
  display: flex; flex-wrap: wrap; gap: 4px 14px;
  margin-top: 9px;
}
.rk-fbar-key {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--adm-label-2);
  font-size: var(--adm-t-caption1);
}
.rk-fbar-key i {
  width: 8px; height: 8px; border-radius: 2px; flex: 0 0 auto;
  background: var(--adm-fill);
}
.rk-fbar-key.f-identity i { --rk-fam-c: var(--adm-info); }
.rk-fbar-key.f-network  i { --rk-fam-c: var(--adm-warn); }
.rk-fbar-key.f-velocity i { --rk-fam-c: var(--adm-ok); }
.rk-fbar-key.f-behavior i { --rk-fam-c: #bf5af2; }
.rk-fbar-key.f-graph    i { --rk-fam-c: var(--adm-bad); }
.rk-fbar-key.f-content  i { --rk-fam-c: var(--adm-info); }
.rk-fbar-key i { background: var(--rk-fam-c, var(--adm-fill)); }
.rk-fbar-key .adm-num {
  color: var(--adm-label);
  font-variant-numeric: tabular-nums;
}

/* 家族分组：同一族的信号聚在一起，看出它们其实是同一个源头的多个侧面 */
.rk-fam-wrap { display: flex; flex-direction: column; gap: 12px; }
.rk-fam {
  padding: 10px 12px;
  border-radius: var(--adm-r-md);
  background: var(--adm-fill-3);
  border: 1px solid var(--adm-sep-soft);
}
.rk-fam-head { display: flex; align-items: center; gap: 8px; }
.rk-fam-dot {
  width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto;
  background: var(--adm-label-3);
}
.rk-fam.f-identity .rk-fam-dot { --rk-fam-c: var(--adm-info); }
.rk-fam.f-network  .rk-fam-dot { --rk-fam-c: var(--adm-warn); }
.rk-fam.f-velocity .rk-fam-dot { --rk-fam-c: var(--adm-ok); }
.rk-fam.f-behavior .rk-fam-dot { --rk-fam-c: #bf5af2; }
.rk-fam.f-graph    .rk-fam-dot { --rk-fam-c: var(--adm-bad); }
.rk-fam.f-content  .rk-fam-dot { --rk-fam-c: var(--adm-info); }
.rk-fam-dot { background: var(--rk-fam-c, var(--adm-label-3)); }
.rk-fam-name {
  color: var(--adm-label);
  font-size: var(--adm-t-footnote);
  font-weight: 600;
}
.rk-fam-count { color: var(--adm-label-3); font-size: var(--adm-t-caption1); }
.rk-fam-pts {
  margin-left: auto;
  color: var(--adm-label-2);
  font-size: var(--adm-t-caption1);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.rk-fam-list {
  margin: 9px 0 0; padding: 0; list-style: none;
  display: flex; flex-direction: column; gap: 10px;
}
.rk-sig-top { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.rk-sig-name {
  color: var(--adm-label-2);
  font-size: var(--adm-t-footnote);
}
.rk-sig-tag {
  padding: 1px 7px;
  border-radius: var(--adm-r-full);
  background: var(--adm-bad);
  color: #ffffff;
  font-size: var(--adm-t-caption2);
  font-weight: 600;
  white-space: nowrap;
}
.rk-sig-pts {
  margin-left: auto;
  color: var(--adm-label);
  font-size: var(--adm-t-footnote);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.rk-sig-meter { margin-top: 5px; }
.rk-sig-ev {
  margin: 5px 0 0;
  color: var(--adm-label-3);
  font-size: var(--adm-t-caption1);
  line-height: 1.5;
  overflow-wrap: anywhere;
}
.rk-fam-note {
  margin: 12px 0 0;
  color: var(--adm-label-3);
  font-size: var(--adm-t-caption1);
  line-height: 1.6;
}

/* 窄屏：家族分组在手机上收紧内边距，分值始终保持在右端 */
@media (max-width: 480px) {
  .rk-verdict { padding: 10px 12px; }
  .rk-fam { padding: 9px 10px; }
  .rk-fbar-legend { gap: 4px 10px; }
  .rk-dec-rule { white-space: normal; }
}


/* --- 第三十轮：用户详情剩余额度卡内部节奏 --- */
/* 百分比 + 剩余 贴紧；积分行、进度条、刷新行依次拉开 */
.qcard-space .adm-tile-value { line-height: 1.1; }
.qcard-space .adm-tile-value + .adm-small { margin-top: 2px; }
.qcard-space .adm-small + .adm-tiny { margin-top: 16px; }
.qcard-space .adm-bar { margin-top: 10px; }
.qcard-space .adm-bar + .adm-tiny { margin-top: 14px; }

/* ── 兑换码页（第三十三轮新增）──────────────────────────────────────────── */
.adm-form-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
@media (max-width: 640px) { .adm-form-row { grid-template-columns: 1fr; } }

.adm-codes { display: flex; flex-direction: column; gap: 8px; margin-top: 6px; }
.adm-codes code {
  display: block; font-family: var(--adm-mono); font-size: 15px; letter-spacing: .06em;
  padding: 12px 14px; background: var(--adm-fill); border: 1px solid var(--adm-border);
  border-radius: var(--adm-r-md); color: var(--adm-label); cursor: pointer; user-select: all;
  word-break: break-all;
  transition: background .16s var(--adm-ease-out), border-color .16s var(--adm-ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .adm-codes code:hover { background: var(--adm-fill-2); border-color: var(--adm-accent); }
}
.adm-code { font-family: var(--adm-mono); font-size: 12.5px; letter-spacing: .02em; color: var(--adm-label-2); }
.adm-dim { color: var(--adm-label-3); font-size: 12px; }

.adm-search-row { display: flex; gap: 10px; align-items: center; margin-bottom: 12px; }
.adm-search-row .adm-input { flex: 1; }

.adm-filters { display: flex; gap: 6px; flex-wrap: wrap; }
.adm-filter {
  appearance: none; border: 1px solid var(--adm-border); background: transparent; color: var(--adm-label-2);
  font: inherit; font-size: 13px; padding: 5px 12px; border-radius: var(--adm-r-full); cursor: pointer;
  transition: background .16s var(--adm-ease-out), color .16s var(--adm-ease-out), border-color .16s var(--adm-ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .adm-filter:hover { background: var(--adm-fill); }
}
.adm-filter.is-active { background: var(--adm-accent); border-color: var(--adm-accent); color: var(--adm-on-accent); }

.adm-pager { display: flex; gap: 12px; align-items: center; justify-content: center; margin-top: 14px; color: var(--adm-label-3); font-size: 13px; }

@media (prefers-reduced-motion: reduce) {
  .adm-codes code, .adm-filter { transition: none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   外壳 v2（第二十八轮补 11 · 2026-09-25）
   ──────────────────────────────────────────────────────────────────────────
   为什么换壳：用户原话「完全适配手机端，重新分类，太难看了，太混乱了」。

   三条自查过的约束（沿用 admin.css 顶部的三条铁律）：
     1) 全部选择器都在 .adm / body.adm-mode 之下，绝不外泄到聊天界面；
     2) 玻璃只给「顶栏 / 底栏 / 抽屉 / 弹层」这类 chrome，内容卡片一律不透明；
     3) 只有一套单色强调色 + 四个语义色，不引入新的主题色。

   结构：
     手机 = 顶栏（返回 + 标题 + 刷新） + 分区首页（卡片清单） + 底部 4 Tab + 更多(抽屉)
     桌面 = 左侧常驻抽屉（≥900px）+ 右侧分区首页 / 具体页
   子页 key 与旧版**一字不差**，深链 #admin/<key> 照旧可用。
   ══════════════════════════════════════════════════════════════════════════ */

/* ---------- 1. 根布局 ---------- */
.adm.asx-app {
  grid-template-columns: minmax(0, 1fr);
  min-height: 100%;
  align-items: start;
}
.asx-col { min-width: 0; display: flex; flex-direction: column; }

/* ---------- 2. 顶栏（玻璃 · 仅 chrome） ---------- */
.asx-bar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 4px;
  min-height: var(--adm-nav-h);
  padding: env(safe-area-inset-top, 0px) 8px 0 6px;
  background: transparent;
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
  transition: background-color 200ms var(--adm-ease-out), box-shadow 200ms var(--adm-ease-out);
}
.asx-bar.is-scrolled {
  background: var(--adm-glass);
  /* 卷边阴影代替 1px 硬分割线：内容从玻璃条下方穿过时是渐隐而不是被切断 */
  box-shadow: 0 0.5px 0 var(--adm-sep-soft), 0 6px 18px -14px rgba(0, 0, 0, 0.5);
}
.asx-bar-btn {
  flex: 0 0 auto;
  width: 44px;                 /* ≥44pt 命中区，别用 36px 的「好看但点不准」 */
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--adm-r-full);
  background: transparent;
  color: var(--adm-label);
  cursor: pointer;
  transition: background-color 150ms var(--adm-ease-out), transform 150ms var(--adm-ease-out);
}
.asx-bar-btn:active { transform: scale(0.94); background: var(--adm-fill-3); }
.asx-bar-btn svg { display: block; }
.asx-bar-btn.is-busy svg { animation: asx-spin 720ms linear infinite; }
@keyframes asx-spin { to { transform: rotate(360deg); } }
.asx-bar-mid { flex: 1 1 auto; min-width: 0; padding-right: 4px; }
.asx-bar-title {
  font-size: var(--adm-t-headline);
  font-weight: 600;
  letter-spacing: var(--adm-ls-body);
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.asx-bar-sub {
  font-size: var(--adm-t-caption1);
  letter-spacing: -0.005rem;
  color: var(--adm-label-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- 3. 内容区 ---------- */
.asx-main { min-width: 0; flex: 1 1 auto; }
.asx-wrap {
  max-width: 1120px;
  margin: 0 auto;
  padding: 6px max(16px, env(safe-area-inset-right, 0px))
           calc(92px + env(safe-area-inset-bottom, 0px))
           max(16px, env(safe-area-inset-left, 0px));
}
.asx-hub-head { padding: 6px 0 16px; }
.asx-hub-title {
  margin: 0;
  font-size: var(--adm-t-largetitle);
  font-weight: 700;
  letter-spacing: var(--adm-ls-lg);
  line-height: 1.18;
  color: var(--adm-label);
}
.asx-page-head { padding: 2px 0 14px; }
.asx-page-head .asx-hub-title { font-size: var(--adm-t-title1); }
.asx-hub-desc {
  margin: 6px 0 0;
  font-size: var(--adm-t-footnote);
  letter-spacing: -0.005rem;
  line-height: 1.45;
  color: var(--adm-label-2);
}
.asx-glabel {
  padding: 14px 12px 4px;
  font-size: var(--adm-t-caption2);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--adm-label-3);
}
#adm-hub .asx-glabel {
  padding: 18px 2px 8px;
  font-size: var(--adm-t-footnote);
  letter-spacing: 0;
  text-transform: none;
  color: var(--adm-label-2);
}
.asx-empty { padding: 28px 12px; text-align: center; color: var(--adm-label-2); font-size: var(--adm-t-subhead); }

/* ---------- 4. 分区首页的卡片 ---------- */
.asx-cards { display: grid; gap: 10px; }
.asx-hcard {
  position: relative;
  display: flex;
  align-items: center;
  gap: 13px;
  width: 100%;
  min-height: 64px;
  padding: 13px 14px;
  border: 0;
  border-radius: var(--adm-r-lg);
  background: var(--adm-surface);
  /* 极轻的一道顶部高光：让不透明卡面看起来是「一块材质」而不是一个色块。
     克制到几乎察觉不到 —— 只有 3% 白，且 60% 处就散完。 */
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.03), rgba(255, 255, 255, 0) 62%);
  color: var(--adm-label);
  font: inherit;
  text-align: left;
  cursor: pointer;
  box-shadow: 0 0 0 0.5px var(--adm-sep-soft), var(--adm-shadow-raise);
  transition: transform 140ms var(--adm-ease-out), background-color 140ms var(--adm-ease-out);
}
.asx-hcard:active { transform: scale(0.985); }
.asx-hcard-ico {
  flex: 0 0 auto;
  width: 40px; height: 40px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--adm-r-md);
  background: var(--adm-fill-3);
  color: var(--adm-label);
}
.asx-hcard-ico svg { display: block; }
.asx-hcard-txt { flex: 1 1 auto; min-width: 0; display: block; }
.asx-hcard-label {
  display: block;
  font-size: var(--adm-t-headline);
  font-weight: 600;
  letter-spacing: var(--adm-ls-sub);
}
.asx-hcard-desc {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin-top: 3px;
  font-size: var(--adm-t-footnote);
  line-height: 1.4;
  color: var(--adm-label-2);
}
.asx-hcard-chev { flex: 0 0 auto; color: var(--adm-label-3); display: inline-flex; }
.asx-hcard-badge { flex: 0 0 auto; display: inline-flex; }

/* ---------- 5. 底部 Tab 栏（玻璃） ---------- */
.asx-tabs {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 30;
  display: flex;
  align-items: stretch;
  height: calc(58px + env(safe-area-inset-bottom, 0px));
  padding: 0 max(4px, env(safe-area-inset-left, 0px)) env(safe-area-inset-bottom, 0px)
           max(4px, env(safe-area-inset-right, 0px));
  background: var(--adm-glass-strong);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
  backdrop-filter: blur(24px) saturate(180%);
  box-shadow: 0 -0.5px 0 var(--adm-sep-soft), 0 -10px 26px -20px rgba(0, 0, 0, 0.6);
}
.asx-tab {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  border: 0;
  background: transparent;
  color: var(--adm-label-2);
  font: inherit;
  font-size: var(--adm-t-caption2);
  letter-spacing: 0.0044rem;
  cursor: pointer;
  transition: color 160ms var(--adm-ease-out), transform 160ms var(--adm-ease-out);
}
.asx-tab:active { transform: scale(0.94); }
.asx-tab-ico { display: block; height: 24px; position: relative; }
.asx-tab-ico svg { display: block; }
.asx-tab-label { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.asx-tab.is-active { color: var(--adm-label); font-weight: 600; }
.asx-tab-badge-dot {
  position: absolute;
  top: -5px; right: -9px;
  min-width: 16px; height: 16px;
  padding: 0 4px;
  border-radius: var(--adm-r-full);
  background: var(--adm-bad);
  color: #ffffff;
  font-size: var(--adm-t-caption2);
  font-weight: 700;
  line-height: 16px;
  text-align: center;
}

/* ---------- 6. 抽屉 / 侧栏 ---------- */
.asx-scrim {
  position: fixed;
  inset: 0;
  z-index: 34;
  background: rgba(0, 0, 0, 0.5);
  opacity: 0;
  transition: opacity 220ms var(--adm-ease-out);
}
.asx-scrim.is-open { opacity: 1; }

.asx-drawer {
  position: fixed;
  top: 0; bottom: 0; left: 0;
  z-index: 35;
  width: min(86vw, 340px);
  display: flex;
  flex-direction: column;
  background: var(--adm-glass-strong);
  -webkit-backdrop-filter: blur(30px) saturate(180%);
  backdrop-filter: blur(30px) saturate(180%);
  box-shadow: 0.5px 0 0 var(--adm-sep-soft), 28px 0 70px -30px rgba(0, 0, 0, 0.75);
  transform: translateX(-102%);
  transition: transform 280ms var(--adm-ease-drawer);
  will-change: transform;
}
.asx-drawer.is-open { transform: none; }
.asx-drawer-head {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: calc(14px + env(safe-area-inset-top, 0px)) 14px 12px;
}
.asx-drawer-top { display: flex; align-items: center; gap: 8px; }
.asx-brand { flex: 1 1 auto; min-width: 0; }
.asx-brand-title {
  font-size: var(--adm-t-title3);
  font-weight: 700;
  letter-spacing: var(--adm-ls-title3);
  line-height: 1.2;
}
.asx-brand-sub {
  margin-top: 2px;
  font-size: var(--adm-t-caption1);
  color: var(--adm-label-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.asx-search-wrap { position: relative; display: flex; align-items: center; }
.asx-search-wrap > svg {
  position: absolute;
  left: 10px;
  color: var(--adm-label-2);
  pointer-events: none;
}
.asx-search-wrap input {
  width: 100%;
  height: 38px;
  padding: 0 12px 0 32px;
  border: 0;
  border-radius: var(--adm-r-md);
  background: var(--adm-fill-2);
  color: var(--adm-label);
  font: inherit;
  font-size: var(--adm-t-subhead);
  outline: none;
}
.asx-search-wrap input::placeholder { color: var(--adm-label-2); }
.asx-search-wrap input:focus { background: var(--adm-fill-3); box-shadow: 0 0 0 0.5px var(--adm-sep); }

.asx-drawer-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 0 8px 10px;
}
.asx-dgroup { padding-bottom: 2px; }
.asx-gbtn {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 46px;
  padding: 6px 10px;
  border: 0;
  border-radius: var(--adm-r-md);
  background: transparent;
  color: var(--adm-label);
  font: inherit;
  font-size: var(--adm-t-headline);
  text-align: left;
  cursor: pointer;
  transition: background-color 140ms var(--adm-ease-out);
}
.asx-gbtn:active { background: var(--adm-fill-3); }
.asx-gbtn.is-active { background: var(--adm-fill-2); font-weight: 600; }
.asx-gbtn-ico { flex: 0 0 auto; display: inline-flex; color: var(--adm-label-2); }
.asx-gbtn.is-active .asx-gbtn-ico { color: var(--adm-label); }
.asx-gbtn-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.asx-gbtn-badge,
.asx-ditem-badge { flex: 0 0 auto; }
.asx-subs { padding: 0 0 2px 10px; }
.asx-ditem {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 42px;
  padding: 6px 12px;
  border: 0;
  border-radius: var(--adm-r-sm);
  background: transparent;
  color: var(--adm-label-2);
  font: inherit;
  font-size: var(--adm-t-subhead);
  letter-spacing: var(--adm-ls-sub);
  text-align: left;
  cursor: pointer;
  transition: background-color 140ms var(--adm-ease-out), color 140ms var(--adm-ease-out);
}
.asx-ditem:active { background: var(--adm-fill-3); }
.asx-ditem.is-active { background: var(--adm-accent-soft); color: var(--adm-label); font-weight: 600; }
.asx-ditem-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.asx-drawer-foot {
  flex: 0 0 auto;
  padding: 8px 10px calc(10px + env(safe-area-inset-bottom, 0px));
  box-shadow: 0 -0.5px 0 var(--adm-sep-soft);
}
.asx-exitbtn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  min-height: 44px;
  border: 0;
  border-radius: var(--adm-r-md);
  background: transparent;
  color: var(--adm-label-2);
  font: inherit;
  font-size: var(--adm-t-subhead);
  cursor: pointer;
  transition: background-color 140ms var(--adm-ease-out);
}
.asx-exitbtn:active { background: var(--adm-fill-3); }
.asx-exitbtn svg { display: block; }

/* ---------- 7. 交互细节 ---------- */
.asx-tab,
.asx-gbtn,
.asx-ditem,
.asx-exitbtn,
.asx-hcard {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
@media (hover: hover) and (pointer: fine) {
  .asx-hcard:hover { background-color: var(--adm-surface-2); }
  .asx-tab:hover, .asx-ditem:hover, .asx-gbtn:hover, .asx-exitbtn:hover { color: var(--adm-label); }
  .asx-bar-btn:hover { background: var(--adm-fill-3); }
}

/* 抽屉打开时锁住页面滚动 —— 保证同一时刻只有一个可滚容器
   （第十五轮踩过的坑：两个滚动容器并存时，手势落在哪儿就滚哪个）。 */
@media (max-width: 899px) {
  body.asx-drawer-open #page-content { overflow: hidden; }
}

/* ---------- 8. 桌面（≥900px）：抽屉变常驻左栏 ---------- */
@media (min-width: 900px) {
  .adm.asx-app { grid-template-columns: 250px minmax(0, 1fr); }
  .asx-tabs { display: none; }
  .asx-scrim { display: none !important; }
  .asx-drawer {
    position: sticky;
    top: 0;
    height: 100dvh;
    width: auto;
    transform: none;
    z-index: 25;
    background: var(--adm-bg);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    box-shadow: none;
    border-right: 0.5px solid var(--adm-sep-soft);
    padding-left: env(safe-area-inset-left, 0px);
    /* ⚠️ 桌面才允许侧栏自己滚。手机上这里是 fixed 全屏抽屉，锁页面后
       它是唯一的滚动容器；桌面是鼠标滚轮，两个容器并存没有手势歧义。 */
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  .asx-drawer-head { padding-top: 18px; }
  .asx-only-mobile { display: none !important; }
  .asx-wrap { padding: 12px 32px 56px; }
  .asx-bar { padding-left: 20px; padding-right: 20px; }
  .asx-hub-title { font-size: 2.25rem; }
  .asx-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
  .asx-drawer-foot { padding-bottom: 16px; }
  #adm-hub .asx-glabel { padding-top: 20px; }
}
@media (min-width: 1280px) {
  .asx-cards { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ---------- 9. 无障碍：降级要真的降级 ---------- */
@media (prefers-reduced-transparency: reduce) {
  .asx-bar, .asx-tabs, .asx-drawer {
    background: var(--adm-bg);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  .asx-bar.is-scrolled { background: var(--adm-bg); }
}
@media (prefers-reduced-motion: reduce) {
  .asx-drawer, .asx-scrim, .asx-hcard, .asx-tab, .asx-bar-btn,
  .asx-gbtn, .asx-ditem, .asx-exitbtn {
    transition-duration: 1ms !important;
  }
  .asx-hcard:active, .asx-tab:active, .asx-bar-btn:active { transform: none; }
  .asx-bar-btn.is-busy svg { animation: none; }
}
@media (prefers-contrast: more) {
  .asx-hcard { box-shadow: 0 0 0 1px var(--adm-sep); }
  .asx-ditem.is-active, .asx-gbtn.is-active { box-shadow: 0 0 0 1px var(--adm-sep); }
}
