/* =============================================================================
   企业后台 · company-admin / style.css
   -----------------------------------------------------------------------------
   Phase 3 · 刀 1：全量重写（原 397 行 → 本文件）
   依据：docs/company-admin-design-spec.md（Phase 1 视觉规范，数值唯一来源）
         docs/company-admin-experience-spec.md（Phase 2 体验规范）
         docs/company-admin-class-inventory.md（98 个 class 覆盖清单）

   约束（本刀不越界）：
   · 只改这一个文件；不改任何 .js / .html；不引入外部字体 / CDN / 图标库 / 构建。
   · 类名与现有模板完全兼容（不重命名），否则 380 处内联样式与 21 个页面会失配。
   · 旧 CSS 变量名全部保留为"别名层"（见 §2），否则内联 style="…var(--border)…" 静默失效。

   目录
     §1  设计 token（:root）
     §2  旧变量别名层（内联样式兼容，刀 3 清理内联后可删）
     §3  基础重置与全局排版
     §4  骨架：.app / .sidebar / .topbar / .content
     §5  容器：.card 系列 / KPI 卡
     §6  表格：.data-table 与 .table（同一套规则）/ 权限矩阵 / 缩略图
     §7  按钮
     §8  表单、搜索、筛选控件
     §9  徽章 6 态 / 状态点 / 筛选 chip
     §10 Tab / 工具栏 / 分页 / 批量条 / 下拉 / Stepper
     §11 空态 / 加载骨架 / 提示文本
     §12 弹窗 / Toast / 浮层
     §13 业务遗留组件（文档列表 / 脚本向导 / 音频色块块 / 关于页）
     §14 登录页与改密页
     §15 响应式 5 档断点
     §16 自检表（98 个 class 逐条落位 + 豁免说明）
   ========================================================================== */


/* =============================================================================
   §1  设计 token
   -----------------------------------------------------------------------------
   全部数值来自 Phase 1 §1，不得在此之外新造数值。新增组件若缺 token，
   优先复用最近的档位，而不是发明 15px / 18px / 22px 这类值。
   ========================================================================== */
:root {
  /* ── 1.1 主色：深空青 11 档（§1.1）────────────────────────────────────── */
  --teal-50:  #EDF7FA;
  --teal-100: #D3ECF2;
  --teal-200: #A9D9E5;
  --teal-300: #74BFD0;
  --teal-400: #3D9FB6;
  --teal-500: #17879F;   /* 图形色：图表/图标强调，⚠ 不作按钮填充（白字对比 4.35） */
  --teal-600: #0F6E86;   /* 主色：主按钮、聚焦边框、Tab 指示线（白字 5.84 ✅） */
  --teal-700: #0C596D;   /* 主按钮 hover / 强调文字 */
  --teal-800: #0A4757;   /* 主按钮 active */
  --teal-900: #0A2A33;   /* 侧边栏底色（深空面） */
  --teal-950: #06202A;   /* 深空面最深层（登录页） */

  /* ── 1.2 深空面专用色（§2.1 导航三态，属于组件级固定值，不是通用色阶）── */
  --ink-text:      #A9C2CB;                    /* 默认文字 */
  --ink-icon:      #7E97A1;                    /* 默认图标 */
  --ink-strong:    #E6EFF2;                    /* hover 文字 */
  --ink-bright:    #7BD3E8;                    /* 选中图标 / 聚焦环 */
  --ink-group:     #7E97A1;   /* 分组标题 / 角色文字 / 版权行（对 --teal-900 = 4.91 ✅）
                                 旧值（对深空面只有 4.03 的那个偏绿灰）已列为禁用值 */
  --ink-hover-bg:  rgba(255, 255, 255, 0.06);  /* hover 背景 */
  --ink-active-bg: #12414E;                    /* 选中实色浮块 */
  --ink-ring:      rgba(123, 211, 232, 0.24);  /* 选中 inset 描边环 */
  --ink-line:      rgba(255, 255, 255, 0.08);  /* 深空面分隔线 */

  /* ── 1.3 中性色阶 11 档（§1.2，冷灰带 3% 青调）──────────────────────── */
  --gray-0:   #FFFFFF;
  --gray-25:  #FAFCFC;
  --gray-50:  #F5F7F8;   /* 页面背景 / 表头底 / 骨架底 */
  --gray-100: #EDF1F3;   /* 中性徽章底 / disabled 底 */
  --gray-200: #E1E7EA;   /* 描边默认 */
  --gray-300: #CCD6DB;   /* 控件描边 */
  --gray-400: #A3B0B7;   /* 禁用文字 / placeholder */
  --gray-500: #7A8B94;
  --gray-600: #5F7079;   /* 三级文字：表头 / label / 辅助（5.15 ✅） */
  --gray-700: #3F4F58;   /* 表格单元格正文 */
  --gray-800: #2C3A42;   /* 正文 */
  --gray-900: #16242B;   /* 标题 */

  /* ── 1.4 语义色：每个语义只 3 个值（文字 600 / 浅底 50 / 浅底描边 200）── */
  --success-600: #0B6B4F;  --success-50: #E6F6EF;  --success-200: #B9E3D2;
  --warning-600: #8A5A08;  --warning-50: #FCF3E2;  --warning-200: #F0D9A8;
  --danger-600:  #B42318;  --danger-50:  #FCECEA;  --danger-200:  #F3C6C1;
  --info-600:    #0C596D;  --info-50:    #EDF7FA;  --info-200:    #A9D9E5;
  /* 危险按钮 hover/active：取自 §2.5 按钮状态表（不是扩展色阶） */
  --danger-700: #9A1D13;
  --danger-800: #841A11;

  /* ── 1.5 字号 6 档 + 行高 6 档（§1.4 v1.1，行高一律固定 px）──────────
     12px 是全站下限，11px 档已删除（v1.1 裁决）。任何位置不得出现 < 12px 的字号。 */
  --fs-2xl: 28px;  --lh-2xl: 36px;
  --fs-xl:  20px;  --lh-xl:  28px;
  --fs-lg:  16px;  --lh-lg:  24px;
  --fs-md:  14px;  --lh-md:  22px;
  --fs-sm:  13px;  --lh-sm:  20px;
  --fs-xs:  12px;  --lh-xs:  18px;

  /* ── 1.6 间距 8 档（4px 基准，§1.5）─────────────────────────────────── */
  --sp-1:  4px;
  --sp-2:  8px;
  --sp-3:  12px;
  --sp-4:  16px;
  --sp-5:  20px;
  --sp-6:  24px;
  --sp-8:  32px;
  --sp-10: 40px;

  /* ── 1.7 圆角 6 档（§1.6）─────────────────────────────────────────── */
  --r-xs:   4px;
  --r-sm:   6px;
  --r-md:   8px;
  --r-lg:   10px;
  --r-xl:   12px;
  --r-full: 999px;

  /* ── 1.8 描边 2 档 ────────────────────────────────────────────────── */
  --bw-1: 1px;
  --bw-2: 2px;

  /* ── 1.9 阴影 5 个（带青调暗色，不用纯黑）──────────────────────────── */
  --shadow-1: 0 1px 2px 0 rgba(16, 36, 43, 0.06);
  --shadow-2: 0 4px 12px -2px rgba(16, 36, 43, 0.10);
  --shadow-3: 0 16px 40px -8px rgba(16, 36, 43, 0.18);
  --shadow-focus: 0 0 0 3px rgba(23, 135, 159, 0.20);
  --shadow-focus-danger: 0 0 0 3px rgba(180, 35, 24, 0.16);

  /* ── 1.10 动效 3 档 + 2 缓动 ──────────────────────────────────────── */
  --dur-fast: 120ms;
  --dur-base: 180ms;
  --dur-slow: 260ms;
  --ease-std: cubic-bezier(0.2, 0, 0.2, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);

  /* ── 1.11 布局 7 个 ───────────────────────────────────────────────── */
  --sidebar-w: 232px;
  --sidebar-w-collapsed: 64px;
  --topbar-h: 56px;
  --content-max: 1440px;
  --content-pad: 24px;
  --card-gap: 16px;
  --drawer-w: 252px;          /* XS 抽屉宽度（§1.6 响应式表） */

  /* ── 1.11.1 长表吸顶高度（§2.4.2 模式 B）────────────────────────────
     不写死 220px：工具栏折两行时可用高度会少 40px，算错就露出半截行。
     --table-chrome  = 顶栏 56 + 工具栏单行 64 + 卡片头 52 + 分页 48 ≈ 220
     --table-chrome-2row = 工具栏折两行时 260
     用法：长表容器加 class="table-wrap--tall table-wrap--tall-2row" */
  --table-chrome: 220px;
  --table-chrome-2row: 260px;
  --table-max-h: calc(100vh - var(--topbar-h) - var(--table-chrome));

  /* ── 1.12 层级 5 个 ───────────────────────────────────────────────── */
  --z-sidebar: 30;
  --z-topbar: 20;
  --z-dropdown: 60;
  --z-modal: 100;
  --z-toast: 200;

  /* ── 1.13 遮罩与骨架（两处固定值，集中定义避免散落）────────────────── */
  --mask: rgba(8, 28, 35, 0.48);
  --font-sans: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei",
               "Hiragino Sans GB", "Segoe UI", Roboto, sans-serif;
}


/* =============================================================================
   §2  旧变量别名层
   -----------------------------------------------------------------------------
   ⚠ 不可删。模板里大量内联 style="…var(--border)…" 直接引用旧变量名，
   删掉不会报错，只会静默失效（按钮变透明 / 文字变黑），是最典型的"改完就出事故"。
   覆盖面：--border --text-muted --primary --text --danger --bg
           --badge-info-text/bg --success --primary-hover --card-bg
           --badge-success-text/bg --danger-hover --badge-warn-text/bg
   刀 3 把内联样式收敛进组件类后，本段可整段删除。
   ========================================================================== */
:root {
  --primary:        var(--teal-600);
  --primary-hover:  var(--teal-700);
  --danger:         var(--danger-600);
  --danger-hover:   var(--danger-700);
  --success:        var(--success-600);
  --text:           var(--gray-800);
  --text-muted:     var(--gray-600);
  --border:         var(--gray-200);
  --bg:             var(--gray-50);
  --card-bg:        var(--gray-0);
  --badge-success-bg:   var(--success-50);
  --badge-success-text: var(--success-600);
  --badge-warn-bg:      var(--warning-50);
  --badge-warn-text:    var(--warning-600);
  --badge-info-bg:      var(--info-50);
  --badge-info-text:    var(--info-600);
}


/* =============================================================================
   §3  基础重置与全局排版
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--fs-md);
  line-height: var(--lh-md);
  color: var(--gray-800);
  background: var(--gray-50);
  font-variant-numeric: tabular-nums;   /* 表格/统计数字等宽（§1.4） */
  -webkit-text-size-adjust: 100%;
}

h1, h2, h3, h4, h5, h6 { margin: 0; color: var(--gray-900); font-weight: 600; }
p  { margin: 0; }
ul, ol { margin: 0; padding: 0; }
img { max-width: 100%; }
button, input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }

a { color: var(--teal-700); text-decoration: none; }
a:hover { text-decoration: underline; }

/* 统一聚焦：用 box-shadow 代替 outline，避免键鼠混用时焦点环突兀（§1.6） */
:focus { outline: none; }
:focus-visible {
  outline: none;
  border-color: var(--teal-600);
  box-shadow: var(--shadow-focus);
}

/* 原生控件跟随主色（§4.5 只读矩阵用 accent-color，零成本上色） */
input[type="checkbox"], input[type="radio"] {
  width: 15px; height: 15px;
  accent-color: var(--teal-600);
  cursor: pointer;
  vertical-align: middle;
  margin: 0 4px 0 0;
}
input[type="checkbox"]:disabled, input[type="radio"]:disabled { cursor: not-allowed; }

::selection { background: var(--teal-100); color: var(--gray-900); }

/* 滚动条美化（8px 细条，比系统默认的 15px 更"仪器感"） */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--gray-300);
  border-radius: var(--r-full);
}
::-webkit-scrollbar-thumb:hover { background: var(--gray-400); }
::-webkit-scrollbar-corner { background: transparent; }

/* 动效纪律：用户要求减少动态时全部关掉（§1.6） */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}


/* =============================================================================
   §4  骨架：.app / .sidebar / .topbar / .content
   -----------------------------------------------------------------------------
   关键结构性约定（改坏这里会连带 21 个页面）：
   · .app 高度锁 100vh 且 overflow:hidden；html/body 不滚；
   · .content 是**唯一滚动容器**（Phase 2 §1.1 关键改动 2）。表头 sticky、
     批量条吸顶、卡片内 sticky 左栏都依赖这一点；
   · 宽屏（≥1600）用 .content > * 的 max-width 居中收口，不动 .content 自身，
     这样滚动条仍贴在窗口右缘，不会跑到 1440px 处（审计：宽屏被拉成一片）。
   ========================================================================== */
.app {
  display: flex;
  height: 100vh;
  overflow: hidden;
  background: var(--gray-50);
}

/* ── 侧边栏（232px 深空面，§2.1）──────────────────────────────────────── */
.sidebar {
  width: var(--sidebar-w);
  flex: none;
  height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--teal-900);
  color: var(--ink-text);
  z-index: var(--z-sidebar);
  transition: width var(--dur-base) var(--ease-std);
}

