/* 线索管理页组件样式（ui-ux-pro-max 重构）
 * 全部走 --zway-* 设计令牌，自动适配绿/蓝/橙/灰主题。
 * 规范要点：徽章文本 nowrap 不换行；状态表达不只靠颜色（图标/文字并行）；
 * 交互控件有 hover/focus-visible 反馈；间距按 4/8 节奏。
 */

/* ── 页首统计卡片区（M8 重新设计）───────────────────────────
 * 扁平设计：无厚重阴影，1px 边框 + 底部语义色条；hover 仅位移/边框变化，
 * 过渡 150-200ms；数字用大字重建立层级；卡片可下钻（button 语义 + aria-pressed）。
 */
.clue-stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
  gap: 12px;
  margin-bottom: 14px;
}

.clue-stat-card {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  min-height: 96px;
  padding: 14px 16px;
  border: 1px solid var(--zway-border);
  border-radius: var(--zway-radius-md);
  background: var(--zway-surface);
  text-align: left;
  overflow: hidden;
  transition: transform 160ms ease, border-color 160ms ease, box-shadow 160ms ease;
}
/* 底部语义色条：状态表达不只靠图标颜色 */
.clue-stat-card::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 3px;
  background: var(--_stat-accent, var(--zway-border-strong));
  opacity: 0.55;
  transition: opacity 160ms ease;
}
button.clue-stat-card { cursor: pointer; font: inherit; color: inherit; }
button.clue-stat-card:hover {
  transform: translateY(-2px);
  border-color: var(--_stat-accent, var(--zway-border-strong));
  box-shadow: var(--zway-shadow-sm, 0 6px 16px rgba(15, 23, 42, 0.07));
}
button.clue-stat-card:hover::after { opacity: 1; }
button.clue-stat-card:active { transform: translateY(0); }
button.clue-stat-card:focus-visible {
  outline: 2px solid var(--zway-primary);
  outline-offset: 2px;
}
/* 选中态（当前筛选生效）：左侧主色标记 + 轻底色，与 aria-pressed 同步 */
button.clue-stat-card.active {
  border-color: var(--_stat-accent, var(--zway-primary));
  background: color-mix(in srgb, var(--_stat-accent, var(--zway-primary)) 6%, var(--zway-surface) 94%);
}
button.clue-stat-card.active::after { opacity: 1; }

.clue-stat-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: var(--zway-radius-sm);
  flex: none;
  background: color-mix(in srgb, var(--_stat-accent, var(--zway-text-muted)) 10%, var(--zway-surface) 90%);
  color: var(--_stat-accent, var(--zway-text-muted));
}
.clue-stat-icon svg { width: 19px; height: 19px; }

.clue-stat-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.clue-stat-label { font-size: var(--zway-font-size-xs); font-weight: 600; color: var(--zway-text-muted); white-space: nowrap; }
.clue-stat-value { font-size: clamp(22px, 1.9vw, 28px); line-height: 1.1; font-weight: 700; color: var(--zway-text); font-variant-numeric: tabular-nums; }
.clue-stat-hint { font-size: var(--zway-font-size-xs); color: var(--zway-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* 语义色调（令牌化，随主题切换） */
.clue-stat-primary { --_stat-accent: var(--zway-primary); }
.clue-stat-info { --_stat-accent: var(--zway-info, var(--zway-primary)); }
.clue-stat-success { --_stat-accent: var(--zway-success); }
.clue-stat-warning { --_stat-accent: var(--zway-warning); }
.clue-stat-danger { --_stat-accent: var(--zway-danger); }
.clue-stat-dark { --_stat-accent: var(--zway-surface-inverse); }
.clue-stat-muted { --_stat-accent: var(--zway-text-muted); }
/* 警示卡有存量时hint加强可读性 */
.clue-stat-warning .clue-stat-value { color: var(--zway-warning); }

.clue-stats-error {
  grid-column: 1 / -1;
  padding: 14px 16px;
  border: 1px dashed var(--zway-border-strong);
  border-radius: var(--zway-radius-md);
  color: var(--zway-text-muted);
  font-size: var(--zway-font-size-sm);
  text-align: center;
}

/* 渠道转化漏斗：卡片间距；漏斗本体样式统一放在 assets/styles.css 的 .clue-funnel-* 段落 */
.clue-funnel-card { margin-top: 16px; }

@media (max-width: 640px) {
  .clue-stats-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .clue-stat-card { min-height: 88px; padding: 12px; gap: 10px; }
  .clue-stat-icon { width: 32px; height: 32px; }
}

/* 减少动态偏好：禁用位移动画，保留颜色反馈 */
@media (prefers-reduced-motion: reduce) {
  .clue-stat-card, .clue-stat-card::after { transition: none; }
  button.clue-stat-card:hover { transform: none; }
}

/* ── 页面容器与筛选栏 ─────────────────────────────── */
.clue-list-card .section-title h3 { margin: 0; }

.clue-filters {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap; /* 筛选控件在空间不足时换行，不挤压不裁剪 */
  margin-bottom: 12px;
}
.clue-filters input[type="search"], .clue-filters input:not([type]) { flex: 1; min-width: 200px; }
/* 全局 select{width:100%} 会把筛选下拉撑成整行堆叠；筛选栏内恢复自适应宽度，保持单行工具栏布局 */
.clue-filters select { width: auto; min-width: 120px; }

.clue-batch-toolbar > div {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
  padding: 12px 16px;
  margin-bottom: 8px;
  border: 1px solid var(--zway-border);
  border-radius: var(--zway-radius-md);
  background: var(--zway-surface-muted);
}
.clue-batch-toolbar label { display: inline-flex; align-items: center; gap: 6px; padding: 4px 6px; border-radius: var(--zway-radius-sm); font-size: var(--zway-font-size-sm); color: var(--zway-text-muted); }
.clue-batch-toolbar label:hover { background: var(--zway-surface); }
.clue-batch-toolbar select { width: auto; min-width: 140px; }

/* ── 表格 ────────────────────────────────────────── */
/* 错位根因（三条全局规则压过线索表自身的 0-1-x 规则）：
 *   1) `.table-wrap thead th:nth-child(1)/:nth-child(2)`（特异性 0-2-1）覆盖了
 *      `.clue-table thead th`（0-1-2）：首列左右 padding 变成 10/6、次列 8/8，
 *      而第 3 列起走 `tbody td` / `thead th`（0-0-2）的 14/14
 *      → 表头各列文字左边界逐列跳变，与正文也对不齐。
 *   2) `table tbody tr:nth-child(even){background:…!important}`（0-1-2 + !important）
 *      把项目/合同表的斑马纹漏进了线索表（本表设计无斑马纹，靠 hover 区分行）。
 *   3) `.next-action-cell{min-width:300px}`（0-1-0）在 11 列布局里没有对手，
 *      逐行把表格撑到 1608px，与视口宽度无关 → 只能在窄框里横滑。
 * 解法：表格规则整体收进 `#clues` 作用域（特异性 1-1-x）无条件压过上述全局规则；
 *      斑马纹用 !important 反制；列宽交给 <colgroup> + table-layout:fixed 统一分配。
 */
.clue-table {
  width: 100%;
  /* 11 列的绝对需求（日期 130、电话 127、状态 93…）与容器宽度无关，
     故给表格一个下限宽度：容器宽于 1080px 时按百分比铺满（1440 视口实测容器 1116px，无横滑）；
     窄于 1080px 时保持列宽、改由 .table-wrap 横向滚动，而不是把列压到日期折断。
     768px 以下交给卡片模式，届时 min-width 归零。
     ⚠️ 2026-09-16 删列后未下调这个下限：删「最近跟进」后绝对值合计已 <1000px，理论上可降到
        ≈970px，但那会让 970~1080px 的容器从「横滑」变成「压缩列」，是本次未被要求的行为变更。 */
  min-width: 1080px;
  table-layout: fixed;
  border-collapse: collapse;
}
/* 列宽轨道：与 index.html 的 <colgroup> 类名一一对应。**改列宽只动这一段。**
   比例依据（1080px 下限宽度下逐列实测「最小必需宽」后重新分配）：
   日期列要放满「2026-09-16 14:50」16 字符、电话列要放 11 位号码 + 通话按钮、
   联系人列要放姓名 + 微信按钮、操作列最多 3 个图标按钮、状态列要放不换行的芯片。
   名称 / 下一步是变长内容，走单行省略号 + title 悬停，属于设计内截断。
   ⚠️ 产品列 4.2% → 10.8%（≈45px → 117px @1080）：产品列显示的是
   `产品线 · 产品类型 · 产品` 三段拼接（生产实测 17~19 字符、最长 30），
   4.2% 时可用宽仅 25px、只放得下 1 个中文字。详见下面 .clue-product-cell 注释。
   本次腾挪的额度来自**逐列实测的最小必需宽**（1080px 下，注意联系人/电话/操作的
   图标按钮是绝对定位、不参与 td 自然宽计算，不能用「整列自然宽」估；实测最小必需宽：
   序号 33、勾选 28、状态 86（芯片 66+内距）、负责人 58、操作 78、
   联系人 91、电话 123 —— 均为「文本完整 + 图标按钮不压文本」的下限）。
   合计腾出 ≈78px 给产品列；名称列 10.4%→9.5%（112→103px，约少显示半个多汉字，
   其单行省略号 + title 悬停行为与之前一致）。
   ⚠️ 产品列改到 11.2% 是「2 行能放下 19 字符」的下限：11.1% 时 1080 宽下会差 1px 截断。

   ── 2026-09-16：删「最近跟进」列，12 列 → 11 列 ──────────────────
   该列展示的 lastFollowupAt（服务端 MAX(clue_followups.followup_time)）与「最近动作」列
   语义重复（后者本就取「更新时间 vs 最近跟进时间」的较新者），用户要求只留「最近动作」。
   删除后腾出的 11.6% 按「补足下限 → 让给变长文本列」两段重分配（合计仍恒为 100%）：
   ① 补足实测最小必需宽（原先 12 列挤到 100%，这三列实际都差了 0.5~1px）：
      联系人 8.4→9.0（97px，下限 91）、电话 11.3→11.6（125px，下限 123）、
      操作 7.2→7.7（83px，下限 78）。
   ② 其余全部让给最常被截断的变长文本列：
      名称 9.5→14.5（103→157px，+54px，单行省略号触发率大幅下降）、
      下一步 10.0→13.0（108→140px，动作文案 + 计划日期的可读性提升）、
      产品 11.2→12.5（121→135px，在 11.2% 的「19 字符下限」之上留出安全余量）、
      最近动作 11.6→12.5（125→135px，接棒「最近跟进」后给足呼吸感即可）。
   ⚠️ 改这一段必须同步改 index.html 的 <colgroup>，两边类名一一对应、数量必须相等；
      忘记改 colgroup 会让后续所有列整体错位一格（表格仍是 11 个 col 对 11 个 th 才不漂移）。 */
.clue-col-index { width: 3.1%; }
.clue-col-check { width: 2.7%; }
.clue-col-name { width: 17%; }
.clue-col-product { width: 12.5%; }
.clue-col-contact { width: 9.0%; }
.clue-col-phone { width: 11.6%; }
.clue-col-status { width: 8.0%; }
.clue-col-owner { width: 5.4%; }
.clue-col-lastaction { width: 11.5%; }
.clue-col-next { width: 12.0%; }
.clue-col-ops { width: 7.7%; }

/* 表头 / 正文共用同一套盒模型：左右内边距统一 10px，文字左边界必然对齐。
   ⚠️ 必须带 !important：全局另有一条
   `.table-wrap tbody td{…padding-top:12px!important;padding-bottom:12px!important;vertical-align:top!important}`
   把正文上下内边距抬到 12px、对齐改成 top，而表头那条是 10px!important —— 两者差 2px，
   这正是「表头与正文文字基线不齐」的直接来源。这里用同等 !important + 更高特异性拉平。 */
#clues .clue-table thead th,
#clues .clue-table tbody td {
  box-sizing: border-box;
  padding: 10px !important;
  line-height: 1.45;
}
#clues .clue-table thead th {
  position: sticky;
  top: 0;
  /* 表格行本身带有 position/z-index 以稳定 hover 层级；表头必须更高，
     否则向上滚动时首行内容会盖住「操作」等表头文字和按钮。 */
  z-index: 6 !important;
  background: var(--zway-surface);
  color: var(--zway-text-muted);
  font-size: var(--zway-font-size-xs);
  font-weight: 600;
  text-align: left;
  vertical-align: middle;
  border-bottom: 1px solid var(--zway-border-strong);
  box-shadow: 0 2px 6px color-mix(in srgb, var(--zway-text) 9%, transparent);
  white-space: nowrap;
}
#clues .clue-table tbody td {
  border-bottom: 1px solid var(--zway-border);
  font-size: var(--zway-font-size-md);
  /* 全局那条把 vertical-align 也钉成了 top!important，这里必须同等反制，
     否则内容在行内顶对齐，与 10px 上边距叠加后视觉重心偏上。 */
  vertical-align: middle !important;
  /* fixed 布局下内容不裁就会画到邻列；单行 + 省略号是 11 列表格的标准做法 */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#clues .clue-table tbody tr {
  position: relative;
  z-index: 0;
  transition: background-color 120ms ease;
}
/* 反制全局斑马纹（那条带 !important，这里必须同样带 !important 才盖得住） */
#clues .clue-table tbody tr:nth-child(even),
#clues .clue-table tbody tr:nth-child(odd) { background: transparent !important; }
#clues .clue-table tbody tr:hover { background: var(--zway-surface-muted) !important; }