.sidebar-logo {
  height: 60px;
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 0 10px;
  border-bottom: var(--bw-1) solid var(--ink-line);
  color: #FFFFFF;
  font-size: var(--fs-md);
  line-height: var(--lh-md);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 企业自定义 LOGO（刀 2：cache.brandConfig.item.logoUrl）
   统一 24px 方形槽位 + contain，避免用户传竖图把 60px 顶栏撑破 */
.sidebar-logo .logo-img {
  flex: none;
  width: 24px;
  height: 24px;
  border-radius: var(--r-xs);
  object-fit: contain;
  background: rgba(255, 255, 255, 0.08);
}
.sidebar-logo > .ico { flex: none; width: 24px; height: 24px; color: var(--ink-bright); }
.sidebar-logo .logo-text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar-nav {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: var(--sp-2) var(--sp-3);
}
.sidebar-nav::-webkit-scrollbar { width: 8px; }
.sidebar-nav::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.12); }
.sidebar-nav::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.24); }

/* 分组标题（§2.1 v1.1：12px/500 --ink-group #7E97A1，不加粗、不大写、不画线）
   12px 是全站下限（11px 档已删）；0.06em 字距是侧边栏中文唯一允许加字距的地方。 */
.nav-group-title {
  height: 28px;
  display: flex;
  align-items: center;
  padding: 0 10px;
  margin-top: var(--sp-3);
  font-size: var(--fs-xs);
  line-height: var(--lh-xs);
  font-weight: 500;
  color: var(--ink-group);
  letter-spacing: 0.06em;
  user-select: none;
}

/* 导航项三态（§2.1，禁止彩色左边框条） */
.nav-item {
  height: 36px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 10px;
  margin-bottom: 2px;
  border-radius: var(--r-md);
  font-size: var(--fs-md);
  line-height: var(--lh-md);
  color: var(--ink-text);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  overflow: hidden;
  transition: background-color var(--dur-fast) var(--ease-std),
              color var(--dur-fast) var(--ease-std);
}
.nav-item:hover { background: var(--ink-hover-bg); color: var(--ink-strong); }
.nav-item:focus-visible { box-shadow: 0 0 0 2px var(--ink-bright); }

/* 选中 = 实色浮块 + 字重升级 + 极细内描边环（三重信号，非边框条） */
.nav-item.active {
  background: var(--ink-active-bg);
  color: #FFFFFF;
  font-weight: 600;
  box-shadow: inset 0 0 0 1px var(--ink-ring);
}

/* 图标位：刀 1 模板里是 emoji <span>，刀 2 换 <svg class="ico">，两者都按 18px 槽位对齐 */
.nav-item > span:first-child {
  flex: none;
  width: 18px;
  text-align: center;
  font-size: 15px;
  line-height: 1;
  color: var(--ink-icon);
}
.nav-item.active > span:first-child { color: var(--ink-bright); }
.nav-item > span:last-child {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.nav-item .ico { width: 18px; height: 18px; }

/* 刀 2 起导航图标是 <svg class="ico"><use/></svg>，文字是 <span class="nav-text">。
   两者与 emoji 时代共用同一 18px 槽位；图标颜色走 --ink-icon，选中转 --ink-bright。
   ⚠ <use> 不会继承宿主 <svg> 上的 presentation 属性，颜色只能靠 color 继承。 */
.nav-item > .ico { flex: none; color: var(--ink-icon); }
.nav-item:hover > .ico { color: var(--ink-strong); }
.nav-item.active > .ico { color: var(--ink-bright); }
.nav-item .nav-text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 折叠态的分组分隔线（刀 2 渲染，桌面隐藏）：分组标题在 64px 下压成竖排是最丑的死法，
   所以折叠态把"标题"换成"1px 分隔线"，信息不丢失、只是换了载体（layout-spec §1.4）。
   只出现在组与组之间，第一组上面不画（由 MENU_GROUPS 的 rendered>0 判断）。 */
.nav-group-sep {
  display: none;
  height: 1px;
  margin: var(--sp-2) 10px;
  background: var(--ink-line);
}

.sidebar-footer {
  flex: none;
  min-height: 56px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  padding: var(--sp-2) 10px;
  border-top: var(--bw-1) solid var(--ink-line);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--ink-strong);
  overflow: hidden;
}
.sidebar-footer a { color: var(--ink-group); font-size: var(--fs-xs); }
.sidebar-footer a:hover { color: var(--ink-strong); text-decoration: none; }

/* ── 主区与顶栏（§2.2）───────────────────────────────────────────────── */
.main-area {
  flex: 1;
  min-width: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.topbar {
  flex: none;
  height: var(--topbar-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: 0 var(--sp-6);
  background: var(--gray-0);
  border-bottom: var(--bw-1) solid var(--gray-200);
  position: sticky;
  top: 0;
  z-index: var(--z-topbar);
}
/* 页面标题：全页唯一的一级标题（Phase 2 §1.1 关键改动 1） */
.topbar h1,
.topbar h2,
.topbar .page-title {
  margin: 0;
  font-size: var(--fs-xl);
  line-height: var(--lh-xl);
  font-weight: 600;
  color: var(--gray-900);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 唯一滚动容器（Phase 2 §1.1 关键改动 2） */
.content {
  flex: 1;
  min-height: 0;
  padding: var(--content-pad);
  overflow: auto;
  background: var(--gray-50);
}
/* ≥1600 宽屏收口：只约束直接子元素，滚动条仍在窗口右缘 */
@media (min-width: 1600px) {
  .content > * {
    max-width: var(--content-max);
    margin-left: auto;
    margin-right: auto;
  }
}

/* 内容内层（刀 2：id="pageContent" 挂在这一层，.content 上不能有同名 id）
   ⚠ 绝对不要给 .content-inner 加 overflow：话术工作台的 sticky AI 面板依赖
   .content 作为唯一滚动容器，这里一旦成为滚动容器，sticky 面板立刻失效。 */
.content-inner { min-width: 0; }
@media (min-width: 1600px) {
  .content > .content-inner > * {
    max-width: var(--content-max);
    margin-left: auto;
    margin-right: auto;
  }
}

/* ── 顶栏内部（刀 2 结构，刀 1 预留）───────────────────────────────── */
.topbar-left {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
}
.topbar-right {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex: none;
  margin-left: auto;
}
/* 顶栏"定位行"：分组名 · 页面标题（§2.2 layout-spec v1.2）
   单行、基线对齐、gap 8px；两级同色、无 hover、无下划线、不设 cursor:pointer。
   结构：h1.page-title > span.crumb-group + span.crumb-sep + span.crumb-title */
.page-title { display: flex; align-items: baseline; gap: var(--sp-2); min-width: 0; }
.crumb-group {
  font-size: var(--fs-xs);
  line-height: 16px;
  color: var(--gray-600);
  font-weight: 400;
  white-space: nowrap;
}
.crumb-sep {
  font-size: var(--fs-xs);
  line-height: 16px;
  color: var(--gray-600);
  padding: 0 2px;
}
/* 只有分组名 + 页面标题在同一行时才用中点；这里给行内组合写法留位 */
.crumb-group--inline { display: inline-flex; align-items: center; }
.topbar .page-title > .crumb-title {
  font-size: var(--fs-xl);
  line-height: 28px;
  font-weight: 600;
  color: var(--gray-900);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 用户名：过长省略，不把顶栏挤成两行（XS 直接隐藏，只留头像 + 角色） */
.user-trigger .user-name {
  max-width: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--gray-800);
}
@media (max-width: 767px) {
  .user-trigger .user-name { display: none; }
  .topbar .page-title > .crumb-title { font-size: var(--fs-lg); line-height: var(--lh-lg); }
  .topbar .page-title .crumb-group { display: none; }
  .topbar .page-title .crumb-sep { display: none; }
}
/* 汉堡按钮：仅 XS 显示（刀 2 由 toggleSidebar() 切换 aria-expanded）。
   ⚠ .icon-btn 的 display:inline-flex 在文件更靠后，会盖掉单类名的 display:none，
   所以这里必须用两类的合写选择器压住它。 */
.topbar-burger,
.icon-btn.topbar-burger,
.btn-icon.topbar-burger { display: none; }
@media (max-width: 767px) {
  .topbar-burger,
  .icon-btn.topbar-burger,
  .btn-icon.topbar-burger { display: inline-flex; }
}

/* 顶栏用户菜单：原生 <details>，零 JS */
.user-menu { position: relative; }
.user-trigger {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  height: 36px;
  padding: 0 var(--sp-2);
  border: var(--bw-1) solid transparent;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--gray-800);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.user-trigger::-webkit-details-marker { display: none; }
.user-trigger:hover { background: var(--gray-100); }
.user-menu[open] > .user-trigger { background: var(--gray-100); border-color: var(--gray-200); }
.user-trigger .badge { margin-left: 2px; }
.user-trigger .chev { width: 14px; height: 14px; color: var(--gray-600); flex: none; }
.user-menu > .dropdown-menu { right: 0; }
/* 2026-10-19 修复：用户菜单是原生 <details> 展开，但 .dropdown-menu 基础样式 display:none
   只配了 .dropdown.open（JS 方式）的显示规则——details 打开后菜单仍隐藏，表现为"点了没反应" */
.user-menu[open] > .dropdown-menu { display: block; }

/* 移动端抽屉（<768 时 sidebar 变为抽屉，由 .sidebar.open 控制） */
.sidebar-mask {
  position: fixed;
  inset: 0;
  background: var(--mask);
  z-index: calc(var(--z-sidebar) - 1);
  display: none;
}
.sidebar-mask.open { display: block; }

/* 面包屑（可选，刀 1 未渲染，预留） */
.breadcrumb { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-xs); color: var(--gray-600); }
.breadcrumb > *:last-child { color: var(--gray-800); }


/* =============================================================================
   §5  容器：卡片 / KPI
   ========================================================================== */
.card {
  background: var(--gray-0);
  border: var(--bw-1) solid var(--gray-200);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  margin-bottom: var(--sp-4);
  /* ⚠ 不要加 overflow:hidden：一旦成为滚动容器，表头 sticky 会退化为"相对卡片"而失效 */
}
.card:last-child { margin-bottom: 0; }

.card-header {
  min-height: 52px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-5);
  border-bottom: var(--bw-1) solid var(--gray-200);
}
/* 卡片标题：14px/600（旧值 15px 是 §1.4 明令禁止的"自造字号"） */
.card-header h2,
.card-header h3,
.card-header h4 {
  margin: 0;
  font-size: var(--fs-md);
  line-height: var(--lh-md);
  font-weight: 600;
  color: var(--gray-900);
}
/* 副标题：与标题同行、间距 8px、基线对齐 */
.card-header .sub,
.card-header .card-sub {
  font-size: var(--fs-xs);
  line-height: var(--lh-xs);
  color: var(--gray-600);
  font-weight: 400;
  margin-left: var(--sp-2);
}
/* 卡片头右侧动作区：最多 2 个按钮 + 1 个「更多 ⋯」（§2.3） */
.card-header .btn-bar { margin: 0; }

.card-pad,
.card-body { padding: var(--sp-5); }

/* 通栏卡片：表格/分页贴边，不吃 20px 内边距（Phase 2 §1.1 关键改动 3） */
.card-flush > .card-header { border-bottom: var(--bw-1) solid var(--gray-200); }
.card-flush > .table-wrap,
.card-flush > table { width: 100%; }
.card-flush > .pagination { border-top: var(--bw-1) solid var(--gray-200); }
.card-flush > .card-pad:first-child { padding-top: 0; }

/* 可点击卡片：只改 shadow + border-color，不上浮、不缩放（§4-8） */
.card.card-hover:hover { box-shadow: var(--shadow-2); border-color: var(--gray-300); }

/* ── KPI 卡（§2.3 / Phase 2 §4.3）────────────────────────────────────── */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: var(--card-gap);
}
.stat-card {
  position: relative;
  background: var(--gray-0);
  border: var(--bw-1) solid var(--gray-200);
  border-radius: var(--r-lg);
  padding: var(--sp-5);
  box-shadow: var(--shadow-1);
  transition: box-shadow var(--dur-base) var(--ease-std),
              border-color var(--dur-base) var(--ease-std);
}
.stat-card:hover { box-shadow: var(--shadow-2); border-color: var(--gray-300); }

.stat-card .stat-label,
.stat-label {
  font-size: var(--fs-xs);
  line-height: var(--lh-xs);
  color: var(--gray-600);
  margin-bottom: var(--sp-2);
}
.stat-card .stat-value {
  font-size: var(--fs-2xl);
  line-height: var(--lh-2xl);
  font-weight: 600;
  color: var(--gray-900);
  font-variant-numeric: tabular-nums;
}
/* 空值降档（§1.4：数字为空时降为 14px + gray-600，现有做法正确，保留） */
.stat-card .stat-value.empty-text {
  font-size: var(--fs-md);
  line-height: var(--lh-md);
  font-weight: 400;
  color: var(--gray-600);
}
.stat-card .stat-icon,
.stat-icon {
  position: absolute;
  top: var(--sp-4);
  right: var(--sp-4);
  font-size: 20px;
  line-height: 1;
  color: var(--teal-500);
  opacity: 0.35;          /* 装饰性，不抢数字（替代旧 float:right 24px 实色 emoji） */
}
/* 工作台用紧凑档：数字 20px（概览不是报表，§6 工作台） */
.stat-card--compact { padding: var(--sp-4) var(--sp-5); }
.stat-card--compact .stat-value { font-size: var(--fs-xl); line-height: var(--lh-xl); }

/* 工作台旧组件：.overview-grid/.overview-item 保留为 KPI 卡的别名，
   Phase 2 计划合并到 .stat-grid/.stat-card；刀 1 不改 JS，故必须继续有样式，
   否则工作台首屏 6 张卡会塌成裸 div。刀 3 合并后可删。 */
.overview-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: var(--card-gap);
  margin-bottom: var(--card-gap);
}
.overview-item {
  background: var(--gray-0);
  border: var(--bw-1) solid var(--gray-200);
  border-radius: var(--r-lg);
  padding: var(--sp-4) var(--sp-5);
  box-shadow: var(--shadow-1);
}
.overview-item .label {
  font-size: var(--fs-xs);
  line-height: var(--lh-xs);
  color: var(--gray-600);
  margin-bottom: var(--sp-2);
}
.overview-item .value {
  font-size: var(--fs-xl);
  line-height: var(--lh-xl);
  font-weight: 600;
  color: var(--gray-900);
  font-variant-numeric: tabular-nums;
}


/* =============================================================================
   §6  表格
   -----------------------------------------------------------------------------
   §2.4 审计缺陷 1：7 处模板用 class="table"，旧 CSS 完全没有 .table 规则。
   方案：.table 与 .data-table 共用同一套选择器（不动模板）。
   ───────────────────────────────────────────────────────────────────────────
   ⚠ v1.1 修正（原规范写错，务必按新版）：表头 sticky 分两种模式，不能一把梭。

   为什么：`overflow-x: auto` 会让另一轴的 visible 被计算成 auto，所以 .table-wrap
   一开横向滚动，它自己就成了**两个方向**的滚动容器。此时 `thead th{position:sticky}`
   的参照是 .table-wrap 的 scrollport，而不是 .content；而 .table-wrap 若不限高就永远
   不纵向滚动 → sticky 完全无效，长表往下滚时表头会跟页面一起滚走。

   模式 A（默认，行数 < 15）：.table-wrap 只负责横滚，**表头不加 sticky**。
   模式 B（长表，行数 ≥ 15）  ：.table-wrap--tall，受限高度 + 双向滚动 →
                                此时才对 thead th 和"操作列（末列）"加 sticky。

   连带三条（缺了会出"透视"）：
   ① 分页必须放在 .table-wrap 外面，否则跟着一起滚走；
   ② sticky 单元格背景必须不透明，且 hover 时要单独覆盖；
   ③ 表头与操作列的交叉格 z-index 要高于两者。

   另：.card 不能加 overflow:hidden（会二次制造滚动容器，sticky 全废）；
       行分隔线一律画在 td 自己身上（配合 border-collapse:separate）。
   ========================================================================== */

/* ── 模式 A：只横滚（默认，短表）────────────────────────────────────── */
.table-wrap {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* ── 模式 B：长表吸顶（行数 ≥ 15 才加；话术管理/回复日志/员工日志/图库）──
   用法：<div class="table-wrap table-wrap--tall">…
   工具栏折两行时再加 .table-wrap--tall-2row 把可用高度扣掉 40px。 */
.table-wrap--tall {
  width: 100%;
  max-height: var(--table-max-h);
  overflow: auto;
  -webkit-overflow-scrolling: touch;
}
.table-wrap--tall.table-wrap--tall-2row {
  max-height: calc(100vh - var(--topbar-h) - var(--table-chrome-2row));
}

/* 长表：表头吸顶 */
.table-wrap--tall thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--gray-50);
}
/* 长表：末列（操作列）吸右，必须不透明，否则会透出底层文字 */
.table-wrap--tall th:last-child,
.table-wrap--tall td:last-child {
  position: sticky;
  right: 0;
  z-index: 3;
  background: var(--gray-0);
  border-left: var(--bw-1) solid var(--gray-200);
}
/* 交叉格（表头 × 末列）要压过两者 */
.table-wrap--tall thead th:last-child { z-index: 4; }
/* hover 时末列单独覆盖，保持行高亮连续（不做这步会出现"操作列不变色"的断口） */
.table-wrap--tall tbody tr:hover > td:last-child { background: var(--gray-25); }

/* ── 修复：行内 ⋯ 菜单被后续行的 sticky 操作列盖住 ──────────────────────
   根因：td:last-child 的 position:sticky + z-index:3 创建层叠上下文，
   把 .dropdown-menu(z-index:60) 困在本行 td 内；后续行同样是 z-index:3
   且 DOM 靠后 → 后行操作列（编辑/⋯ 按钮）盖住展开的菜单。
   对策：本行操作列里有展开的 details.dropdown 时，把该 td 提到 z-index:5。
   项目已依赖 :has()（见下方 .card-pad:has(> table)），此处同规格。 */
.table-wrap--tall td:last-child:has(details.dropdown[open]) { z-index: 5; }

/* 兼容别名：早期命名，等价于 --tall */
.table-wrap--vscroll { max-height: var(--table-max-h); overflow: auto; }
.table-wrap--vscroll thead th { position: sticky; top: 0; z-index: 2; background: var(--gray-50); }

/* ── 表格主体（.table 与 .data-table 完全等价）────────────────────────── */
.table,
.data-table {
  width: 100%;
  min-width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  table-layout: auto;      /* 显式声明：绝不使用 fixed，否则长文本列会被压缩 */
}
/* 长表（话术管理 7 列）：总宽 964 = 32 + 260 + 168 + 140 + 76 + 128 + 160
   不横滚门槛：视口 ≥ 1246（964 + 侧边栏 232 + 内容 padding 48）。
   1280 宽应无横滚条；1200 宽有横滚条属正常，不要为消掉它去压列宽。 */
.table--wide { min-width: 964px; }

/* ── 窄容器最小宽度兜底（v1.1 硬伤修复 · 820 竖排字）───────────────────
   现象：820 宽下 8~11 列的表被"自适应"到每列 60px，「价格太贵的应对话术」
        竖排成 5 行；用户读到的是一列字，不是一行数据。
   根因：table-layout:auto 没有列宽下限，中文可以在任意字符处断行，
        于是浏览器把列压到"最窄能放下一个字"。
   修法：给 <table> 兜最小宽度，让表格**宁可溢出横滚，也不压字**。
   ⚠ td 上的 min-width 在 auto 布局下不生效，必须写在 table 上。
   ⚠ 真实模板里表格有两种落位，两种都得兜：
      · .table-wrap 内（新写法，容器自己横滚）
      · .card-pad / .card-body 直挂（旧写法 12 处：phrase.js:208、
        activitylog.js:110、member.js:48、copywriting.js:188…）
   横滚条由容器负责：.table-wrap 本来就有 overflow-x:auto；
   .card-pad 的横滚见本节末尾"卡片承载表格时自己横滚"。 */
.table-wrap > .table,
.table-wrap > .data-table,
.card-pad > .table,
.card-pad > .data-table,
.card-body > .table,
.card-body > .data-table { min-width: 720px; }

/* 宽表（7 列以上）用 964（§2.4 定稿列宽总和，标题列 260） */
.table--wide,
.table-wrap > .table--wide,
.card-pad > .table--wide,
.card-body > .table--wide { min-width: 964px; }

/* 卡片直接承载表格时自己横滚（≥1024 也要，否则表格会顶破卡片右边界，
   进而把整个 .content 拖成横向滚动）。用 :has() 精确命中，避免给所有
   .card-pad 都套一个滚动容器（那会裁掉绝对定位的下拉/浮层）。
   :has() = Edge/Chrome 105+；不支持时这条整体失效，由 ≤1023 的宽规则兜底。 */
.card-pad:has(> table),
.card-body:has(> table) { overflow-x: auto; }

.table thead th,
.data-table thead th {
  height: 40px;
  padding: 10px var(--sp-4);
  background: var(--gray-50);
  color: var(--gray-600);
  font-size: var(--fs-xs);
  line-height: var(--lh-xs);
  font-weight: 500;
  text-align: left;
  white-space: nowrap;     /* 表头永不折行 */
  border: 0;
  border-bottom: var(--bw-1) solid var(--gray-200);
}

.table tbody td,
.data-table tbody td {
  height: 48px;
  padding: 14px var(--sp-4);
  color: var(--gray-700);
  vertical-align: middle;
  border: 0;
  border-bottom: var(--bw-1) solid var(--gray-200);
}

/* ── 单元格折行策略（v1.1 硬伤修复 · 更新时间折行）─────────────────────
   现象：1440 截图里「更新时间」渲染成「2026-10-」/「17」两行。
   日期、数字、徽章、分类这类短值是"原子值"，一折行就是肉眼可见的错版，
   所以 tbody td 打底 nowrap；长文本列（标题/内容/描述）才允许折行。
   三个逃生口（刀 1 不改 JS，先把钩子留好，刀 3 补类）：
   ① .cell-text / .cell-wrap —— 允许折行（配 .cell-clamp-2 限两行）
   ② td:first-child 放宽到 320px（标题列是最常被用来定位行的一列）
   ③ 其余纯文本单元格 260px ≈ 20 个汉字后省略号，避免整表被拉到 3000px */
.table tbody td,
.data-table tbody td { white-space: nowrap; }

.cell-text,
.cell-wrap,
.cell-clamp-2,
.cell-clamp-3 { white-space: normal; }

/* 只裁"纯文本"单元格（:has(*) 排除含徽章/按钮/复选框/缩略图的格子，
   否则多标签单元格会被裁掉半个徽章）。:has() 不支持时本段整体失效，
   退化为"表格更宽但文字完整"，不会错版。 */
.table tbody td:not(:has(*)),
.data-table tbody td:not(:has(*)) {
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
}
.table tbody td:first-child:not(:has(*)),
.data-table tbody td:first-child:not(:has(*)) { max-width: 320px; }

/* 数字列 / 徽章列永不折行（即便有人后面加了白名单类，也压不回来） */
.table td.num,
.data-table td.num { white-space: nowrap; }
.table tbody tr:last-child td,
.data-table tbody tr:last-child td { border-bottom: 0; }

/* 行 hover：不用斑马纹（§2.4：与 sticky 操作列冲突、hover 反而看不出） */
.table tbody tr:hover > td,
.data-table tbody tr:hover > td { background: var(--gray-25); }

/* 首列 = 行锚点：medium 字重 + 深一档正文色 */
.table tbody td:first-child,
.data-table tbody td:first-child {
  font-weight: 500;
  color: var(--gray-700);
}

/* ── 双行单元格（§2.4.3 v1.1 定稿：行高 60px）─────────────────────────
   算式：主行 22 + 副行 18 + 上下 padding 10 + 10 = 60
   两条跨列对齐死规矩：
   ① 同一行内所有列的第 1 行必须都是 14/22，第 2 行必须都是 12/18；
      任何一列写成 13/20 都会让相邻列基线差 2px，整行看起来是歪的。
   ② 某列没有副行时必须补 18px 占位（<span class="sub">&nbsp;</span> 或 min-height），
      否则该单元格只有 42px，行高由最高单元格撑开，同排基线立刻错位。 */
.table-2line tbody td {
  padding: 10px var(--sp-4);
  font-size: var(--fs-md);
  line-height: var(--lh-md);      /* 14 / 22 */
  vertical-align: top;
}
.table-2line tbody td > .sub,
.table-2line tbody td .cell-sub {
  display: block;
  min-height: 18px;               /* 无副行时的占位，保证跨列基线对齐 */
  font-size: var(--fs-xs);
  line-height: var(--lh-xs);      /* 12 / 18 */
  color: var(--gray-600);
  font-weight: 400;
}
.table-2line tbody td:first-child {
  font-weight: 600;
  color: var(--gray-900);
}

/* ── 空结果行（筛选后无匹配时用）─────────────────────────────────────────
   首次无数据 → 不渲染 <thead>，整块三段式空态；
   筛选无结果 → **保留表头**，表体一行"没有匹配的结果" + 清除筛选。
   <td colspan> 只能用在这个场景，禁止用一行灰字冒充"整表无数据"。 */
.row-empty td,
.empty-row td,
.table tbody tr.row-empty:hover > td {
  height: 120px;
  padding: var(--sp-10) var(--sp-4);
  text-align: center;
  vertical-align: middle;
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--gray-600);
  background: var(--gray-0);       /* 压掉 hover 底色 */
}
.row-empty .btn-text,
.empty-row .btn-text { margin-left: var(--sp-2); }

/* 数字列 / 操作列 / 长文本列 */
.table th.num, .data-table th.num,
.table td.num, .data-table td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.table td.row-actions,
.data-table td.row-actions,
.row-actions {
  text-align: right;
  white-space: nowrap;
}
.row-actions .btn { margin-right: var(--sp-1); }
.row-actions .btn:last-child,
.row-actions > *:last-child { margin-right: 0; }
.row-actions:empty { display: none; }

.cell-clamp-2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  word-break: break-word;
}

/* 单元格内的徽章/复选框与文字基线对齐 */
.table td .badge,
.data-table td .badge { vertical-align: middle; }
.table td input[type="checkbox"],
.data-table td input[type="checkbox"] { margin: 0; }

/* 表格密度三档（§2.4） */
.table-compact thead th { padding: 8px var(--sp-3); }
.table-compact tbody td { height: 40px; padding: 10px var(--sp-3); }

.table-comfortable thead th { padding: 10px var(--sp-4); }
.table-comfortable tbody td { height: 60px; padding: 18px var(--sp-4); }

/* 表格内缩略图（phrase-thumb / asset-thumb / copywriting-thumb）
   尺寸由内联 style 决定（40/56px），这里只统一裁切与占位底色 */