/* ── 各列内容排版：一律单行，行高因此收敛为唯一值 ──
 * 表格行高 = 最高的单元格。11 列里只有「下一步」列是刻意两行（动作 + 状态/日期），
 * 其余列全部单行 → 每行都是「两行高」，行高整齐、翻页不跳。
 */
.clue-name-cell { display: flex; align-items: center; gap: 6px; min-width: 0; }
/* 名称允许折 2 行（-webkit-line-clamp 限高，保持「统一两行高」的行高设计）；
   单行省略会把长名称裁成「xxx…」显示不全（2026-09-24 反馈），折行 + 列加宽解决。 */
.clue-name-text {
  min-width: 0;
  font-weight: 600;
  color: var(--zway-text);
  white-space: normal;
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* 产品列：值是 `产品线 · 产品类型 · 产品` 三段拼接（生产实测 17~19 字符、最长 30），
   原 4.2%（≈45px、可用 25px）只能显示 1 个中文字 —— 就是「服…」那个观感。
   现在给到 12.5%（≈135px、可用 115px）并允许折 2 行，配合降一档字号，
   生产全部 17/18/19 字符真实值都能完整显示、并留出余量；30 字符的极端值仍 2 行截断，
   完整值靠 title 悬停。
   ⚠️ 字号降到 sm(12px)：与「最近动作」同一套理由 —— 产品是辅助信息（弱化色），
   12px 下 19 字符值 2 行只需 92px，13px 则要 100px。降档换来的是「名称列少让 1%」。
   ⚠️ 不能改 3 行：3 行文字高 ≈72px（含内距）会超过 68px 的既定行高，
   把行高从单一值变成 68/77 两档，翻页跳行。2 行（≈55px）在 68px 内，行高保持单一。
   ⚠️ white-space 必须显式写 normal：td 基础规则是 nowrap，会被继承 —— 那样根本不换行、
      line-clamp 形同虚设，超长值直接横向溢出被裁（实测踩过，表现为「产品列都只有 1 行」的假象）。 */
.clue-product-cell span {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  white-space: normal;
  word-break: break-word;
  overflow-wrap: anywhere;
  font-size: var(--zway-font-size-sm);
  color: var(--zway-text-muted);
}

.clue-owner-cell { white-space: nowrap; }
/* 最近动作列：辅助信息（弱化色 + 等宽数字 + 小一号字），单行不换行避免日期被折断。
   ⚠️ 2026-09-16：原与本列合并书写的 `.clue-followup-cell`（最近跟进列）已随列删除，
     这里只剩「最近动作」一条 —— 不要再把它拆成分散的多条，否则以后改字号容易漏改。
   字号降到 sm(12px)：16 字符的完整时间戳在 13px 下需 112px 内容宽，是本表最贵的一列；
   降一档后需求降到 ≈103px。
   ⚠️ 必须带 #clues 前缀：下面那条 `#clues .clue-table tbody td{font-size:…md}` 靠 id 权重
   压得住纯 class 选择器（0-2-0），不写 id 这行字号根本不生效（实测踩过）。 */
#clues .clue-table tbody .clue-updated-cell {
  white-space: nowrap;
  color: var(--zway-text-muted);
  font-size: var(--zway-font-size-sm);
  font-variant-numeric: tabular-nums;
}

/* 联系人 / 电话列：文本 + 一个图标按钮同处一格。
   ⚠️ 不能把 td 设成 display:flex —— td 一旦脱离 table-cell，fixed 布局的列宽轨道立刻失效。
   改为：文本块右侧留出按钮位（padding-right），按钮绝对定位贴右并垂直居中。 */
.clue-table .clue-contact-cell,
.clue-table .clue-phone-cell { position: relative; padding-right: 38px; }
.clue-table .clue-contact-cell .clue-cell-text,
.clue-table .clue-phone-cell .clue-cell-text {
  display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.clue-table .clue-contact-cell .icon-btn,
.clue-table .clue-phone-cell .icon-btn {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
}

/* 「下一步」列：复用项目列表的 .next-action-cell 结构（动作 + 状态标签 + 日期）。
   全局那个类自带 min-width:300px、以及 -webkit-line-clamp:4 —— 照搬会把整表撑到 1608px、
   且动作长的行能长到 4 行（实测最大行高 155px）。此处按项目表同样思路在本作用域内
   解除宽度约束，并把动作文本钳到 1 行，让整列固定为 2 行（动作 1 行 + 状态/日期 1 行）。 */
.clue-table .next-action-cell { width: 100%; min-width: 0; max-width: none; line-height: 1.45; }
.clue-table .next-action-main {
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
  max-width: 100%;
  white-space: normal;
  word-break: break-word;
  overflow-wrap: anywhere;
}
.clue-table .next-action-meta { justify-content: flex-start; flex-wrap: nowrap; margin-top: 4px; overflow: hidden; }
/* 状态标签优先完整显示，空间不足时由日期让位（省略号收尾，比被硬切好看）。
   这样「下一步」列稳定为 2 行（动作 1 行 + 状态/日期 1 行），行高不会因长日期跳档。 */
.clue-table .next-action-meta .tag { flex: none; }
.clue-table .next-action-meta .cell-sub {
  min-width: 0;
  flex: 0 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 序号列（首列）：窄列 + 等宽数字，避免两位数（10+）把首列撑开导致其它列抖动；
   编号跨页连续（页偏移 + 行内序号），翻页后仍能对上「第 N 条」。
   宽度统一由上面的 .clue-col-index 决定，这里只管文字样式。 */
.clue-table .clue-index-cell { color: var(--zway-text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* 复选框列：表头与行内都居中，避免勾选框左右漂移。
   ⚠️ 必须显式钉死尺寸：全局 `input,select,textarea{width:100%;padding:9px 12px;border:1px solid…}`
   （特异性 0-0-1，styles.css 表单基础样式）会把这枚 checkbox 也拉成「占满整列宽」的扁长控件
   —— 桌面端实测被撑到整列宽 × 13px，卡片模式（绝对定位、收缩定宽）下更离谱：160px × 13px，
   视觉上几乎只剩一条横线、且触摸命中区只有 13px 高。
   这里用 id 作用域 + 属性选择器（1-2-1，0-1-1）压过全局规则，把控件还原成 16×16。 */
#clues .clue-table .clue-check-head,
#clues .clue-table .clue-check-cell {
  text-align: center;
  /* 本列单独收紧左右内边距：16px 控件 + 两侧 6px = 28px 需求，
     而 3.0% 轨道在 1080px 下限宽度下只给 32.4px —— 余量 4px。
     ⚠️ 不能沿用基础规则的 10px：那样本列需求 36px > 32.4px，勾选框会被裁掉一半
     （实测 td scrollWidth 溢出 16px，1440/1280/992 三个断点全中）。
     表头与正文必须同步收紧，否则「表头/正文内边距一致」这条判据被破坏。
     特异性说明：本条 1-2-0 必须高于 `#clues .clue-table tbody td{padding:10px!important}`（1-1-1），
     故同样带 #clues 前缀 + !important 才压得住。 */
  padding-left: 6px !important;
  padding-right: 6px !important;
}
#clues .clue-table .clue-check-head input[type="checkbox"],
#clues .clue-table .clue-check-cell input[type="checkbox"] {
  width: 16px;
  height: 16px;
  flex: none;
  margin: 0;
  padding: 0;
  vertical-align: middle;
}

/* 操作列：3 个图标按钮（详情 / 转项目 / 归档）必须一行放下，
   在表格作用域内把按钮收紧到 26px、间距 2px，总占位 ≈ 82px。 */
.clue-table .clue-actions { gap: 2px; }
.clue-table .clue-actions .action-link.icon-btn { padding: 3px; min-width: 26px; height: 26px; }

/* ══ 窄屏卡片模式（≤768px）═══════════════════════════════════
 * 实测：430px 视口下容器仅 378px、表格 1608px —— 只能看到前 2~3 列，
 * 「下一步」「操作」要横滑约 1230px，等于关键进度信息在窄屏不可达
 * （ui-ux-pro-max：避免横向滚动，严重度 High；窄屏宽表应改卡片布局）。
 * 这里把每行变成一张卡片：表头隐藏，字段名由 td 的 data-label 渲染到值左侧。
 * ⚠️ 全部字段与操作入口保持原样，只改呈现方式。
 */
@media (max-width: 768px) {
  /* 解除全局在 768px 断点给 .table-wrap 的 max-height:380px 压制，
     否则整张卡片列表被塞进一个 380px 高的内滚动框，反而更难用。 */
  #clues .table-wrap {
    max-height: none;
    border: 0;
    background: transparent;
  }
  #clues .clue-table {
    min-width: 0;
    table-layout: auto;
    display: block;
  }
  /* 卡片模式下列宽轨道与表头都不再需要 */
  #clues .clue-table colgroup,
  #clues .clue-table thead { display: none; }
  #clues .clue-table tbody { display: block; }

  #clues .clue-table tbody tr {
    position: relative;
    display: block;
    margin-bottom: 10px;
    padding: 2px 0;
    border: 1px solid var(--zway-border);
    border-radius: var(--zway-radius-md);
    background: var(--zway-surface) !important;
  }

  #clues .clue-table tbody td {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    /* 基础规则那条 10px 带 !important，这里必须同等 !important 才压得住 */
    padding: 5px 12px !important;
    border-bottom: 0;
    /* ⚠️ 不要放开成 visible：方块内长文本一旦溢出，会把 tbody 的 scrollWidth
       顶大 200px+（实测 590px vs 容器 380px），页面虽被裁住但容器内多出横滑。
       横向交给「文本换行 + min-width:0」解决，纵向这里本来也不裁剪（nowrap 已解除）。 */
    overflow: hidden;
    text-overflow: clip;
    white-space: normal;
  }
  /* 字段名：取值自 app.js 行渲染里写入的 data-label */
  #clues .clue-table tbody td::before {
    content: attr(data-label);
    flex: none;
    width: 60px;
    padding-top: 1px;
    color: var(--zway-text-muted);
    font-size: var(--zway-font-size-xs);
    font-weight: 600;
  }

  /* 空态行（「暂无线索」）不是一个「字段」，不能走上面那条 flex：
     空态 td 没有 data-label，flex 会把整格收缩到内容宽 —— 430px 实测宽 36px、高 624px，
     「暂无线索」被压成竖排、整块看起来像一片空白（2026-09-16 布局重构引入，次日复检发现）。
     这里整行复权为块级，并去掉卡片模式的边框/底色（空态不是一张卡片）。
     ⚠️ 两个类名由 app.js 的空态渲染写入（`tr.clue-empty-row` / `td.clue-empty-cell`），
        改类名必须同步两边，否则这个修复静默失效。 */
  #clues .clue-table tbody tr.clue-empty-row {
    border: 0;
    margin-bottom: 0;
    padding: 0;
    background: transparent !important;
  }
  #clues .clue-table tbody td.clue-empty-cell {
    display: block;
    width: 100%;
    padding: 0 !important;
    overflow: visible;
  }
  #clues .clue-table tbody td.clue-empty-cell::before { content: none; }

  /* 卡片头部：序号在右上角、勾选框在左上角，名称独占一行作标题 */
  #clues .clue-table tbody td.clue-index-cell {
    position: absolute;
    top: 12px;
    right: 14px;
    padding: 0 !important;
    font-size: var(--zway-font-size-xs);
    color: var(--zway-text-muted);
    white-space: nowrap;
  }
  #clues .clue-table tbody td.clue-index-cell::before,
  #clues .clue-table tbody td.clue-check-cell::before,
  #clues .clue-table tbody td.clue-name-col::before,
  #clues .clue-table tbody td.clue-ops-cell::before { content: none; }

  /* 勾选框：卡片模式放大到 18×18、四周 6px 内边距作触摸缓冲（≥ 原来 13px 的命中高度）。
     位置做了补偿（left 12→6、top 15→9），叠加 6px padding 后视觉落点不变。 */
  #clues .clue-table tbody td.clue-check-cell {
    position: absolute;
    top: 9px;
    left: 6px;
    padding: 6px !important;
  }
  #clues .clue-table tbody td.clue-check-cell input[type="checkbox"] {
    width: 18px;
    height: 18px;
  }
  /* 名称独占一行作标题。右侧留白必须 ≥ 序号徽标占位（徽标宽约 36 + right 14 + 间距 8），
     否则长标题会伸到徽标底下（390px 实测重叠 6px，第 4 张卡「…光声小动物活4体成像」）。
     ⚠️ 只加 padding 不够：名称块是 flex 子项、宽度按内容收缩，收缩后的宽度不受 td 内边距约束，
     长标题照样越界。必须同时 width:100% 让它吃满可用宽度，换行才发生在留白之前。 */
  #clues .clue-table tbody td.clue-name-col {
    padding: 13px 58px 9px 40px !important;
    border-bottom: 1px dashed var(--zway-border);
    margin-bottom: 3px;
  }
  #clues .clue-table tbody .clue-name-cell {
    display: block;
    flex: 1 1 auto;
    width: 100%;
    min-width: 0;
  }
  /* 桌面端是单行省略（inline 元素的 overflow 不生效，靠 td 裁切兜住）；
     卡片模式要的是换行，必须显式转成块级，否则 span 会以内容宽撑出父容器。 */
  #clues .clue-table tbody .clue-name-text {
    display: block;
    font-size: var(--zway-font-size-lg);
    white-space: normal;
    overflow-wrap: anywhere;
  }

  /* 内容列：值占满剩余宽度，长文本换行而不是溢出 */
  #clues .clue-table tbody td > * { min-width: 0; }
  #clues .clue-table tbody td > .clue-cell-text,
  #clues .clue-table tbody td > .next-action-cell { flex: 1; }
  /* 联系人 / 电话的图标按钮回到正常文档流（表格里的绝对定位在此不适用） */
  #clues .clue-table tbody td.clue-contact-cell,
  #clues .clue-table tbody td.clue-phone-cell { padding-right: 12px !important; }
  #clues .clue-table tbody td.clue-contact-cell .icon-btn,
  #clues .clue-table tbody td.clue-phone-cell .icon-btn {
    position: static;
    transform: none;
    flex: none;
  }
  /* 卡片模式下「下一步」恢复两行展示（动作一行 + 状态/日期一行），纵向排列。
     卡片宽度足够，不需要再靠 nowrap 压行。 */
  #clues .clue-table tbody .next-action-cell { display: block; width: auto; }
  #clues .clue-table tbody .next-action-main { -webkit-line-clamp: 2; white-space: normal; }
  #clues .clue-table tbody .next-action-meta { flex-wrap: wrap; margin-top: 3px; overflow: visible; }

  /* 操作区：底部整条虚线 + 按钮右对齐，点击目标放大到 32px（触摸友好） */
  #clues .clue-table tbody td.clue-ops-cell {
    margin-top: 3px;
    padding-top: 8px !important;
    border-top: 1px dashed var(--zway-border);
    justify-content: flex-end;
  }
  #clues .clue-table tbody .clue-actions { justify-content: flex-end; gap: 6px; }
  #clues .clue-table .clue-actions .action-link.icon-btn { min-width: 32px; height: 32px; }
  #clues .clue-table .clue-actions .action-link.icon-btn svg { width: 17px; height: 17px; }
}