.phrase-thumb,
.asset-thumb,
.copywriting-thumb {
  display: block;
  object-fit: cover;
  background: var(--gray-100);
  border-radius: var(--r-xs);
  border: var(--bw-1) solid var(--gray-200);
}

/* ── 角色权限矩阵（T2b，Phase 2 §4.5）────────────────────────────────── */
.perm-matrix {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
}
.perm-matrix thead th {
  height: 40px;
  padding: 8px var(--sp-3);
  background: var(--gray-50);
  color: var(--gray-600);
  font-size: var(--fs-xs);
  font-weight: 500;
  text-align: center;
  white-space: nowrap;
  border: 0;
  border-bottom: var(--bw-1) solid var(--gray-200);
  /* 表头吸顶只在 .table-wrap--tall 下启用（见 §6 开头 v1.1 说明），
     这里不加 position:sticky —— 无限高容器里的 sticky 只会"什么都不做"。 */
}
.perm-matrix thead th:first-child { text-align: left; }
.perm-matrix tbody td {
  padding: 8px var(--sp-3);
  text-align: center;
  border: 0;
  border-bottom: var(--bw-1) solid var(--gray-200);   /* 只留横线，删掉竖线棋盘（§4.5） */
  color: var(--gray-700);
}
.perm-matrix tbody tr:last-child td { border-bottom: 0; }
.perm-matrix tbody tr:hover > td { background: var(--gray-25); }

/* 首列吸左：仅在矩阵处于横向滚动容器内时生效，否则无副作用 */
.perm-matrix td.role-name,
.perm-matrix th.role-name,
.perm-matrix .role-name {
  text-align: left;
  font-weight: 500;
  color: var(--gray-900);
  background: var(--gray-0);
  position: sticky;
  left: 0;
  z-index: 1;
  white-space: nowrap;
}
.role-name { font-weight: 500; }
.perm-matrix input[type="checkbox"] { width: 16px; height: 16px; }
/* 矩阵只有放进长表容器时才吸顶（此时表头吸上、首列吸左，交叉格压最高） */
.table-wrap--tall .perm-matrix thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--gray-50);
}
.table-wrap--tall .perm-matrix thead th:first-child { z-index: 4; }

/* 批量勾选列（pcat-check 等）—— 纯 JS 选择器 + 原生复选框，只补光标 */
.pcat-check,
.batch-tag,
.pi-member,
.pi-tag,
.pm-member { cursor: pointer; accent-color: var(--teal-600); }


/* =============================================================================
   §7  按钮（§2.5）
   -----------------------------------------------------------------------------
   字重统一 500（600 在 14px 中文上显笨，400 压不住实色底）。
   高度用 min-height + line-height，保证内联 padding 的老按钮（登录页 12px）不塌。
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 36px;
  padding: 0 14px;
  border: var(--bw-1) solid transparent;   /* 预留：让有/无描边变体高度一致 */
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--gray-800);
  font-size: var(--fs-md);
  line-height: var(--lh-md);
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  vertical-align: middle;
  transition: background-color var(--dur-fast) var(--ease-std),
              border-color var(--dur-fast) var(--ease-std),
              color var(--dur-fast) var(--ease-std),
              box-shadow var(--dur-fast) var(--ease-std);
}
.btn:active { transition-duration: 0; }
.btn .ico { width: 16px; height: 16px; flex: none; }

/* md 默认尺寸的 3 个变体 */
.btn-primary {
  background: var(--teal-600);
  color: #FFFFFF;
  border-color: transparent;
}
.btn-primary:hover { background: var(--teal-700); }
.btn-primary:active { background: var(--teal-800); }

/* secondary = 白底描边（旧 .btn-ghost 的"描边按钮"角色由它接管） */
.btn-secondary {
  background: var(--gray-0);
  color: var(--gray-800);
  border-color: var(--gray-300);
}
.btn-secondary:hover { background: var(--gray-50); border-color: var(--gray-400); }
.btn-secondary:active { background: var(--gray-100); }

/* ghost = 无底无描边的轻量按钮（§2.5）
   这是本轮改版的核心取舍：模板里 147 处 btn-ghost 绝大多数在工具栏/卡片头，
   属于次要操作。旧版一律给描边，导致一屏 6 个描边按钮、主次完全平权。
   改为纯文字后主按钮才真正突出，代价是必须补两条可点性提示：
   ① hover 有 --gray-100 浅底 + 文字转 --gray-800（否则用户感知不到可点）；
   ② 内边距 8px（不是 14px），相邻 ghost 的间距由 .btn-bar 的 gap:8px 提供，
      文字间距 = 8 + 8 + 8 = 24px，不会糊成一串字。 */
.btn-ghost {
  padding: 0 var(--sp-2);
  background: transparent;
  color: var(--gray-600);
  border-color: transparent;
}
.btn-ghost:hover { background: var(--gray-100); color: var(--gray-800); }
.btn-ghost:active { background: var(--gray-200); }
/* sm 档跟着收到 8px（.btn-sm 的 10px 会把上面的取舍抵消掉） */
.btn-ghost.btn-sm,
.btn-ghost.btn-xs { padding: 0 var(--sp-2); }

.btn-danger {
  background: var(--danger-600);
  color: #FFFFFF;
  border-color: transparent;
}
.btn-danger:hover { background: var(--danger-700); }
.btn-danger:active { background: var(--danger-800); }

/* 文字按钮：无底、主色文字，用于"编辑/查看/标记完成"这类行内动作。
   内边距 4px（不是 8px）：相邻文字按钮的视觉间距靠容器 gap 8px 凑，
   否则两个「编辑 / 删除」贴成一条，看不出是两个可点目标。 */
.btn-text {
  background: transparent;
  color: var(--teal-700);
  border-color: transparent;
  padding: 0 var(--sp-1);
}
.btn-text:hover { background: var(--teal-50); color: var(--teal-800); }
.btn-text:active { background: var(--teal-100); }

.btn-text-danger {
  background: transparent;
  color: var(--danger-600);
  border-color: transparent;
  padding: 0 var(--sp-1);
}
.btn-text-danger:hover { background: var(--danger-50); color: var(--danger-700); }
.btn-text-danger:active { background: var(--danger-200); }

/* 整行按钮（登录页 / 改密页提交）：宽 100% + 高 40px，
   取代模板里的内联 style="width:100%;padding:12px" */
.btn-block {
  display: flex;
  width: 100%;
  min-height: 40px;
  padding: 0 var(--sp-4);
}

/* 尺寸档 */
.btn-sm {
  min-height: 30px;
  padding: 0 10px;
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
}
.btn-sm .ico { width: 14px; height: 14px; }

.btn-xs {
  min-height: 24px;
  padding: 0 var(--sp-2);
  font-size: var(--fs-xs);
  line-height: var(--lh-xs);
  border-radius: var(--r-xs);
}
.btn-xs .ico { width: 12px; height: 12px; }

/* 纯图标按钮（32×32），两个类名等价：.btn-icon 是 Phase 1 写法，.icon-btn 是清单写法 */
.btn-icon,
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  min-height: 0;
  padding: 0;
  flex: none;
  border: var(--bw-1) solid transparent;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--gray-600);
  font-size: var(--fs-md);
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-std),
              color var(--dur-fast) var(--ease-std);
}
.btn-icon:hover,
.icon-btn:hover { background: var(--gray-100); color: var(--gray-800); }
.btn-icon .ico,
.icon-btn .ico { width: 16px; height: 16px; }

/* disabled：统一"浅底灰字 + 去阴影"，覆盖所有变体（写在变体之后才有特权） */
.btn:disabled,
.btn[disabled],
.btn.disabled {
  background: var(--gray-100);
  color: var(--gray-400);
  border-color: var(--gray-200);
  box-shadow: none;
  cursor: not-allowed;
}
.btn-ghost:disabled,
.btn-text:disabled {
  background: transparent;
  border-color: transparent;
}

/* 按钮组：主按钮固定最右（§2.5 全站统一） */
.btn-bar {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  margin-bottom: var(--sp-4);
}
.btn-bar:last-child { margin-bottom: 0; }
/* 行内文字按钮之间保底 8px，即使模板是用空格分隔而非 flex */
.btn-text + .btn-text,
.btn-text + .btn-text-danger,
.btn-text-danger + .btn-text { margin-left: var(--sp-1); }

/* 已废弃变体别名（Phase 1 §2.5 删除"绿色成功按钮"语义）
   模板里仍有 4 处 btn-success（customer.js:91 / customer.js:361「AI 重新分析」/
   script.js:253「完成配置」等）。刀 1 不能改 JS：整段删除会让它们退化成裸文字。
   两人复核结论一致——映射为 **secondary** 外观（中性描边），不用主色，
   因为这两处都是"次要动作"，绿色/主色都不符合 §2.5 的单一主按钮原则。
   刀 3 把那 4 处分别改成 btn-ghost / btn-primary 后，本节可删。 */
.btn-success {
  background: var(--gray-0);
  color: var(--gray-800);
  border-color: var(--gray-300);
}
.btn-success:hover { background: var(--gray-50); border-color: var(--gray-400); }
.btn-success:active { background: var(--gray-100); }


/* =============================================================================
   §8  表单、搜索、筛选控件（§2.6 / §2.7 / §1.2 三档宽度）
   ========================================================================== */
.form-group { margin-bottom: var(--sp-4); }
.form-group label,
.form-label {
  display: block;
  margin-bottom: 6px;
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  font-weight: 400;
  color: var(--gray-600);
}
.form-group label .req,
.form-label .req { color: var(--danger-600); }

.form-control {
  width: 100%;
  min-height: 36px;
  padding: 0 var(--sp-3);
  background: var(--gray-0);
  border: var(--bw-1) solid var(--gray-300);
  border-radius: var(--r-sm);
  font-size: var(--fs-md);
  line-height: var(--lh-md);
  color: var(--gray-800);
  outline: none;
  transition: border-color var(--dur-fast) var(--ease-std),
              box-shadow var(--dur-fast) var(--ease-std);
}
.form-control::placeholder { color: var(--gray-400); }
.form-control:hover { border-color: var(--gray-400); }
.form-control:focus {
  border-color: var(--teal-600);
  box-shadow: var(--shadow-focus);
}
.form-control:disabled,
.form-control[disabled] {
  background: var(--gray-50);
  border-color: var(--gray-200);
  color: var(--gray-400);
  cursor: not-allowed;
}
.form-control.is-error,
.form-control.warn {
  border-color: var(--danger-600);
  box-shadow: var(--shadow-focus-danger);
}

/* 多行文本 */
textarea.form-control {
  min-height: 88px;
  padding: var(--sp-2) var(--sp-3);
  line-height: var(--lh-md);
  resize: vertical;
}

/* 下拉：去掉系统箭头，用内联 SVG（data URI，不引外链/图标库） */
select.form-control,
select.w-select,
.w-select,
.filter-select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: var(--sp-8);
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235F7079' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 14px 14px;
  cursor: pointer;
}

.form-row {
  display: flex;
  gap: var(--sp-4);
  flex-wrap: wrap;
}
.form-row .form-group { flex: 1; min-width: 200px; margin-bottom: var(--sp-4); }

/* ── 搜索框（§2.7：34px 高、6px 圆角、左侧图标留白 36px、不用胶囊）──── */
.search-wrap {
  position: relative;
  width: 240px;              /* 列表页工具栏固定 240px（§2.7） */
  max-width: 100%;
  margin-bottom: var(--sp-4);
}
.search-wrap--fluid { width: 100%; }   /* 搜索是该页唯一筛选时用（如快捷话术） */

.search-box {
  width: 100%;
  min-height: 34px;
  padding: 0 var(--sp-3) 0 36px;
  background: var(--gray-0);
  border: var(--bw-1) solid var(--gray-300);
  border-radius: var(--r-sm);
  font-size: var(--fs-md);
  line-height: var(--lh-md);
  color: var(--gray-800);
  outline: none;
  transition: border-color var(--dur-fast) var(--ease-std),
              box-shadow var(--dur-fast) var(--ease-std);
}
.search-box::placeholder { color: var(--gray-400); }
.search-box:hover { border-color: var(--gray-400); }
.search-box:focus {
  border-color: var(--teal-600);
  box-shadow: var(--shadow-focus);
}

.search-wrap .search-icon,
.search-icon {
  position: absolute;
  left: var(--sp-3);
  top: 50%;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-sm);
  line-height: 1;
  color: var(--gray-400);
  pointer-events: none;      /* 图标不挡点击 */
}

/* ── 筛选/搜索控件宽度：4 档，只允许这 4 个值（§1.2 v1.1）─────────────
   .w-date 132 / .w-select 168 / .w-key 220 / .w-search 240
   原 .filter-input(140) / .filter-input-sm(110) / .filter-select(160) 三档作废，
   但类名保留为**同值别名**（清单要求有规则，且刀 3 之前模板还在用它），
   避免"两套宽度语言并存"：别名只能映射到这 4 个值，不许出现第五个。 */