/* ── 评分等级徽标：药丸形（字母+分值语义配对），非纯色圆点 ── */
.clue-grade {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 22px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: var(--zway-font-size-xs);
  font-weight: 700;
  white-space: nowrap;
  border: 1px solid transparent;
}
.clue-grade-a { background: color-mix(in srgb, var(--zway-success) 12%, var(--zway-surface) 88%); border-color: color-mix(in srgb, var(--zway-success) 30%, var(--zway-border) 70%); color: var(--zway-success); }
.clue-grade-b { background: color-mix(in srgb, var(--zway-warning) 12%, var(--zway-surface) 88%); border-color: color-mix(in srgb, var(--zway-warning) 30%, var(--zway-border) 70%); color: var(--zway-warning); }
.clue-grade-c { background: var(--zway-surface-muted); border-color: var(--zway-border); color: var(--zway-text-muted); }
.clue-grade .clue-score-num { font-weight: 500; opacity: 0.85; }

/* ── 状态芯片：圆点+文字双通道，不只靠颜色 ── */
.clue-status {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-height: 22px;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: var(--zway-font-size-xs);
  font-weight: 600;
  white-space: nowrap;
  border: 1px solid transparent;
}
.clue-status::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
.clue-status-new { background: color-mix(in srgb, var(--zway-primary) 10%, var(--zway-surface) 90%); border-color: var(--zway-primary-border); color: var(--zway-primary); }
.clue-status-following { background: color-mix(in srgb, var(--zway-success) 10%, var(--zway-surface) 90%); border-color: color-mix(in srgb, var(--zway-success) 28%, var(--zway-border) 72%); color: var(--zway-success); }
.clue-status-converted { background: var(--zway-surface-inverse); border-color: var(--zway-surface-inverse); color: var(--zway-text-on-primary); }
.clue-status-unassigned { background: var(--zway-surface-muted); border-color: var(--zway-border); color: var(--zway-text-muted); }
.clue-status-invalid { background: var(--zway-surface-muted); border-color: var(--zway-border); color: var(--zway-text-muted); }
.clue-status-invalid::before { display: none; }
.clue-status-lost { background: color-mix(in srgb, var(--zway-danger) 8%, var(--zway-surface) 92%); border-color: color-mix(in srgb, var(--zway-danger) 26%, var(--zway-border) 74%); color: var(--zway-danger); }