.filter-input,
.filter-select {
  min-height: 36px;
  padding: 0 var(--sp-3);
  background-color: var(--gray-0);
  border: var(--bw-1) solid var(--gray-300);
  border-radius: var(--r-sm);
  font-size: var(--fs-md);
  line-height: var(--lh-md);
  color: var(--gray-800);
  outline: none;
  transition: border-color var(--dur-fast) var(--ease-std),
              box-shadow var(--dur-fast) var(--ease-std);
}
.filter-input::placeholder,
.w-key::placeholder,
.w-search::placeholder { color: var(--gray-400); }
.filter-input:hover,
.filter-select:hover,
.w-date:hover,
.w-select:hover,
.w-key:hover,
.w-search:hover { border-color: var(--gray-400); }
.filter-input:focus,
.filter-select:focus,
.w-date:focus,
.w-select:focus,
.w-key:focus,
.w-search:focus {
  border-color: var(--teal-600);
  box-shadow: var(--shadow-focus);
}

/* 四档宽度（唯一合法宽度语言） */
.w-date,
.w-select,
.w-key,
.w-search {
  min-height: 36px;
  padding: 0 var(--sp-3);
  background-color: var(--gray-0);
  border: var(--bw-1) solid var(--gray-300);
  border-radius: var(--r-sm);
  font-size: var(--fs-md);
  line-height: var(--lh-md);
  color: var(--gray-800);
  outline: none;
  flex: none;
  transition: border-color var(--dur-fast) var(--ease-std),
              box-shadow var(--dur-fast) var(--ease-std);
}
.w-date   { width: 132px; }   /* 日期输入 */
.w-select { width: 168px; }   /* 下拉 */
.w-key    { width: 220px; }   /* 关键词输入 */
.w-search { width: 240px; }   /* 表格搜索框 */

/* 下拉的右侧留给箭头（必须写在上面 padding 之后，否则文字会压在箭头上） */
select.w-select,
.filter-select { padding-right: var(--sp-8); }

/* 旧三档 → 就近归入新四档（刀 3 全部替换成 .w-* 后删除） */
.filter-input    { width: 220px; }   /* → .w-key */
.filter-input-sm { width: 168px; }   /* → .w-select */
.filter-select   { width: 168px; }   /* → .w-select */

/* ── 标签输入 / 选项卡 / chip 组（脚本向导与话术弹窗）────────────────── */
.chip-group { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

.opt-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: var(--sp-3);
}
.opt-card {
  position: relative;
  padding: var(--sp-3) 10px;
  background: var(--gray-0);
  border: var(--bw-1) solid var(--gray-300);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  text-align: center;
  color: var(--gray-700);
  cursor: pointer;
  user-select: none;
  transition: background-color var(--dur-fast) var(--ease-std),
              border-color var(--dur-fast) var(--ease-std),
              color var(--dur-fast) var(--ease-std);
}
.opt-card:hover { border-color: var(--gray-400); color: var(--gray-900); }
.opt-card.on {
  background: var(--teal-50);
  border-color: var(--teal-600);
  color: var(--teal-700);
  font-weight: 500;
}
.opt-card.on::after {
  content: "✓";
  position: absolute;
  top: 2px;
  right: 6px;
  font-size: var(--fs-xs);
  line-height: 1;
  color: var(--teal-600);
}

.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-bottom: var(--sp-2);
}
.tag-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px var(--sp-3);
  background: var(--teal-50);
  border: var(--bw-1) solid var(--teal-200);
  color: var(--teal-700);
  border-radius: var(--r-full);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
}
.tag-pill .tag-x {
  cursor: pointer;
  font-weight: 700;
  opacity: 0.7;
  line-height: 1;
}
.tag-pill .tag-x:hover { opacity: 1; color: var(--danger-600); }

.tag-input-row { display: flex; gap: var(--sp-2); }
.tag-input-row .form-control { flex: 1; }

/* 分类色点：颜色只做"点"，退出文字层，对比度不再依赖用户数据（Phase 2 §4.1） */
.tag-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: var(--r-full);
  margin-right: 6px;
  vertical-align: middle;
  flex: none;
}
.tag-dot--lg { width: 8px; height: 8px; }

/* 标签筛选横滚行 */
.tag-filter-row {
  display: flex;
  gap: var(--sp-2);
  overflow-x: auto;
  padding: 2px 0 var(--sp-3);
  -webkit-overflow-scrolling: touch;
}
.tag-filter-row::-webkit-scrollbar { height: 6px; }


/* =============================================================================
   §9  徽章 6 态 / 状态点 / 筛选 chip
   -----------------------------------------------------------------------------
   ⚠ 陷阱 2：模板里 .badge 裸用 30 处，旧 CSS 默认红底 → 「企业共享」「手动」
   这类中性标签全变红，一屏 20 个红标签就是"界面显脏"的第一元凶。

   三条硬约束（复核结论，改之前先读）：
   1) 基类 .badge **全文件只定义一次**，默认 = 中性灰。旧的 170 行 / 227 行两份
      定义正是"整页红标签"的根因。
   2) 修饰符必须排在基类**之后**：.badge-info 与 .badge 特异性相同（0,1,0），
      靠源码顺序决胜，写前面会被吃掉 → "看着对但不生效"。
   3) 每个语义态写两种选择器：.badge.info 管 class="badge info"（21 处），
      .badge-info 同时管 class="badge badge-info" 与独立 .badge-info。
      只写一种会让页面"一半对一半不对"，最难自查。

   六态语义分工（不要合并）：
   · neutral（有底 gray-100 + gray-600 字）→ 有实义的属性值：企业共享 / 手动 / 导入
   · muted（透明底 + 1px gray-200 描边 + gray-500 字）→ 不用读的附属信息：
     空值「—」、计数、「只读」
   · info / success / warning / danger → 真状态：个人话术 / 已同步 / 待处理 / 失败

   ⚠ 8 处徽章带内联 style（其中 4 处是手写 hex 在模拟缺失的类名，另 2 处是
   数据驱动的标签色 t.color）。这些 CSS 改不动，**本刀不用强制覆盖去压它们**：
   压了会连带盖掉业务颜色，以后没法排查。刀 3 删内联后自动归位；
   在此之前这 8 处保持旧色，视觉上暂时不一致是可接受的。
   ========================================================================== */

/* ── 基类：中性态（有底）─────────────────────────────────────────────── */
.badge {
  display: inline-flex;
  align-items: center;
  height: 20px;
  padding: 0 6px;
  border: var(--bw-1) solid transparent;
  border-radius: var(--r-xs);
  background: var(--gray-100);
  color: var(--gray-600);
  font-size: var(--fs-xs);
  line-height: var(--lh-xs);
  font-weight: 500;
  white-space: nowrap;
  vertical-align: middle;
}

/* 一行内 ≥2 个徽章时的间距（替代旧模板里的内联 margin-left:8px） */
.badge + .badge { margin-left: var(--sp-1); }

/* ── 信息态 ─────────────────────────────────────────────────────────── */
.badge.info { background: var(--info-50); color: var(--info-600); }
.badge-info { background: var(--info-50); color: var(--info-600); }

/* ── 成功态 ─────────────────────────────────────────────────────────── */
.badge.success { background: var(--success-50); color: var(--success-600); }
.badge-success { background: var(--success-50); color: var(--success-600); }

/* ── 警告态 ─────────────────────────────────────────────────────────── */
.badge.warning { background: var(--warning-50); color: var(--warning-600); }
.badge-warning { background: var(--warning-50); color: var(--warning-600); }

/* ── 危险态 ─────────────────────────────────────────────────────────── */
.badge.danger { background: var(--danger-50); color: var(--danger-600); }
.badge-danger { background: var(--danger-50); color: var(--danger-600); }

/* ── 弱化态（透明底 + 浅描边）：只给「—」空值 / 计数 / 只读 ──────────── */
.badge.muted {
  background: transparent;
  color: var(--gray-500);
  border-color: var(--gray-200);
}
.badge-muted {
  background: transparent;
  color: var(--gray-500);
  border-color: var(--gray-200);
}

/* ── 中性显式写法（模板若写明 neutral 也命中，避免落回未知类名）──────── */
.badge.neutral { background: var(--gray-100); color: var(--gray-600); }
.badge-neutral { background: var(--gray-100); color: var(--gray-600); }

/* ── 状态点（§2.8：6px 圆点 + 8px 间距 + 同色文字，不加发光/描边环）── */
.tag-dot.success, .dot-success { background: var(--success-600); }
.tag-dot.warning, .dot-warning { background: var(--warning-600); }
.tag-dot.danger,  .dot-danger  { background: var(--danger-600); }
.tag-dot.info,    .dot-info    { background: var(--info-600); }
.tag-dot.muted,   .dot-muted   { background: var(--gray-400); }

.status-dot {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
}
.status-dot::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: var(--r-full);
  background: currentColor;
  flex: none;
}
.status-dot.success { color: var(--success-600); }
.status-dot.warning { color: var(--warning-600); }
.status-dot.danger  { color: var(--danger-600); }
.status-dot.info    { color: var(--info-600); }
.status-dot.muted   { color: var(--gray-500); }

/* ── 筛选 chip（§2.10：28px 胶囊，选中=浅青底+青描边，不用实心青）───── */
.chip,
.tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  padding: 0 var(--sp-3);
  flex: none;
  background: var(--gray-0);
  border: var(--bw-1) solid var(--gray-300);
  border-radius: var(--r-full);
  color: var(--gray-600);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  transition: background-color var(--dur-fast) var(--ease-std),
              border-color var(--dur-fast) var(--ease-std),
              color var(--dur-fast) var(--ease-std);
}
.chip:hover,
.tag-chip:hover { border-color: var(--gray-400); color: var(--gray-800); }

/* 选中态：.chip.on（脚本向导）与 .tag-chip.active（话术标签行）写法并存 */
.chip.on,
.chip.active,
.tag-chip.active {
  background: var(--teal-50);
  border-color: var(--teal-600);
  color: var(--teal-700);
  font-weight: 500;
}

.chip-clear {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  height: 28px;
  padding: 0 var(--sp-3);
  background: transparent;
  border: 0;
  border-radius: var(--r-full);
  color: var(--gray-600);
  font-size: var(--fs-sm);
  cursor: pointer;
}
.chip-clear:hover { color: var(--gray-900); }


/* =============================================================================
   §10  Tab / 工具栏 / 分页 / 批量条 / 下拉 / Stepper（刀 3 使用，规则预留）
   ========================================================================== */

/* ── 真 Tab（§2.9：2px 底部指示线；.page-tabs/.page-tab 与 .tabs/.tab 等价）── */
.page-tabs,
.tabs {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  height: 40px;
  margin-bottom: var(--sp-4);
  border-bottom: var(--bw-1) solid var(--gray-200);
  overflow-x: auto;
}
.page-tab,
.tab {
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
  height: 40px;
  padding: 0 2px;
  flex: none;
  background: none;
  border: 0;
  color: var(--gray-600);
  font-size: var(--fs-md);
  line-height: var(--lh-md);
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-std);
}
.page-tab:hover,
.tab:hover { color: var(--gray-900); }
.page-tab.active,
.tab.active { color: var(--teal-700); font-weight: 600; }
.page-tab.active::after,
.tab.active::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: var(--bw-2);
  border-radius: 1px;
  background: var(--teal-600);
}
.page-tab:focus-visible,
.tab:focus-visible { box-shadow: none; color: var(--teal-700); text-decoration: underline; }

/* Tab 计数角标 */
.tab-count {
  height: 18px;
  padding: 0 6px;
  display: inline-flex;
  align-items: center;
  border-radius: var(--r-xs);
  background: var(--gray-100);
  color: var(--gray-600);
  font-size: var(--fs-xs);
  line-height: var(--lh-xs);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}
.page-tab.active .tab-count,
.tab.active .tab-count { background: var(--teal-50); color: var(--teal-700); }

/* 竖向 Tab（>5 个时改用，§2.9） */
.tabs-vertical { display: flex; flex-direction: column; gap: var(--sp-1); border: 0; height: auto; width: 160px; }
.tabs-vertical .tab { width: 100%; height: 34px; padding: 0 var(--sp-3); border-radius: var(--r-sm); justify-content: flex-start; }
.tabs-vertical .tab.active { background: var(--teal-50); }
.tabs-vertical .tab.active::after { left: 0; top: 6px; bottom: 6px; right: auto; width: var(--bw-2); height: auto; }

/* ── 工具栏三区（Phase 2 §1.2）───────────────────────────────────────── */
.toolbar {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
  margin-bottom: var(--sp-4);
}
.toolbar-left {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  min-width: 0;
}
.toolbar-left .search-wrap { margin-bottom: 0; }
.toolbar-right {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-left: auto;
}
.toolbar-filters {
  flex: 1 0 100%;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  margin-top: var(--sp-1);
}
.toolbar-count {
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--gray-600);
  white-space: nowrap;
}

/* ── 分页（§2.15：挂在卡片内底部，右侧对齐）─────────────────────────── */
.pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-5);
  border-top: var(--bw-1) solid var(--gray-200);
  flex-wrap: wrap;
}
.pagination .page-info,
.page-info {
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--gray-600);
}
.pagination .page-list,
.page-list {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  margin-left: auto;
}
.page-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  height: 32px;
  padding: 0 6px;
  border: var(--bw-1) solid transparent;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--gray-700);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-std),
              color var(--dur-fast) var(--ease-std);
}
.page-btn:hover { background: var(--gray-100); }
/* 当前页：浅青底 + 内描边，不用实心青底 */
.page-btn.active,
.page-btn[aria-current="page"] {
  background: var(--teal-50);
  color: var(--teal-700);
  font-weight: 600;
  box-shadow: inset 0 0 0 1px var(--teal-200);
}
.page-btn:disabled { color: var(--gray-400); cursor: not-allowed; background: transparent; }
.page-ellipsis {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  height: 32px;
  color: var(--gray-400);
  font-size: var(--fs-sm);
  user-select: none;
}
.page-size { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-sm); color: var(--gray-600); }
.page-size select.form-control { width: auto; min-height: 32px; height: 32px; }

/* ── 批量操作条（Phase 2 §5.3）───────────────────────────────────────── */
.batch-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  min-height: 44px;
  padding: var(--sp-1) var(--sp-4);
  margin: 0 0 var(--sp-2);
  background: var(--teal-50);
  border: var(--bw-1) solid var(--teal-200);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--gray-800);
  flex-wrap: wrap;
}
.batch-bar__count { color: var(--gray-700); }
.batch-bar__count b { color: var(--teal-700); font-weight: 600; }
.batch-bar__actions { display: flex; align-items: center; gap: var(--sp-2); margin-left: auto; }

/* ── 下拉浮层（卡片头「更多 ⋯」、顶栏用户菜单，刀 3 使用）────────────── */
.dropdown { position: relative; display: inline-flex; }
.dropdown-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 160px;
  padding: var(--sp-1);
  background: var(--gray-0);
  border: var(--bw-1) solid var(--gray-200);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-2);
  z-index: var(--z-dropdown);
  display: none;
}
.dropdown.open > .dropdown-menu,
.dropdown-menu.open { display: block; }
.dropdown-item {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  width: 100%;
  height: 32px;
  padding: 0 var(--sp-2);
  border: 0;
  border-radius: var(--r-xs);
  background: transparent;
  color: var(--gray-800);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}
.dropdown-item:hover { background: var(--gray-100); }
.dropdown-item.danger { color: var(--danger-600); }
.dropdown-item.danger:hover { background: var(--danger-50); }
/* 刀 2 的 renderMain 用 is-danger（BEM 修饰符），与旧 .danger 并存 */
.dropdown-item.is-danger { color: var(--danger-600); }
.dropdown-item.is-danger:hover { background: var(--danger-50); }
.dropdown-divider { height: var(--bw-1); margin: var(--sp-1) 0; background: var(--gray-200); }

/* ── Stepper（§2.9 同源视觉；Phase 2 §4.4 数字式）────────────────────── */
.stepper {
  display: flex;
  align-items: center;
  gap: 0;
  height: 56px;
  margin-bottom: var(--sp-5);
}
.stepper-item {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex: 1;
  min-width: 0;
}
.step-dot {
  flex: none;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-full);
  background: var(--gray-100);
  border: var(--bw-1) solid var(--gray-300);
  color: var(--gray-600);
  font-size: var(--fs-xs);
  line-height: 1;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}
.step-label {
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--gray-600);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.step-line {
  flex: 1;
  height: var(--bw-1);
  margin: 0 var(--sp-2);
  background: var(--gray-200);
}
.stepper-item.current .step-dot {
  background: var(--teal-600);
  border-color: var(--teal-600);
  color: #FFFFFF;
  font-weight: 600;
  box-shadow: var(--shadow-focus);
}
.stepper-item.current .step-label { color: var(--gray-900); font-weight: 600; }
.stepper-item.done .step-dot {
  background: var(--teal-50);
  border-color: var(--teal-600);
  color: var(--teal-700);
}
.stepper-item.done .step-label { color: var(--gray-700); }
.stepper-item:last-child { flex: none; }

/* ── 头像（28px 圆形；详情头 40px）───────────────────────────────────── */
.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: var(--r-full);
  background: var(--teal-100);
  color: var(--teal-800);
  font-size: var(--fs-xs);
  line-height: 1;
  font-weight: 600;
  user-select: none;
  overflow: hidden;
}
.avatar-sm { width: 24px; height: 24px; font-size: var(--fs-xs); }
.avatar-lg { width: 40px; height: 40px; font-size: var(--fs-md); }
.avatar img { width: 100%; height: 100%; object-fit: cover; }

/* ── 详情页头部摘要（Phase 2 §4.2）───────────────────────────────────── */
.detail-head {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 72px;
  padding: var(--sp-3) var(--sp-5);
  margin-bottom: var(--sp-4);
  background: var(--gray-0);
  border: var(--bw-1) solid var(--gray-200);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
  flex-wrap: wrap;
}
.detail-head .avatar {
  width: 40px;
  height: 40px;
  font-size: var(--fs-lg);
}
.detail-name {
  font-size: var(--fs-lg);
  line-height: var(--lh-lg);
  font-weight: 600;
  color: var(--gray-900);
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
}
.detail-sub {
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--gray-600);
  margin-top: 2px;
}
.detail-actions { display: flex; align-items: center; gap: var(--sp-2); margin-left: auto; }

/* ── 双栏（详情页 / 左表单右预览，刀 3 起用）────────────────────────────
   ⚠ 第二列必须写 minmax(0, 1fr) 而不是 1fr：
   裸 1fr 的最小尺寸是 auto，内部表格/长英文串会把栅格撑破，右侧溢出到卡片外。 */
.split-2 {
  display: grid;
  grid-template-columns: 360px minmax(0, 1fr);
  gap: var(--sp-4);
  align-items: start;
}
.split-2--form { grid-template-columns: minmax(0, 1fr) 320px; }   /* 左表单右预览 */
.split-2 > * { min-width: 0; }
/* 折单列：跟随 §1.6 的第 4 档（≤1023 即 SM 及以下），不另造断点。
   Phase 2 §7 表里 1024–1199 仍是双栏（280 + 1fr），故边界取 1023 而非 1199。 */
@media (max-width: 1023px) {
  .split-2,
  .split-2--form { grid-template-columns: minmax(0, 1fr); }
}

/* ── 组内小标题（话术工作台的「话术栏」「弹药库」等）────────────────── */
.group-label {
  font-size: var(--fs-xs);       /* 12px，全站下限 */
  line-height: var(--lh-xs);
  font-weight: 500;
  color: var(--gray-600);
  margin-bottom: var(--sp-2);
}


/* =============================================================================
   §11  空态 / 加载 / 提示文本
   ========================================================================== */

/* 空态（§2.11 三段式：图标盘 + 标题 + 说明 + 可选行动） */
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 48px var(--sp-6);
  color: var(--gray-600);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
}
.empty-icon {
  width: 64px;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-full);
  background: var(--gray-50);
  color: var(--gray-400);
  font-size: 24px;
  line-height: 1;
  margin-bottom: var(--sp-4);
}
.empty-icon .ico { width: 28px; height: 28px; }
.empty-title {
  font-size: var(--fs-md);
  line-height: var(--lh-md);
  font-weight: 500;
  color: var(--gray-800);
}
.empty-desc {
  margin-top: var(--sp-1);
  max-width: 320px;
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--gray-600);
}
.empty .btn { margin-top: var(--sp-4); }

/* 加载占位（旧 .loading 保留为文字占位；骨架块用 .skeleton，刀 3 替换） */
.loading {
  padding: var(--sp-10);
  text-align: center;
  color: var(--gray-600);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
}

/* 骨架：脉冲，不用流光（20 个块同时扫光会闪成一片，§2.12） */
.skeleton {
  background: var(--gray-100);
  border-radius: var(--r-xs);
  animation: sk-pulse 1.4s var(--ease-std) infinite;
}
.skeleton-text { height: 12px; margin-bottom: var(--sp-2); }
.skeleton-title { height: 14px; width: 40%; margin-bottom: var(--sp-3); }
.skeleton-row { height: 16px; margin-bottom: var(--sp-2); }
.skeleton-card { height: 88px; border-radius: var(--r-lg); }
@keyframes sk-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.55; }
}

/* 提示文本
   ⚠ 陷阱说明：模板里 .hint 有 43 处，其中约 20 处是"说明性文字"（配额说明、
   绑定规则、统计口径…），只有少数是错误提示容器。旧 CSS 把 .hint 整体标红，
   于是满屏说明文字都是红的。本文件把 .hint 收敛为中性提示（--gray-600），
   并把登录/改密两处没有内联色、纯靠类名变红的错误容器用 ID 显式标红。 */
.hint {
  margin-top: var(--sp-3);
  font-size: var(--fs-xs);
  line-height: var(--lh-xs);
  color: var(--gray-600);
}
#loginHint,
#pwdHint {
  color: var(--danger-600);
  min-height: 16px;
}

.field-hint {
  margin-top: var(--sp-1);
  font-size: var(--fs-xs);
  line-height: var(--lh-xs);
  color: var(--gray-600);
}
.field-hint.warn,
.hint.warn,
.warn {
  color: var(--danger-600);
}

/* 文字层级工具类 */
.text-muted { color: var(--gray-600); }
.text-strong { color: var(--gray-900); font-weight: 600; }
.text-danger { color: var(--danger-600); }
.text-success { color: var(--success-600); }
.text-right { text-align: right; }
.text-center { text-align: center; }
.text-nowrap { white-space: nowrap; }
.sub { color: var(--gray-600); font-size: var(--fs-sm); line-height: var(--lh-sm); }


/* =============================================================================
   §12  弹窗 / Toast / 浮层
   ========================================================================== */
.modal-mask {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-6);
  background: var(--mask);
  z-index: var(--z-modal);
  animation: mask-in var(--dur-slow) var(--ease-std);
}
@keyframes mask-in { from { opacity: 0; } to { opacity: 1; } }

.modal {
  display: flex;
  flex-direction: column;
  width: 520px;                 /* md 默认宽度 */
  max-width: 92vw;
  max-height: 88vh;
  background: var(--gray-0);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-3);
  animation: modal-in var(--dur-base) var(--ease-out);
}
.modal.modal-sm { width: 400px; }
.modal.modal-lg { width: 720px; }
.modal.modal-xl { width: 880px; }
@keyframes modal-in {
  from { opacity: 0; transform: scale(0.98); }
  to   { opacity: 1; transform: scale(1); }
}

.modal-header {
  flex: none;
  min-height: 60px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-5);
  border-bottom: var(--bw-1) solid var(--gray-200);
}
.modal-header h2,
.modal-header h3 {
  margin: 0;
  font-size: var(--fs-lg);
  line-height: var(--lh-lg);
  font-weight: 600;
  color: var(--gray-900);
}

.modal-close {
  flex: none;
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--gray-600);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-std),
              color var(--dur-fast) var(--ease-std);
}
.modal-close:hover { background: var(--gray-100); color: var(--gray-900); }

.modal-body {
  flex: 1;
  min-height: 0;
  padding: var(--sp-5);
  overflow-y: auto;
}
.modal-body > *:first-child { margin-top: 0; }
.modal-body > *:last-child { margin-bottom: 0; }

.modal-footer {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--sp-2);
  padding: 14px var(--sp-5);
  border-top: var(--bw-1) solid var(--gray-200);
  flex-wrap: wrap;
}

/* ── Toast（§2.14：白底 + 状态点，不用实色胶囊）─────────────────────── */
.toast {
  position: fixed;
  top: var(--sp-6);
  right: var(--sp-6);
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 260px;
  max-width: 400px;
  min-height: 44px;
  padding: 11px 14px;
  background: var(--gray-0);
  border: var(--bw-1) solid var(--gray-200);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-3);
  color: var(--gray-800);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  z-index: var(--z-toast);
  animation: toast-in var(--dur-base) var(--ease-out);
}
.toast::before {
  content: "";
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: var(--r-full);
  background: var(--gray-400);
}
.toast.success::before { background: var(--success-600); }
.toast.warning::before { background: var(--warning-600); }
.toast.error::before,
.toast.danger::before  { background: var(--danger-600); }
.toast.info::before    { background: var(--info-600); }

/* 多条堆叠：相邻 sibling 依次下移（第 1 条消失后后面的自动回到 top 位） */
.toast + .toast { top: 84px; }
.toast + .toast + .toast { top: 144px; }

@keyframes toast-in {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}


/* =============================================================================
   §13  业务遗留组件
   ========================================================================== */

/* ── 文档列表（企业知识库 / 企业资料）────────────────────────────────── */
.doc-list { list-style: none; padding: 0; margin: 0; }
.doc-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: 10px var(--sp-3);
  margin-bottom: var(--sp-2);
  background: var(--gray-0);
  border: var(--bw-1) solid var(--gray-200);
  border-radius: var(--r-md);
  transition: border-color var(--dur-fast) var(--ease-std),
              box-shadow var(--dur-fast) var(--ease-std);
}
.doc-list li:hover { border-color: var(--gray-300); box-shadow: var(--shadow-1); }
.doc-list li:last-child { margin-bottom: 0; }
.doc-list .doc-title {
  font-size: var(--fs-md);
  line-height: var(--lh-md);
  font-weight: 500;
  color: var(--gray-900);
  word-break: break-all;
}
.doc-list .doc-meta {
  margin-top: 2px;
  font-size: var(--fs-xs);
  line-height: var(--lh-xs);
  color: var(--gray-600);
}
.doc-list .doc-content {
  margin-top: var(--sp-1);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--gray-600);
  max-height: 60px;
  overflow: hidden;
  word-break: break-all;
}