/* 公海/私有池芯片（.clue-pool-chip*）已随公海概念下线移除：B 端不做掉池倒计时 */

/* ── 行内操作组：主次分明，归档弱化为 danger 文本 ── */
.clue-actions { display: flex; align-items: center; gap: 2px; white-space: nowrap; }
.clue-actions .action-link { padding: 4px 6px; border-radius: var(--zway-radius-sm); }
.clue-actions .action-link:focus-visible { outline: 2px solid var(--zway-primary); outline-offset: 1px; }
.clue-actions .action-link.primary { font-weight: 700; }
/* 纯图标操作按钮 */
.clue-actions .action-link.icon-btn { padding: 4px; min-width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center; border-radius: var(--zway-radius-sm); background: transparent; border: 1px solid transparent; transition: background .12s, border-color .12s, color .12s; }
.clue-actions .action-link.icon-btn:hover { background: var(--zway-surface-muted); border-color: var(--zway-border-strong); }
.clue-actions .action-link.icon-btn.primary:hover { background: color-mix(in srgb, var(--zway-primary) 10%, var(--zway-surface)); border-color: color-mix(in srgb, var(--zway-primary) 30%, var(--zway-border)); color: var(--zway-primary); }
.clue-actions .action-link.icon-btn.danger:hover { background: color-mix(in srgb, var(--zway-danger) 10%, var(--zway-surface)); border-color: color-mix(in srgb, var(--zway-danger) 30%, var(--zway-border)); color: var(--zway-danger); }
.clue-actions .action-link.icon-btn svg { width: 15px; height: 15px; }