/* ── 键值表（关于页 / 客户详情基础信息）：label 96px 右对齐 + value 左对齐 ── */
.about-list { list-style: none; padding: 0; margin: 0; }
.about-list li {
  display: grid;
  grid-template-columns: 96px 1fr;
  align-items: start;
  gap: var(--sp-3);
  padding: var(--sp-3) 0;
  border-bottom: var(--bw-1) solid var(--gray-200);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
}
.about-list li:first-child { padding-top: 0; }
.about-list li:last-child { border-bottom: 0; padding-bottom: 0; }
.about-list .label {
  color: var(--gray-600);
  text-align: right;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.about-list .value {
  color: var(--gray-800);
  word-break: break-word;
}

/* ── 脚本模块：向导顶部条（旧 wiz-* 保留，刀 3 换成 .stepper）────────── */
.wiz-top {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
  flex-wrap: wrap;
}
.wiz-title { display: flex; align-items: center; gap: var(--sp-3); }
.wiz-title h3 {
  margin: 0;
  font-size: var(--fs-lg);
  line-height: var(--lh-lg);
  font-weight: 600;
  color: var(--gray-900);
}
.wiz-steps {
  display: flex;
  gap: 6px;
  flex: 1;
  min-width: 200px;
}
.wiz-step {
  flex: 1;
  height: 6px;
  border-radius: var(--r-full);
  background: var(--gray-200);
  transition: background-color var(--dur-fast) var(--ease-std);
}
.wiz-step.done { background: var(--teal-300); cursor: pointer; }
.wiz-step.done:hover { background: var(--teal-400); }
.wiz-step.cur { background: var(--teal-600); }

.wiz-guide {
  padding: var(--sp-3) var(--sp-4);
  margin-bottom: var(--sp-4);
  background: var(--teal-50);
  border: var(--bw-1) solid var(--teal-200);
  border-radius: var(--r-md);
  color: var(--teal-700);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
}

.wiz-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: var(--sp-4);
  padding-top: var(--sp-4);
  border-top: var(--bw-1) solid var(--gray-200);
  flex-wrap: wrap;
}

/* ── 脚本工作台：生成结果展示 ───────────────────────────────────────── */
.script-content {
  padding: 14px var(--sp-4);
  background: var(--gray-50);
  border: var(--bw-1) solid var(--gray-200);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  line-height: var(--lh-md);
  color: var(--gray-800);
  white-space: pre-wrap;
  word-break: break-word;
}
.gen-note {
  font-size: var(--fs-sm);
  line-height: 22px;
  color: var(--gray-800);
  white-space: pre-wrap;
  word-break: break-word;
}
.gen-toolbar {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin: 14px 0;
  flex-wrap: wrap;
}
.gen-toolbar label {
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--gray-600);
}
.gen-loading {
  padding: var(--sp-6) 0;
  text-align: center;
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--gray-600);
}

/* ── 内容完整度色块（回复日志 cp-wrap）──────────────────────────────── */
.cp-wrap {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-xs);
  line-height: var(--lh-xs);
  color: var(--gray-600);
  flex-wrap: wrap;
}
.cp-blocks { display: flex; gap: 2px; }
.cp-block {
  width: 10px;
  height: 10px;
  border-radius: 2px;
  background: var(--gray-200);
}
.cp-wrap.cp-green  .cp-block.on { background: var(--success-600); }
.cp-wrap.cp-yellow .cp-block.on { background: var(--warning-600); }
.cp-wrap.cp-red    .cp-block.on { background: var(--danger-600); }
.cp-wrap.cp-blue   .cp-block.on { background: var(--teal-600); }

.cp-value {
  font-weight: 600;
  color: var(--gray-800);
  font-variant-numeric: tabular-nums;
}
.cp-wrap.cp-red .cp-value,
.cp-wrap.cp-red .field-hint,
.cp-wrap.cp-red .hint { color: var(--danger-600); }
.cp-wrap.cp-yellow .cp-value { color: var(--warning-600); }
.cp-wrap.cp-green .cp-value { color: var(--success-600); }
.cp-wrap.cp-blue .cp-value { color: var(--teal-700); }


/* =============================================================================
   §14  登录页与改密页（§2.16：去掉 135° 蓝色渐变与大阴影）
   -----------------------------------------------------------------------------
   刀 1 不改 HTML：登录页仍是 .login-wrap > .login-card 单层结构，
   所以用"整页深空面 + 居中白卡"承载 §2.16 的品牌面，不再叠第二组色相。
   下一节 .login-split/.login-aside/.login-main 是给刀 2 左右分栏结构预留的规则，
   当前 DOM 下不产生任何影响。
   ========================================================================== */
.login-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-6);
  background: linear-gradient(180deg, var(--teal-900) 0%, var(--teal-950) 100%);
  overflow-y: auto;
}

.login-card {
  width: 360px;
  max-width: 100%;
  margin: auto;                 /* 内容超高时可滚动，不裁顶部 */
  padding: var(--sp-10);
  background: var(--gray-0);
  border: var(--bw-1) solid var(--gray-200);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-1);  /* 只留一级阴影；旧版的"大投影 + 蓝紫对角渐变"已删 */
}
/* 版权/协议行（login-card 底部）：深空面之外的浅底上，用 --ink-group 同色族 */
.login-card .login-legal {
  margin-top: var(--sp-1);
  text-align: center;
  font-size: var(--fs-xs);
  line-height: var(--lh-xs);
  color: var(--gray-500);
}
.login-card h1 {
  margin: 0 0 var(--sp-1);
  font-size: var(--fs-xl);
  line-height: var(--lh-xl);
  font-weight: 600;
  color: var(--gray-900);
  text-align: center;
}
.login-card .sub {
  margin-bottom: var(--sp-6);
  text-align: center;
  color: var(--gray-600);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
}
.login-card .form-group { margin-bottom: var(--sp-4); }
/* 登录页输入框放宽一档到 40px（§2.16），与登录按钮同高 */
.login-card .form-control { min-height: 40px; }
.login-card .btn { width: 100%; }

/* 刀 2 左右分栏结构预留（当前 DOM 未使用，写上即生效，无副作用） */
.login-split { display: flex; min-height: 100vh; }
.login-aside {
  width: 480px;
  flex: none;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: var(--sp-10) var(--sp-8);
  background: linear-gradient(180deg, var(--teal-900) 0%, var(--teal-950) 100%);
  color: #FFFFFF;
}
.login-aside .login-brand { display: flex; align-items: center; gap: var(--sp-3); font-size: var(--fs-xl); font-weight: 600; }
.login-aside .login-claim { font-size: var(--fs-sm); line-height: var(--lh-sm); color: var(--ink-text); }
.login-aside .login-copy { font-size: var(--fs-xs); color: var(--ink-group); }
.login-main {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-6);
  background: var(--gray-50);
}
@media (max-width: 1023px) {
  .login-aside { display: none; }
}


/* =============================================================================
   §15  响应式 5 档断点（§1.6）
   ≥1600 / 1200–1599 / 1024–1199 / 768–1023 / <768
   ========================================================================== */

/* ── 窄屏表格宽度兜底（v1.1 硬伤修复的断点侧补充）──────────────────────
   主体规则（table 的 min-width 720/964 + tbody td 的 nowrap）已写在 §6，
   这里只做两件窄屏专属的事：
   ① 兜底 .card-pad 的横滚 —— 若浏览器不支持 :has()，§6 的
      .card-pad:has(> table) 就失效了，用不带 :has() 的宽规则接住；
   ② 双行单元格的内边距收紧（窄屏少 8px 可多显示半列）。 */
@media (max-width: 1023px) {
  .card-pad,
  .card-body { overflow-x: auto; }
  .table-2line tbody td { padding-left: var(--sp-3); padding-right: var(--sp-3); }
}

/* ── MD 1024–1199：内容区 padding 20，卡片内边距降到 16 ───────────────── */
@media (max-width: 1199px) {
  .content { padding: var(--sp-5); }
  .card-pad,
  .card-body { padding: var(--sp-4); }
  .card-header { padding-left: var(--sp-4); padding-right: var(--sp-4); }
  .pagination { padding-left: var(--sp-4); padding-right: var(--sp-4); }
}

/* ── SM 768–1023：侧边栏收成 64px（图标列），内容区 padding 16 ────────── */
@media (max-width: 1023px) {
  .sidebar { width: var(--sidebar-w-collapsed); }
  .sidebar-nav { padding: var(--sp-2) var(--sp-2); }

  /* 折叠态：分组标题整块隐藏，改由 .nav-group-sep 画 1px 分隔线
     （64px 宽下标题会被压成竖排/截成"客户…"，这是最丑的死法 —— layout-spec §1.4） */
  .nav-group-title { display: none; }
  .nav-group-sep { display: block; }
  .nav-item {
    justify-content: center;
    padding: 0;
    gap: 0;
  }
  .nav-item > span:first-child { width: auto; }
  .nav-item > span:last-child,
  .nav-item .nav-text { display: none; }

  /* LOGO：收起态只保留图标位（刀 2 起 logo 是 <img>/<svg> + .logo-text，
     文字直接 display:none，不再依赖 text-overflow —— flex 容器的匿名文本项
     是切不出省略号的，旧做法会硬切半个字） */
  .sidebar-logo {
    display: flex;
    justify-content: center;
    padding: 0;
  }
  .sidebar-logo .logo-text { display: none; }

  /* 底部：退出登录已移到顶栏用户菜单，64px 图标列里没有可放文字的位置 */
  .sidebar-footer { display: none; }

  .content { padding: var(--sp-4); }
  .topbar { padding: 0 var(--sp-4); }

  /* 详情双栏在 SM 折成单栏（Phase 2 §7） */
  .detail-grid,
  .two-col { display: block; }
  .detail-grid > *,
  .two-col > * { width: 100%; margin-bottom: var(--card-gap); }

  /* 字段三列/两列在小屏折行 */
  .form-row .form-group { min-width: 160px; }
}

/* ── XS <768：进一步压缩；表格保持横向滚动 ───────────────────────────── */
@media (max-width: 767px) {
  /* 抽屉态（layout-spec §1.5）：侧边栏脱离文档流，默认移出视口，由 .open 拉回。
     252px 比 232px 宽，因为抽屉要恢复分组标题（不留 64px 的图标列）。 */
  .sidebar {
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    width: 252px;
    z-index: var(--z-sidebar);
    transform: translateX(-100%);
    transition: transform var(--dur-slow) var(--ease-std);
  }
  .sidebar.open,
  .sidebar.is-open { transform: translateX(0); }
  /* 抽屉宽 252px，把 SM 折叠态隐藏的东西全部恢复 */
  .sidebar-logo { justify-content: flex-start; padding: 0 10px; }
  .sidebar-logo .logo-text { display: block; }
  .sidebar-footer { display: flex; }
  .nav-group-title { display: flex; }      /* 252px 下恢复分组标题 */
  .nav-group-sep { display: none; }
  .nav-item { justify-content: flex-start; padding: 0 10px; gap: 10px; }
  .nav-item > span:last-child,
  .nav-item .nav-text { display: block; }
  .main-area { width: 100%; }
  .sidebar-mask { display: none; background: var(--mask); }
  .sidebar-mask.open { display: block; }

  .content { padding: var(--sp-4); }
  .topbar { padding: 0 var(--sp-3); }
  .topbar h1, .topbar h2, .topbar .page-title { font-size: var(--fs-lg); line-height: var(--lh-lg); }

  .card-pad,
  .card-body { padding: var(--sp-3); }
  .card-header { padding: var(--sp-2) var(--sp-3); min-height: 48px; }
  .stat-grid, .overview-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--sp-2); }
  .stat-card, .overview-item { padding: var(--sp-3); }
  .stat-card .stat-value { font-size: 22px; line-height: 30px; }

  .search-wrap { width: 100%; }
  .search-wrap--fluid { width: 100%; }

  .pagination { padding: var(--sp-2) var(--sp-3); justify-content: center; }
  .pagination .page-list { margin-left: 0; }

  .btn-bar { gap: var(--sp-1); }
  .modal { width: 100%; max-height: 92vh; }
  .modal-mask { padding: var(--sp-3); }
  .modal-header, .modal-body, .modal-footer { padding-left: var(--sp-4); padding-right: var(--sp-4); }

  .toast { left: var(--sp-3); right: var(--sp-3); min-width: 0; max-width: none; top: var(--sp-3); }
  .toast + .toast { top: 74px; }

  .stepper { height: auto; flex-wrap: wrap; gap: var(--sp-2); }
  .step-line { display: none; }

  /* 表格：单元格内边距收紧，仍横向滚动
     ⚠ Phase 2 §7 的"<td> 卡片化"依赖每个 td 带 data-label，
       刀 1 不改 JS 补不出 data-label，强行卡片化会出现一排没有标签的空行，
       故本刀在 XS 保持横向滚动，数据不丢。刀 3 补 data-label 后放开这段。 */
  .table thead th,
  .data-table thead th { padding: 8px var(--sp-3); }
  .table tbody td,
  .data-table tbody td { height: 44px; padding: 10px var(--sp-3); }
  .table-compact tbody td { height: 38px; padding: 8px var(--sp-2); }
}

/* ── XL ≥1600：内容区收口已在 §4 处理，此处补卡片间距呼吸 ─────────────── */
@media (min-width: 1600px) {
  .content { padding: var(--sp-6) var(--sp-8); }
}