/* ── 空态：图标+引导文案+主操作 ── */
.clue-empty { padding: 40px 16px; text-align: center; color: var(--zway-text-muted); }
.clue-empty svg { width: 40px; height: 40px; opacity: 0.45; margin-bottom: 8px; }
.clue-empty-title { font-size: var(--zway-font-size-lg); font-weight: 600; color: var(--zway-text); margin-bottom: 4px; }
.clue-empty-hint { font-size: var(--zway-font-size-sm); }

/* ── 线索详情样式已迁至 styles.css ─────────────────────────
   详情已由「通用弹窗」改为「抽屉」，与「新增线索」抽屉共用同一套设计语言
   （styles.css 里 :is(#clueDrawer,#clueDetailDrawer) 段落 + #clueDetailDrawer .clue-dt-* 段落）。
   本文件只保留线索**列表**与跟进**编辑表单**（通用弹窗内）的样式，避免两处定义漂移。
   ──────────────────────────────────────────────── */

/* 跟进方式芯片：详情时间线仍在使用（颜色由 styles.css 的详情段落微调） */
.clue-method-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: var(--zway-radius-sm);
  background: var(--zway-surface-muted);
  border: 1px solid var(--zway-border);
  font-size: var(--zway-font-size-xs);
  color: var(--zway-text-muted);
  white-space: nowrap;
}
.clue-method-chip svg { width: 13px; height: 13px; }

/* 通话信息子表单（通用弹窗内，选「电话」时展开） */
.clue-call-extra {
  padding: 10px 12px;
  border: 1px dashed var(--zway-border);
  border-radius: var(--zway-radius-sm, 8px);
  background: var(--zway-surface-muted);
}
.clue-call-extra-title {
  font-size: var(--zway-font-size-sm);
  font-weight: 600;
  color: var(--zway-text);
  margin-bottom: 8px;
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}
.clue-call-extra-title span { font-weight: 400; font-size: var(--zway-font-size-xs); color: var(--zway-text-muted); }
.clue-call-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px; }
.clue-call-hint { margin-top: 8px; font-size: var(--zway-font-size-xs); color: var(--zway-text-muted); line-height: 1.5; }

/* 线索名称：可作为进入详情抽屉的按钮 */
.clue-name-link { cursor: pointer; }
.clue-name-link:hover { color: var(--zway-primary, #16713b); text-decoration: underline; }
.clue-name-link:focus-visible { outline: 2px solid var(--zway-primary, #16713b); outline-offset: 2px; border-radius: 4px; }

@media (max-width: 640px) {
  .clue-filters select { min-width: 0; flex: 1; }
}