/* 打印：去掉阴影与固定滚动，保证打印出完整表格 */
@media print {
  .sidebar, .topbar, .toolbar, .pagination, .batch-bar, .btn-bar { display: none !important; }
  .app { height: auto; overflow: visible; }
  .content { overflow: visible; padding: 0; }
  .card { box-shadow: none; border-color: #ccc; break-inside: avoid; }
  .table thead th { position: static; }
}


/* =============================================================================
   §16  自检表（98 个 class + 刀 1 新增类的落位与豁免）
   -----------------------------------------------------------------------------
   验收口径：inventory 里每个 class 都能在下列分区找到规则，或在此说明豁免。
   纯 JS 钩子（只被 querySelector 用来取值、无视觉职责）标注为"豁免"，但仍给了
   最小必要规则以避免浏览器默认样式意外外露。

   ── 骨架（9）────────────────────────────────────────────────────────────
   app              §4  .app
   sidebar          §4  .sidebar（232px / --teal-900 / 五档断点）
   sidebar-logo     §4  .sidebar-logo
   sidebar-nav      §4  .sidebar-nav（含深色滚动条）
   nav-item         §4  .nav-item 三态（实色浮块 + inset 描边环，无左边框条）
   sidebar-footer   §4  .sidebar-footer
   main-area        §4  .main-area
   topbar           §4  .topbar（56px / sticky / 唯一页面标题）
   content          §4  .content（唯一滚动容器）

   ── 容器（9）────────────────────────────────────────────────────────────
   card             §5  .card
   card-header      §5  .card-header（52px / h3 收敛到 14px）
   card-pad         §5  .card-pad
   card-flush       §5  .card-flush（刀 1 新增）
   stat-grid        §5  .stat-grid
   stat-card        §5  .stat-card（+ .stat-card--compact 新增修饰符）
   stat-icon        §5  .stat-icon（改成绝对定位 20px / opacity .35）
   stat-label       §5  .stat-label
   overview-grid    §5  .overview-grid（旧工作台组件，作为 stat-grid 别名保留）
   overview-item    §5  .overview-item（同上；刀 3 合并到 stat-card 后可删）

   ── 表格（9）────────────────────────────────────────────────────────────
   data-table       §6  与 .table 共用同一套选择器
   table            §6  同上（旧 CSS 完全缺失，这是审计缺陷 1）
   row-actions      §6  右对齐 + nowrap + 按钮间距
   perm-matrix      §6  只留横线 + 首列 sticky left；表头 sticky **仅在 .table-wrap--tall 内**生效
   role-name        §6  .perm-matrix .role-name + .role-name
   phrase-thumb     §6  缩略图统一裁切/占位底
   asset-thumb      §6  同上
   copywriting-thumb§6  同上
   pcat-check       §6  复选框光标（其余为 JS 选择器职责）

   ── 按钮（8 + 新增 4）───────────────────────────────────────────────────
   btn              §7  基类（36px / 500 字重 / inline-flex）
   btn-primary      §7
   btn-secondary    §7  新增
   btn-ghost        §7  改为无底无描边（§2.5）
   btn-danger       §7
   btn-success      §7  已废弃变体：映射为主按钮外观（见 §7 注释，刀 3 删）
   btn-text         §7  新增（+ btn-text-danger）
   btn-sm          §7
   btn-xs          §7
   btn-icon/icon-btn §7 32×32 纯图标按钮
   btn-bar          §7  按钮组

   ── 表单（16）───────────────────────────────────────────────────────────
   form-group       §8
   form-control     §8  含 textarea / select / disabled / error
   form-row         §8
   search-box       §8
   search-wrap      §8  （240px 固定宽 + .search-wrap--fluid 全宽修饰符）
   search-icon      §8  （绝对定位 16px，pointer-events:none）
   chip-group       §8
   chip             §9  含 .chip.on / .chip.active 选中态
   tag-chip         §9  与 .chip 共用规则 + .tag-chip.active
   opt-cards        §8
   opt-card         §8  含 .opt-card.on
   tag-input-row    §8
   tag-list         §8
   tag-pill         §8
   tag-x            §8
   tag-dot          §8  6px 分类色点（+ --lg / 5 个语义修饰符）
   tag-filter-row   §8  横滚筛选行
   filter-input     §8  新增 140px
   filter-input-sm  §8  新增 110px
   filter-select    §8  新增 160px

   ── 徽章（8 种写法）─────────────────────────────────────────────────────
   badge                    §9 基类 = 中性灰（全文件唯一一次定义）
   badge info / .info       §9 信息
   badge success/.success   §9 成功
   badge danger/.danger     §9 危险
   badge-warning/.warning   §9 警告（旧缺失）
   badge-muted/.muted       §9 弱化（旧缺失）
   badge-info               §9 纯前缀写法
   badge-success            §9 纯前缀写法

   ── 状态与提示（9）──────────────────────────────────────────────────────
   empty            §11 三段式容器
   empty-icon       §11 新增 64px 图标盘
   empty-title      §11 新增
   empty-desc       §11 新增
   loading          §11 文字占位（骨架由 .skeleton 承担）
   skeleton         §11 新增（脉冲动画 + 3 个形状类）
   hint             §11 收敛为中性提示；#loginHint/#pwdHint 显式标红
   field-hint       §11 + .warn
   warn             §11
   text-muted       §11
   label            §5 .overview-item .label / §13 .about-list .label（按容器作用域，
   value               不做全局 .label/.value，避免影响 <label> 元素与其它同名 span）
   sub              §11

   ── 弹窗（4 + 容器 2）──────────────────────────────────────────────────
   modal            §12（520px / 88vh / flex 纵向）
   modal-mask       §12
   modal-header     §12
   modal-body       §12
   modal-footer     §12
   modal-close      §12 改成 32×32 图标按钮

   ── 文档列表 / 关于（5）─────────────────────────────────────────────────
   doc-list / doc-title / doc-meta / doc-content   §13
   about-list       §13（96px label 右对齐 + value 左对齐）

   ── 脚本向导（9）───────────────────────────────────────────────────────
   wiz-top / wiz-title / wiz-steps / wiz-guide / wiz-footer   §13
   wiz-step（+ .done / .cur 动态修饰符）                      §13
   script-content / gen-note / gen-toolbar / gen-loading      §13

   ── 日志 / 回复（3 + 4 修饰符）─────────────────────────────────────────
   cp-wrap / cp-blocks / cp-value   §13
   cp-red / cp-yellow / cp-green / cp-blue   §13（.cp-block.on 上色）

   ── 登录（2）───────────────────────────────────────────────────────────
   login-wrap / login-card   §14

   ── 批量（4，豁免）──────────────────────────────────────────────────────
   batch-tag / pi-member / pi-tag / pm-member
        豁免：这是 4 组原生 <input type="checkbox"> 的 JS 选择器钩子
        （querySelectorAll('.pi-member:checked')），视觉完全由原生控件承担，
        父级 <label> 带内联样式。为一致性只加 accent-color + cursor，
        不加尺寸/背景，避免破坏弹窗里的行内排布。

   ── 刀 1 新增（Phase 1/2 要求，为刀 2/3 预留，当前 DOM 未渲染不报错）────
   table-wrap                         §6  模式 A：只横滚，表头不吸顶
   table-wrap--tall                   §6  模式 B：限高 + 表头吸顶 + 末列吸右（+ --tall-2row）
   table-wrap--vscroll                §6  早期命名别名，等价于 --tall
   table--wide                        §6  7+ 列宽表，min-width 964
   table-2line                        §6  双行单元格（22+18+10+10 = 60）
   row-empty / empty-row              §6  筛选无结果行（colspan 合法场景）
   cell-clamp-2 / cell-text / cell-wrap  §6  长文本折行逃生口（刀 3 补类）
   table-compact / table-comfortable  §6
   toolbar / toolbar-left / toolbar-right / toolbar-filters / toolbar-count  §10
   page-tabs / page-tab / tab / tabs / tab-count / tabs-vertical            §10
   pagination / page-btn / page-ellipsis / page-info / page-size            §10
   batch-bar / batch-bar__count / batch-bar__actions                        §10
   dropdown / dropdown-menu / dropdown-item / dropdown-divider              §10
   stepper / stepper-item / step-dot / step-label / step-line               §10
   avatar / avatar-sm / avatar-lg                                          §10
   detail-head / detail-name / detail-sub / detail-actions                 §10
   split-2 / split-2--form            §10  360px + minmax(0,1fr)，≤1023 折单列
   group-label                        §10  12px/500/--gray-600 分组小标题
   nav-group-title                    §4   12px/500/--ink-group + 0.06em
   breadcrumb / ico（.ico 尺寸随按钮与导航继承）                              §4 / §7
   login-split / login-aside / login-main（刀 2 左右分栏预留）                §14

   ── v1.1 三处硬伤修复（820 竖排字 / 更新时间折行 / ghost 可点性）────────
   ① 窄容器不压字   §6  table 的 min-width 720（宽表 964）+ .card-pad:has(>table)
                        自己横滚（≤1023 再兜一层不带 :has() 的宽规则）
   ② 短值不折行     §6  tbody td 打底 nowrap；纯文本单元格 260px 省略号；
                        .cell-text / .cell-wrap / .cell-clamp-2 打开折行
   ③ ghost 可点     §7  无底无描边成立的前提：hover 有 --gray-100 底 + 文字
                        转 --gray-800，padding 8px，靠 .btn-bar 的 gap:8px 分间距

   ── 刀 2 已渲染的骨架类（此前为刀 2 预留）────────────────────────────────
   content-inner（#pageContent 挂这层）/ topbar-left / topbar-right            §4
   page-title / crumb-group / crumb-sep / crumb-title（「分组名 · 页面标题」）  §4
   user-menu / user-trigger / user-name（<details> 原生头像菜单）/ sidebar-mask §4
   topbar-burger（仅 <768）/ nav-group-sep（折叠态分隔线）/ sidebar.open 抽屉   §4
   nav-item > .ico / .nav-text / logo-img / dropdown-item.is-danger           §4 / §12
   btn-block（100% × 40px）/ w-date 132 / w-select 168 / w-key 220 / w-search 240
                                                                            §7 / §8
   stat-card--compact（值 20px，默认 28px）                                  §5
   empty-icon / empty-title / empty-desc / skeleton（三段式空态 + 骨架）      §11
   ========================================================================== */


/* =============================================================================
   §17  刀 3 追加（只追加，不改刀 1 已有规则）
   -----------------------------------------------------------------------------
   五个重点页模板落地后需要的少量配套：话术工作台两栏换位、7 列表格的
   合并单元格、details 下拉、chip 横滚行。全部是新类，不影响其他页面。
   ========================================================================== */

/* ── 话术工作台两栏（.split-2.qp-split）──────────────────────────────────
   DOM 顺序 = 列表在前、AI 面板在后（<1200 单列时列表在上，手机主任务是复制话术）；
   桌面端用 grid-column 换位回「左 AI(360px) 右列表(1fr)」。
   ⚠ AI 面板内部有 position:sticky，依赖 .content 唯一滚动 —— 这里不能加 overflow。 */
.split-2.qp-split > .qp-list-pane { grid-column: 2; grid-row: 1; min-width: 0; }
.split-2.qp-split > .qp-assist-pane { grid-column: 1; grid-row: 1; min-width: 0; }
@media (max-width: 1199px) {
  .split-2.qp-split { grid-template-columns: minmax(0, 1fr); }
  .split-2.qp-split > .qp-list-pane,
  .split-2.qp-split > .qp-assist-pane { grid-column: auto; grid-row: auto; }
}

/* ── chip 横滚行（分类/标签点选）────────────────────────────────────── */
.chip-row {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--sp-2);
  overflow-x: auto;
  padding-bottom: var(--sp-1);
  margin-bottom: var(--sp-3);
  -webkit-overflow-scrolling: touch;
}
.chip-row .chip { flex: none; }

/* ── 数据中心 20px 线性图标（stat-icon 容器内）────────────────────────── */
.stat-ico { width: 20px; height: 20px; color: var(--gray-400); }

/* ── 筛选下拉窄档（归属 120px；分类/模块用默认 .filter-select 168px）──── */
.filter-select--sm { width: 120px; }

/* ── 7 列话术表（.data-table.table--wide.table-2line）────────────────── */
.col-check { width: 40px; text-align: center; }
.col-check input[type="checkbox"] { vertical-align: middle; }
/* 列 2 话术：行1 = 32px 缩略图(有图才有) + 标题；行2 = 内容单行省略。
   max-width 是给自动表格布局的"列宽上限"——没有它长内容会把列撑到 400px+，
   964px 总宽就守不住；260/168 两档按 §2.4 定稿列宽倒推（含 28px 单元格内边距）。 */
.table .ph-main,
.data-table .ph-main {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  max-width: 232px;
}
.ph-main .phrase-thumb { width: 32px; height: 32px; flex: none; }
.ph-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
  color: var(--gray-900);
}
.ph-sub,
.table .ph-sub,
.data-table .ph-sub {
  max-width: 232px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 列 3 分类与标签：行2 = 最多 2 个色点 + 「+N」 */
.table .ph-cats,
.data-table .ph-cats {
  max-width: 140px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ph-tags { display: block; }
.table .ph-tags,
.data-table .ph-tags { max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ph-tags .tag-dot { margin-right: 4px; vertical-align: middle; }
/* 列 4 归属行 2：来源 · 负责人 */
.table .ph-own,
.data-table .ph-own { margin-bottom: 2px; }

/* ── <details> 下拉（原生零 JS；.dropdown-menu 平时 display:none，
   必须补 details[open] 分支才显示）────────────────────────────────────── */
details.dropdown[open] > .dropdown-menu,
details.dropdown[open] > summary + .dropdown-menu { display: block; }
.dropdown > summary { list-style: none; }
.dropdown > summary::-webkit-details-marker { display: none; }
.dropdown > summary::marker { content: ''; }
/* 行内「⋯」更多：32px 图标钮，与「编辑」文字按钮基线对齐 */
.row-more { margin-left: var(--sp-1); }
.row-more > summary { cursor: pointer; }
