/* ============================================================
 * components.css —— 共享组件层（设计系统 / Design System）
 * ------------------------------------------------------------
 * 目的：把跨多个页面共用的 UI 组件（表格、按钮、表单、弹窗、标签等）
 *       集中定义「一次」，所有子页面 / 模块直接 class 引用，
 *       杜绝「同一个问题在 N 个页面重复改」（如今天表头穿模反复修）。
 *
 * 加载顺序（见 index.html）：
 *   tokens.css  →  base.css  →  components.css  →  modules/*.css
 * 后者可覆盖前者；modules 为各业务模块独有样式，互不污染。
 * ============================================================ */

/* ---------- 官方表格组件 .data-table ----------
 * 所有列表页统一由 app.js 的 renderTable() 生成 <table class="data-table">。
 * 表头吸顶 + 显式背景集中于此：未来调整表头高度 / 背景 / 边框，
 * 只改这一处，客户 / 线索 / 商机 / 合同 / 成交 / 工单 / 跟进 等 8+ 列表页同时生效。
 * 背景必须显式设置（不能依赖继承），否则 Chromium 在 border-collapse:separate
 * + position:sticky 滚动时会丢失 thead 背景 → 下方行内容「穿模」。 */
.data-table { width:100%; min-width:560px; border-collapse:separate; border-spacing:0; background:#fff; border-radius:10px; border:1px solid var(--line); }
.data-table th, .data-table td { text-align:left; padding:11px 14px; font-size:13px; border-bottom:1px solid var(--line); }
.data-table th { background:#f7f9fc; color:#556; font-weight:600; white-space:nowrap; }
.data-table td { color:#333; }
.data-table tbody tr:hover td { background:#fafbfe; }
/* 紧凑行高（列表「⤢ 紧凑」开关，2026-09-12）：默认启用，降低行高、提升一屏可视行数 */
.data-table.dense th, .data-table.dense td { padding:9px 14px; }
/* 列表内开关激活态（紧凑等） */
.btn-ghost.on { background:var(--blue); color:#fff; border-color:var(--blue); }
/* 表头吸顶：top 跟随吸顶功能区高度（--hdr-off 由 JS measureStickyHeader 测量） */
.content .data-table thead th { position:sticky; top:var(--hdr-off,0px); z-index:6; background:#f7f9fc; box-shadow:0 1px 0 #dbe1ea; }
/* 列表表格容器：窄屏横向滚动，避免整页被宽表格撑破错位（桌面端不限制，保持表头吸顶相对 .content 生效）。
   注意：不可给 .data-table 本身加 overflow（见下方注释，会让 sticky 失效），横滚容器放在 #tbl 上且仅窄屏生效。 */
@media (max-width:640px){ #tbl { overflow-x:auto; -webkit-overflow-scrolling:touch; } }
/* 智能横滚（桌面端）：renderTable 渲染后由 JS fitTableScroll() 实测表格自然宽度，
   横向溢出或窄表内容超过视口时给 #tbl 加 .x-scroll 并填满视口高度；内容不足一屏的短表不加。
   注意：#tbl 一旦成为滚动容器，其内部 thead sticky 就会失效（原因同上方注释），
   故在该模式下同步关闭表头吸顶，避免出现「表头卡在半空」的半吊子状态。 */
.x-scroll { overflow:auto; -webkit-overflow-scrolling:touch;
  /* 容器定高：把容器底边压在视口内，使横向滚动条常驻可见，
     不必先把 .content 垂直滚到最底才看得到滑块（2026-09-08 客户列表反馈）。
     精确高度由 JS fitTableScroll() 动态写入；此处 70vh 仅为 JS 未执行时的兜底值。 */
  max-height:70vh; }
/* 横滚模式下 #tbl 自身成为滚动容器，thead 的 sticky 参照系由 .content 变为 #tbl，
   因此把 top 从 --hdr-off 改为 0（而不是关闭吸顶），表头相对容器顶部吸顶依然有效。 */
.content .x-scroll .data-table thead th { position:sticky; top:0; z-index:6; }
/* 横滚时：汇总栏 / 批量栏 / 分页栏横向固定（sticky left），不随表格内容左右跑 */
.x-scroll > .deal-sum-bar,
.x-scroll > .auth-sum-bar,
.x-scroll > .batch-bar,
.x-scroll > .page-foot { position:sticky; left:0; }
/* 分页栏纵向也钉在容器底部：翻页无需先垂直滚到底（2026-09-08）。
   sticky bottom 在滚到底时会自动回到文档流自然位置，故不会永久遮挡最后一行。 */
.x-scroll > .page-foot { bottom:0; z-index:7; box-shadow:0 -1px 0 var(--line); }
.x-scroll > .batch-bar,
.x-scroll > .page-foot { background:var(--bg,#f4f6fa); }
/* 超长编码类单元格（授权码等）：定宽 + 省略号，悬浮 title 看全文。
   用 inline-block 包裹而非给 td 加 max-width —— table-layout:auto 下 td 的 max-width 不可靠。 */
.code-ellipsis { display:inline-block; max-width:220px; vertical-align:bottom;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* 可点击复制单元格（授权码等）：hover 反馈提示可点 */
.data-table td.cell-copy { cursor:pointer; }
.data-table td.cell-copy:hover .code-ellipsis { color:var(--blue2); text-decoration:underline; }

/* ---------- 表尾金额列累计（通用 tfoot，renderTable 生成，2026-09-11） ---------- */
/* 与正文列同左对齐（合计落在对应列正下方），tabular-nums 保证数字位数对齐；
   吸底（2026-09-11 潘总反馈）：长表免滚底即见合计 —— 常规模式贴视口底（与表头吸顶对称），
   x-scroll 定高容器模式贴容器可视区底（横向滑块与合计同时常驻）；短表不浮起，跟在最后一行下 */
.data-table tfoot td { background:#f7f9fc; border-top:2px solid #dfe5ee; border-bottom:none; font-weight:600; color:#333; position:sticky; bottom:0; z-index:6; box-shadow:0 -2px 6px rgba(15,40,80,.07); }
.data-table tfoot td.tf-label { color:#66707f; font-weight:500; white-space:nowrap; }
.data-table tfoot td.tf-num { font-variant-numeric:tabular-nums; color:#0e3f8f; white-space:nowrap; }
/* x-scroll 定高容器：分页条 .page-foot 本就吸底常驻（bottom:0; z-index:7），
   tfoot 若同贴 bottom:0 会被其整个盖住（2026-09-12 复刻实测：两者 bottom 相同、pf 不透明），
   故 tfoot 让出分页条高度、吸在其正上方 —— --tf-b 由 fitTableScroll 实测 page-foot 高度写入 */
.content .x-scroll .data-table tfoot td { bottom: var(--tf-b, 0px); }

/* ---------- 从原 styles.css 迁移过来的共享组件 ---------- */
/* 工具栏 */
.toolbar { display:flex; gap:10px; margin-bottom:14px; align-items:center; flex-wrap:wrap; }
.search { height:36px; border:1px solid var(--line); border-radius:8px; padding:0 12px; width:240px; outline:none; font-size:14px; }
.search:focus { border-color:var(--blue2); }
.btn { height:36px; padding:0 16px; border-radius:8px; border:none; cursor:pointer; font-size:14px; }
.btn-primary { background:var(--blue); color:#fff; }
.btn-primary:hover { background:var(--blue2); }
.btn-ghost { background:#fff; border:1px solid var(--line); color:#555; }
.btn-sm { height:28px; padding:0 10px; font-size:12px; border-radius:6px; }
.btn-danger { background:#fff; border:1px solid #ffd0d0; color:#e53935; }
.btn-danger:hover { background:#ffeaea; }

/* 多选筛选弹层（线索状态多选等） */
.msf-wrap { position:relative; }
.msf-btn.on { border-color:var(--blue); color:var(--blue); }
.msf-pop { position:absolute; top:42px; left:0; z-index:200; min-width:168px; background:#fff; border:1px solid var(--line); border-radius:10px; box-shadow:0 8px 24px rgba(0,0,0,.12); padding:8px; }
.msf-item { display:flex; align-items:center; gap:8px; padding:6px 8px; font-size:13px; color:#445; cursor:pointer; border-radius:6px; }
.msf-item:hover { background:#f5f8ff; }
.msf-item input { width:15px; height:15px; accent-color:var(--blue); }
.msf-ft { display:flex; justify-content:flex-end; gap:8px; margin-top:6px; padding-top:6px; border-top:1px solid var(--line); }
.msf-ft .btn { height:30px; padding:0 12px; font-size:12px; }

/* 表格：
   1) overflow:hidden 会让 thead sticky 失效（table 成为滚动容器），故移除；
   2) border-collapse:collapse 与 position:sticky th 组合会导致滚动时表头背景不绘制、
      下方行内容「穿模」透出，故改用 border-collapse:separate + border-spacing:0。
   圆角由外层容器/阴影呈现 */
table { width:100%; border-collapse:separate; border-spacing:0; background:#fff; border-radius:10px; border:1px solid var(--line); }
th,td { text-align:left; padding:11px 14px; font-size:13px; border-bottom:1px solid var(--line); }
th { background:#f7f9fc; color:#556; font-weight:600; }
tr:hover td { background:#fafbfe; }
/* 吸顶规范：把标题/Tab/工具栏包进一个独立白底卡片并整体吸顶。
   之前用全局底色 #f4f6fa 做吸顶背景，用户反馈多个子 div 之间仍“透视”——
   因为标题、Tab、工具栏是独立 div，中间缝隙/子元素背景未完全闭合。
   改为实体白底卡片 + 边框阴影，从视觉上完全封闭为一个不透明块。

   闭合顶部缝隙：.content 默认有 padding-top:22px，会把 sticky 固定点下移 22px，
   导致卡片上方永远露出一段内容区背景。解决办法是：当 .content 第一个子元素为吸顶区时，
   由 JS 给 .content 加 .pt-0（去掉顶部 padding），吸顶卡片自身用 padding-top:22px
   保留“客户管理”标题等内容的视觉位置，同时 sticky 直接贴在 .content 最顶部，无缝隙。
   无吸顶功能区的页面（仪表盘、详情页等）保持 .content 的 padding-top:22px 不变。

   层叠上下文说明：.content 已设置 position:relative;z-index:1（见 base.css），
   因此本层 z-index 只在 .content 内部比较。设为 100 可确保压住后面表格的
   thead（z-index:6）以及 tbody 行，避免滚动时表格行穿透到吸顶卡片上方。 */
.page-sticky, .rep-sticky, .kb-sticky {
  position:sticky; top:0; z-index:100;
  background:#fff;
  border:1px solid var(--line);
  border-radius:10px;
  padding:22px 16px 10px;  /* 顶部 22px 替代 .content 的 padding-top，保持视觉间距 */
  margin-bottom:14px;
  box-shadow:0 2px 10px rgba(15,40,80,.05);
  width:100%;             /* 确保吸顶区横向铺满内容区 */
  box-sizing:border-box;  /* 配合 tokens.css 全局 border-box */
  /* 强制 GPU 合成层：防止某些浏览器把后续普通 div（如 KB 的 .kb-row）
     合成到吸顶卡片上方，导致“穿透”现象。 */
  transform:translateZ(0);
}
/* 吸顶区内部子元素继承白底，并收紧间距，避免卡片内部出现“镂空”感 */
.page-sticky .page-head, .rep-sticky .page-head, .kb-sticky .page-head { margin-bottom:12px; }
.page-sticky .page-tabs, .rep-sticky .page-tabs, .kb-sticky .page-tabs { margin-bottom:12px; }
.page-sticky .toolbar, .rep-sticky .toolbar, .kb-sticky .toolbar { margin-bottom:0; }
/* KB 概览卡片区 / Tab 区：它们也在 .page-sticky 内部，必须同样收紧底部间距，
   否则 margin-bottom 会超出 .page-sticky 的 padding-bottom，形成镂空 */
.page-sticky .kb-dash { margin-bottom:8px; }
.page-sticky .kb-tabs { margin-bottom:8px; }
/* 列表表头吸顶：top 跟随功能区高度（--hdr-off 由 JS 测量），避免与功能区重叠。
   P1-4：全局规则原先是 `.content table thead th`（命中全站所有 table），会把详情页关联表、
   报表页短表（.eff-tbl/.heat-tb）等「卡片内短表」也吸顶——这些短表在双层吸顶（.rep-sticky）
   上下文里 --hdr-off 可达 ~190px，远超表自身高度，表头被压到表格底部盖住末行（穿模）。
   改为只命中真正的列表大表 `.data-table` 与门户任务表 `.portal-task-table`，卡片内短表
   不再吸顶（与 reports.css:109 既有惯例一致，且一次性根治，无需逐表关）。 */
.content .data-table thead th, .content .portal-task-table thead th { position:sticky; top:var(--hdr-off,0px); z-index:6; background:#f7f9fc; box-shadow:0 1px 0 #dbe1ea; }
/* P2-4：关联表 / 商机子表 / 报表短表 统一复用 .data-table 单元格外观 token（padding 11px 14px、hover #fafbfe、表头底色 #f7f9fc），
   避免各写一套；这些卡片内短表本就不吸顶，故不继承 .data-table 的 sticky。eff-tbl 保留数字居中报表语义。 */
.tbl-scroll table th, .tbl-scroll table td,
.opp-sub th, .opp-sub td { text-align:left; padding:11px 14px; font-size:13px; border-bottom:1px solid var(--line); }
.eff-tbl th, .eff-tbl td { text-align:center; padding:11px 14px; font-size:13px; border-bottom:1px solid var(--line); }
.tbl-scroll table th, .opp-sub th, .eff-tbl th { background:#f7f9fc; color:#556; font-weight:600; white-space:nowrap; }
.tbl-scroll table tbody tr:hover td, .opp-sub tbody tr:hover td, .eff-tbl tbody tr:hover td { background:#fafbfe; }

/* 工单专属：4 统计卡 + 快捷筛选 + 视图切换（嵌在 page-sticky 内，不影响其他模块）
   作用：① 让上方所有元素在同一张卡片里，稳固 z-index 关系避免表头吸顶穿透
        ② 4 卡是统计速览，chip 是一键过滤，view 切换是视图模式 */
.tk-stats { display:grid; grid-template-columns:repeat(auto-fit, minmax(130px, 1fr)); gap:12px; margin-bottom:14px; }
.tk-stat { background:#fff; border:1px solid #e5e6eb; border-radius:8px; padding:14px 16px; }
.tk-stat .tk-lb { font-size:12px; color:#8f959e; margin-bottom:6px; }
.tk-stat .tk-vl { font-size:24px; font-weight:500; line-height:1.2; }
/* 4 卡背景统一为白底，仅用数字颜色区分语义（逾期=红、补录=橙），避免视觉割裂 */
.tk-stat.warn .tk-vl { color:#d97706; }
.tk-stat.danger .tk-vl { color:#c0392b; }
.tk-stat .tk-ex { font-size:11px; color:#8f959e; margin-top:3px; }
.tk-quick { display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-bottom:8px; padding:4px 0; }
.tk-quick-lbl { font-size:12px; color:#8f959e; }
.tk-chip { border:1px solid #e5e6eb; border-radius:14px; padding:4px 12px; font-size:12px; color:#646a73; background:#fff; cursor:pointer; font-family:inherit; transition:all .15s; }
.tk-chip:hover { border-color:#2b6cf6; color:#2b6cf6; }
.tk-chip.on { background:#2b6cf6; color:#fff; border-color:#2b6cf6; }
.tk-chip.danger { color:#c0392b; }
.tk-chip.warn { color:#a06400; }
.tk-chip.danger.on { background:#e34d4a; color:#fff; border-color:#e34d4a; }
.tk-chip.warn.on { background:#e8a317; color:#fff; border-color:#e8a317; }
.tk-chip .n { font-weight:500; margin-left:3px; }
.tk-tip { font-size:11px; color:#8f959e; margin-left:8px; }
.tk-views { display:flex; align-items:center; gap:10px; padding:4px 0 8px; }
.tk-cnt { font-size:12px; color:#8f959e; margin-left:6px; }

/* 工单：处理人泳道视图（按 owner_id 分组，未分配独立成组） */
.tk-lanes { display:grid; grid-template-columns:repeat(auto-fill,minmax(240px,1fr)); gap:12px; align-items:start; }
.tk-lane { background:#f5f6f8; border:1px solid #e5e6eb; border-radius:8px; padding:10px; }
.tk-lane.alert { border-color:#e34d4a; background:#fdeeee; }
.tk-lane-h { display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:10px; font-size:13px; }
.tk-lane-h span { font-size:11px; color:#8f959e; }
.tk-lane-cards { display:flex; flex-direction:column; gap:8px; }
.tk-card { background:#fff; border:1px solid #e5e6eb; border-radius:6px; padding:10px 12px; cursor:pointer; transition:border-color .15s; }
.tk-card:hover { border-color:#2b6cf6; }
.tk-card.od { border-color:#e34d4a; background:#fdeeee; }
.tk-card .r1 { display:flex; align-items:center; justify-content:space-between; margin-bottom:5px; font-size:11px; color:#8f959e; }
.tk-card .prio { font-weight:500; }
.tk-card .t { font-size:13px; font-weight:500; margin-bottom:4px; line-height:1.5; }
.tk-card .c { font-size:11px; color:#8f959e; margin-bottom:6px; }
.tk-card .r2 { display:flex; gap:4px; flex-wrap:wrap; margin-bottom:6px; }
.tk-card .stt { display:inline-block; padding:1px 7px; border-radius:4px; font-size:11px; background:#eaf1ff; color:#103a86; }
.tk-card .tag { display:inline-block; padding:1px 6px; border-radius:4px; font-size:11px; background:#fef4e6; color:#a06400; }
.tk-card .tag.gray { background:#f1f4f8; color:#8f959e; }
.tk-card .r3 { display:flex; align-items:center; justify-content:space-between; font-size:11px; color:#8f959e; padding-top:6px; border-top:1px solid #f0f1f3; }
.tk-card .r3 b { font-weight:500; }
/* 按处理人分派：人员卡片看板（替换原横向泳道） */
.tk-assign { display:grid; grid-template-columns:repeat(auto-fill,minmax(248px,1fr)); gap:14px; align-items:start; }
.tk-pcard { background:#fff; border:1px solid #e5e6eb; border-radius:10px; padding:14px; }
.tk-pcard.alert { border-color:#f3b4b1; box-shadow:0 0 0 1px #f3b4b1 inset; }
.tk-pcard-h { display:flex; align-items:center; gap:10px; margin-bottom:12px; }
.tk-av { width:36px; height:36px; border-radius:50%; flex:0 0 auto; display:inline-flex; align-items:center; justify-content:center; color:#fff; font-weight:700; background:linear-gradient(135deg,#8b5cf6,#6366f1); }
.tk-pcard.alert .tk-av { background:linear-gradient(135deg,#ef4444,#f97316); }
.tk-pcard-name { font-size:14px; font-weight:600; line-height:1.3; }
.tk-pcard-meta { display:block; font-size:12px; color:#8f959e; font-weight:400; }
.tk-pcard-kpis { display:flex; gap:8px; margin-bottom:12px; }
.tk-pcard-kpis .k { flex:1; background:#f7f8fa; border-radius:8px; padding:8px 4px; text-align:center; }
.tk-pcard-kpis .k b { display:block; font-size:18px; font-weight:700; line-height:1.2; }
.tk-pcard-kpis .k span { font-size:12px; color:#8f959e; }
.tk-pcard-list { display:flex; flex-direction:column; gap:6px; max-height:280px; overflow:auto; }
.tk-pitem { display:flex; align-items:center; gap:8px; padding:7px 9px; border-radius:6px; background:#f7f8fa; font-size:13px; cursor:pointer; }
.tk-pitem:hover { background:#eef0f3; }
.tk-pitem .id { font-weight:600; }
.tk-pitem .st { font-size:12px; }
.tk-pitem .st.st-wait { color:#e8a317; }
.tk-pitem .st.st-doing { color:#1d4ed8; }
.tk-pitem .st.st-done { color:#1f9254; }
.tk-pitem .st.st-closed { color:#8f959e; }
.tk-pitem .sla { font-size:12px; color:#8f959e; }
.tk-pitem .tag { display:inline-block; padding:1px 6px; border-radius:4px; font-size:11px; background:#fef4e6; color:#a06400; }
.tk-pitem .tag.gray { background:#f1f4f8; color:#8f959e; }
/* AI 评分：圆形徽章 + 悬停气泡评语 */
.ai-tip { position:relative; display:inline-flex; }
.ai-score { display:inline-flex; align-items:center; justify-content:center; width:26px; height:26px; border-radius:50%; font-size:12px; font-weight:700; color:#fff; background:linear-gradient(135deg,#8b5cf6,#6366f1); cursor:help; }
.ai-bubble { display:none; position:absolute; top:calc(100% + 8px); left:50%; transform:translateX(-50%); z-index:60; width:max-content; max-width:280px; padding:8px 10px; background:#1f2329; color:#fff; font-size:12px; line-height:1.55; border-radius:8px; box-shadow:0 6px 18px rgba(0,0,0,.22); white-space:normal; text-align:left; }
.ai-bubble::before { content:''; position:absolute; bottom:100%; left:50%; transform:translateX(-50%); border:6px solid transparent; border-bottom-color:#1f2329; }
.ai-tip:hover .ai-bubble { display:block; }

/* 知识库：左侧分类树吸顶（可独立滚动）。右侧工具栏已统一纳入 .page-sticky，
   不再单独吸顶，避免多个 sticky 元素叠加导致层级/穿透问题。 */
/* 注意：.kb-side 在文件下方还有一次定义，相关属性请在下方的统一规则里维护，避免覆盖 */
@media (max-width:900px){
  .page-sticky, .rep-sticky, .kb-sticky, .kb-side, .kb-main-area .toolbar { position:static; }
  .content table thead th, .content .portal-task-table thead th { position:static; }
}
.tag { display:inline-block; padding:2px 8px; border-radius:10px; font-size:12px; background:#eaf1ff; color:var(--blue); }

/* 模态 */
.modal { position:fixed; inset:0; background:rgba(0,0,0,.4); display:flex; align-items:center; justify-content:center; z-index:50; }
.modal-box { width:480px; max-width:92vw; max-height:86vh; overflow:hidden; display:flex; flex-direction:column; background:#fff; border-radius:12px; padding:22px 24px; }
.modal-title { font-size:17px; font-weight:700; color:var(--blue); margin-bottom:16px; }
.modal-body .fld { margin-bottom:14px; }
.modal-body label { display:block; font-size:13px; color:#556; margin-bottom:6px; }
.modal-body input, .modal-body select, .modal-body textarea { width:100%; border:1px solid var(--line); border-radius:8px; padding:9px 12px; font-size:14px; outline:none; font-family:inherit; }
.modal-body input:focus, .modal-body select:focus, .modal-body textarea:focus { border-color:var(--blue2); }
.modal-body textarea { min-height:80px; resize:vertical; }
.modal-foot { display:flex; justify-content:flex-end; gap:10px; margin-top:4px; }
/* toast */
.toast { position:fixed; top:20px; left:50%; transform:translateX(-50%); background:#333; color:#fff; padding:10px 20px; border-radius:8px; font-size:13px; z-index:99; box-shadow:0 4px 16px rgba(0,0,0,.18); animation:toastIn .18s ease; }
.toast.success { background:#1e8e3e; }
.toast.error { background:#d93025; }
.toast.warn { background:#e37400; }
@keyframes toastIn { from{ opacity:0; transform:translate(-50%,-8px);} to{ opacity:1; transform:translate(-50%,0);} }
.sub-h { font-size:13px; color:var(--muted); font-weight:600; margin:14px 0 8px; }
.todo-item { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:10px 0; border-bottom:1px dashed var(--line); font-size:13px; }
.todo-item:last-child { border-bottom:none; }
.todo-main { flex:1; color:#444; line-height:1.6; }
.todo-type { display:inline-block; background:#eaf1ff; color:var(--blue); font-size:12px; padding:1px 8px; border-radius:10px; margin-right:6px; }
.todo-date { color:var(--muted); font-size:12px; margin-left:6px; }
.todo-item.overdue .todo-date { color:#e53935; font-weight:700; }
.todo-item.overdue .todo-main { color:#c62828; }
.todo-item.warn .todo-type { background:#fff3e0; color:#ef6c00; }
.lnk { color:var(--blue); cursor:pointer; text-decoration:none; border-bottom:1px dashed var(--blue2); }
.lnk:hover { color:var(--blue2); }
.muted { color:var(--muted); font-size:13px; padding:8px 0; }
/* 详情页 */
.detail-bar { display:flex; gap:10px; margin-bottom:16px; flex-wrap:wrap; }
.detail-card { background:#fff; border:1px solid var(--line); border-radius:10px; padding:22px 24px; }
.detail-title { font-size:20px; font-weight:800; color:var(--blue); margin-bottom:16px; }
.kv-grid { display:grid; grid-template-columns:1fr 1fr; gap:10px 28px; margin-bottom:8px; }
.kv { display:flex; font-size:13px; border-bottom:1px solid #f0f2f6; padding-bottom:6px; }
.kv span { color:var(--muted); width:84px; flex:0 0 84px; }
.kv b { color:#333; font-weight:600; }
.rel-sec { margin-top:20px; }
.rel-sec h4 { font-size:14px; color:var(--blue); margin-bottom:10px; border-left:3px solid var(--blue2); padding-left:8px; }
/* 详情页关联区块（联系人/成交记录/商机/合同/工单/任务）表格：列多时不再挤压换行，底部出横向滑块（2026-09-11） */
.rel-sec .tbl-scroll { overflow-x:auto; -webkit-overflow-scrolling:touch; padding-bottom:4px; }
.rel-sec .tbl-scroll table { min-width:max-content; }

/* 时间线 */
.tl-item { display:flex; gap:12px; padding:8px 0; }
.tl-dot { flex:0 0 10px; width:10px; height:10px; border-radius:50%; background:var(--blue2); margin-top:5px; }
.tl-item.done .tl-dot { background:#bcbcbc; }
.tl-body { flex:1; font-size:13px; color:#444; line-height:1.6; }
.tl-item.done .tl-body { color:var(--muted); text-decoration:line-through; }
/* 页面标题区（参考截图：左侧大标题+副标题，右侧+按钮） */
.page-head { display:flex; align-items:center; justify-content:space-between; margin-bottom:18px; gap:16px; flex-wrap:wrap; }
.page-head-l { flex:1; min-width:0; }
.page-title { font-size:24px; font-weight:800; color:#1c2c4e; letter-spacing:.5px; }
.page-desc { font-size:13px; color:var(--muted); margin-top:6px; }

/* Tab 切换（全部/线索/商机/成交客户/流失客户） */
.page-tabs { display:flex; gap:6px; margin-bottom:16px; flex-wrap:wrap; }
.page-tab { padding:7px 16px; border-radius:999px; font-size:13px; color:#556; background:#fff; border:1px solid var(--line); cursor:pointer; transition:.18s; }
.page-tab:hover { color:var(--blue); border-color:var(--blue2); }
.page-tab.active { background:var(--blue); color:#fff; border-color:var(--blue); font-weight:600; }
/* 费用管理类别 tab：按类别着色（inline style 注入 --cat-color） */
.page-tab[style*="--cat-color"] { color:var(--cat-color); border-color:var(--cat-color); }
.page-tab[style*="--cat-color"]:hover { background:var(--cat-color); color:#fff; }
.page-tab[style*="--cat-color"].active { background:var(--cat-color); color:#fff; border-color:var(--cat-color); font-weight:600; }

/* 搜索框（带放大镜图标） */
.search-wrap { position:relative; flex:1; max-width:480px; }
.search-wrap .search-icon { position:absolute; left:12px; top:50%; transform:translateY(-50%); color:#9aa; font-size:13px; pointer-events:none; }
.toolbar .search { width:100%; padding-left:34px; }
.toolbar { margin-bottom:14px; }

/* 状态标签 */
.status-tag { display:inline-block; padding:3px 10px; border-radius:12px; font-size:12px; font-weight:600; }
.status-tag.status-1, .status-tag.status-2, .status-tag.status-3 { background:#eaf1ff; color:#1a5fd0; }
.status-tag.status-4 { background:#fff3e0; color:#ef6c00; }
.status-tag.status-5 { background:#e6f7ec; color:#1a9e57; }
.status-tag.status-6 { background:#fdecec; color:#e53935; }
.status-tag.status-0 { background:#f1f4f8; color:#9aa; }

/* 状态标签 · 选项级配色（同字段不同选项不同色；跨字段常见语义值统一色，避免撞色与同义不同色）
   由 app.js statusColorClass(module,field,value) 生成 s-<色名>，浅底深字保证可读性 */
.status-tag.s-blue    { background:#dbeafe; color:#1e40af; }
.status-tag.s-green   { background:#d1fae5; color:#065f46; }
.status-tag.s-orange  { background:#ffedd5; color:#c2410c; }
.status-tag.s-red     { background:#fee2e2; color:#b91c1c; }
.status-tag.s-purple  { background:#ede9fe; color:#5b21b6; }
.status-tag.s-teal    { background:#ccfbf1; color:#115e59; }
.status-tag.s-pink    { background:#fce7f3; color:#9d174d; }
.status-tag.s-cyan    { background:#cffafe; color:#155e75; }
.status-tag.s-amber   { background:#fef3c7; color:#92400e; }
.status-tag.s-indigo  { background:#e0e7ff; color:#3730a3; }
.status-tag.s-lime    { background:#ecfccb; color:#3f6212; }
.status-tag.s-sky     { background:#e0f2fe; color:#075985; }
.status-tag.s-rose    { background:#ffe4e6; color:#9f1239; }
.status-tag.s-slate   { background:#e2e8f0; color:#334155; }
.status-tag.s-gray    { background:#f1f4f8; color:#64748b; }
.status-tag.s-emerald { background:#d7f0e2; color:#0a7a4f; }

/* 未跟进天数徽标（线索停滞提醒） */
.stale-badge { display:inline-block; padding:3px 10px; border-radius:12px; font-size:12px; font-weight:600; }
.stale-normal { background:#eef6ee; color:#3a7d44; }
.stale-warn { background:#fff3e0; color:#ef6c00; }
.stale-critical { background:#fdecec; color:#e53935; }
.stale-muted { color:#9aa; font-size:12px; }

/* 图标化操作按钮 */
.icon-btn { width:30px; height:30px; border:none; background:transparent; cursor:pointer; border-radius:6px; font-size:15px; line-height:1; }
.icon-btn:hover { background:#f0f4fa; }
.icon-btn.del:hover { background:#fde8e8; }

/* 表格底部 */
.page-foot { padding:10px 14px; color:var(--muted); font-size:13px; text-align:right; }
/* 合同附件列按钮 */
.attach-btn { display:inline-flex; align-items:center; gap:6px; padding:5px 10px; border-radius:6px; cursor:pointer; border:1px solid transparent; font-size:13px; font-weight:600; white-space:nowrap; }
.attach-btn .att-ico { font-size:14px; }
.attach-btn.preview { background:#ecf5fe; color:#0e3f8f; border-color:#d4e3fb; }
.attach-btn.preview:hover { background:#dde9fb; }
.attach-btn.upload  { background:#fff7e6; color:#b25400; border-color:#fde2b6; }
.attach-btn.upload:hover  { background:#fdebcd; }

/* 消息中心铃铛 */
.msg-bell { position:relative; cursor:pointer; padding:6px 10px; border-radius:8px; transition:background .15s; }
.msg-bell:hover { background:rgba(255,255,255,.1); }
.bell-icon { font-size:18px; }
.msg-badge { position:absolute; top:0; right:2px; background:#e74c3c; color:#fff; font-size:11px; font-weight:700; border-radius:10px; min-width:18px; height:18px; line-height:18px; text-align:center; padding:0 4px; }
.msg-panel { position:absolute; top:52px; right:16px; width:360px; max-height:480px; background:#fff; border:1px solid var(--line); border-radius:12px; box-shadow:0 8px 32px rgba(0,0,0,.14); z-index:200; overflow:hidden; }
.msg-head { display:flex; justify-content:space-between; align-items:center; padding:14px 16px; border-bottom:1px solid var(--line); font-weight:700; color:#333; }
.msg-read-all { border:none; background:none; color:var(--blue); font-size:13px; cursor:pointer; }
.msg-read-all:hover { text-decoration:underline; }
.msg-close { border:none; background:transparent; color:#99a; font-size:20px; line-height:1; cursor:pointer; padding:0 2px; border-radius:4px; transition:all .15s; }
.msg-close:hover { color:#333; background:#f0f2f5; }
.msg-list { max-height:380px; overflow:auto; }
.msg-item { padding:12px 16px; border-bottom:1px solid #f0f2f5; cursor:pointer; transition:background .1s; }
.msg-item:hover { background:#f7f9fc; }
.msg-item.unread { background:#eef5ff; }
.msg-item.unread::before { content:''; display:inline-block; width:8px; height:8px; background:#e74c3c; border-radius:50%; margin-right:8px; }
.msg-type { font-size:13px; color:#333; line-height:1.5; }
.msg-time { font-size:12px; color:var(--muted); margin-top:4px; }
.msg-loading, .msg-empty { padding:30px; text-align:center; color:var(--muted); font-size:14px; }
/* 消息中心「我的 / 全部」切换（2026-09-10：铃铛只统计给我的未读，管理员可切全部只读查看） */
.msg-tabs { display:flex; gap:2px; margin-left:10px; background:#f1f3f7; border-radius:6px; padding:2px; }
.msg-tab { border:none; background:transparent; color:var(--muted); font-size:12px; padding:3px 10px; border-radius:4px; cursor:pointer; line-height:1.6; }
.msg-tab:hover { color:#333; }
.msg-tab.on { background:#fff; color:var(--blue); font-weight:600; box-shadow:0 1px 2px rgba(0,0,0,.06); }
.msg-to { display:inline-block; margin-right:8px; padding:0 6px; background:#f1f5f9; color:#64748b; border-radius:4px; font-size:11px; }
.msg-foot { padding:8px 16px; border-top:1px solid var(--line); background:#fafbfc; color:var(--muted); font-size:11px; line-height:1.5; }

/* 任务优先级标签 */
.status-tag.status-2 { background:#fef3c7; color:#92400e; } /* 待处理 - 黄 */
.status-tag.status-3 { background:#dbeafe; color:#1e40af; } /* 进行中 - 蓝 */
.status-tag.status-4 { background:#d1fae5; color:#065f46; } /* 已完成 - 绿 */

/* 时间段筛选 */
.period-tabs { display:flex; gap:6px; flex-shrink:0; align-items:center; }
.period-tab { padding:6px 12px; font-size:13px; color:#666; cursor:pointer; border-radius:6px; user-select:none; transition:all .15s; }
.period-tab:hover { background:#f0f4fa; color:#0e3f8f; }
.period-tab.active { background:#0e3f8f; color:#fff; font-weight:600; }
.period-tab-sep { width:1px; height:18px; background:var(--line); margin:0 4px; }
.period-date { height:32px; border:1px solid var(--line); border-radius:6px; padding:0 8px; font-size:13px; color:#333; background:#fff; outline:none; font-family:inherit; }
.period-date:focus { border-color:#0e3f8f; box-shadow:0 0 0 2px rgba(14,63,143,.1); }
.period-date-to { font-size:13px; color:#999; padding:0 2px; }

.pill { display:inline-block; padding:1px 8px; border-radius:10px; font-size:11px; }
.pill.info { background:#e0f2fe; color:#0369a1; }
.pill.gray { background:#eef1f5; color:#6b7280; }
.pill.ok { background:#d1fae5; color:#065f46; }
.pill.warn { background:#fef3c7; color:#92400e; }
.pill.danger { background:#fee2e2; color:#b91c1c; }
.pill.low { background:#eef1f5; color:#6b7280; }
/* 导航序号 */
.side-nav a { display:flex; align-items:center; gap:8px; }
.side-nav a .nav-num { display:none; }
.side-nav.show-num a .nav-num { display:inline-block; min-width:18px; font-size:11px; color:#fff; background:#0e3f8f; text-align:center; padding:1px 4px; border-radius:4px; margin-right:2px; font-weight:600; letter-spacing:-0.5px; }
.side-nav a .nav-icon { font-size:15px; flex:0 0 18px; text-align:center; }
.side-nav a .nav-label { flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.side-nav a.active .nav-num { background:#1a5fd0; }
.side-nav .side-sep { height:1px; background:#d4dce8; margin:8px 14px; }
/* 2026-09-11 侧栏分组折叠（复用 kb-group 配色范式） */
.side-nav .nav-group{ margin:1px 0; }
/* 2026-09-11 一级分组标题样式优化：11.5→12.5px / 字重 500 / 提亮 #afc6ec / 字距 1→.3px / 左侧 3px 蓝色竖条锚点 */
.side-nav .nav-group-head{ display:flex; align-items:center; gap:7px; padding:11px 22px 7px; font-size:12.5px; font-weight:500; color:#afc6ec; cursor:pointer; user-select:none; letter-spacing:.3px; }
.side-nav .nav-group-head::before{ content:''; flex:0 0 3px; width:3px; height:12px; border-radius:2px; background:#5b9bff; opacity:.75; }
.side-nav .nav-group-head:hover{ color:#dbe6fa; }
.side-nav .nav-group.collapsed .nav-group-head::before{ background:#8fa6d4; }
.side-nav .navg-arrow{ font-size:10px; width:10px; display:inline-block; color:#8fa6d4; }
.side-nav .navg-name{ flex:1; }
.side-nav .nav-group-body{ }
.side-nav .nav-group-body a{ padding-left:34px; font-size:13.5px; }
.side-nav .nav-group.collapsed .nav-group-body{ display:none; }
/* 表格内截止日期颜色（红=超时/橙=今日/蓝=未来） */
.portal-task-table .pstatus + td { white-space:nowrap; }

/* 弹窗头部 + 关闭按钮（右上角 ×） */
.modal-head { display:flex; align-items:center; justify-content:space-between; gap:10px; padding:14px 18px; border-bottom:1px solid #f0f2f5; }
.modal-head .modal-title { flex:1 1 auto; font-size:16px; font-weight:600; color:#1c2c4e; margin:0; padding:0; border:0; background:transparent; text-align:left; }
.modal-close { background:transparent; border:none; font-size:22px; color:#99a; cursor:pointer; width:30px; height:30px; line-height:1; border-radius:6px; transition:all .15s; padding:0; flex:0 0 30px; }
.modal-close:hover { background:#f0f4fa; color:#e74c3c; }
.modal-box { padding:0 !important; }
.modal-box .modal-body { padding:18px; flex:1; min-height:0; overflow:auto; }
.modal-box .modal-foot { padding:8px 18px 18px 18px; border-top:1px solid #f0f2f5; margin-top:8px; }

/* 详情页字段跳转图标 */
.kv-link { display:inline-block; margin-left:6px; font-size:14px; text-decoration:none; opacity:.7; transition:opacity .15s; padding:0 3px; }
.kv-link:hover { opacity:1; transform:scale(1.15); }
/* 跟进记录标题行（与"+ 新建跟进"按钮同行） */
.rel-sec-head { display:flex; align-items:center; flex-wrap:wrap; gap:8px; margin-bottom:8px; }
.rel-sec-head h4 { margin:0; }
.rel-sec-head .btn { margin-left:0; }

/* 客户名称自动补全（开票系统式） */
.ac-wrap { position:relative; }
.ac-list { display:none; position:absolute; top:calc(100% + 4px); left:0; right:0; z-index:60;
  background:#fff; border:1px solid #e3e8f0; border-radius:10px; box-shadow:0 10px 30px rgba(15,40,80,.14);
  max-height:240px; overflow:auto; padding:4px; }
.ac-item { padding:9px 12px; border-radius:8px; cursor:pointer; transition:background .12s; }
.ac-item:hover, .ac-item.ac-active { background:#f0f5fd; }
.ac-name { font-size:14px; color:#1c2c4e; display:flex; align-items:center; gap:8px; }
.ac-badge { font-size:11px; color:#0e3f8f; background:#eef2fb; padding:1px 6px; border-radius:4px; }
.ac-sub { font-size:12px; color:#9aa7b8; margin-top:3px; }
.ac-empty { padding:14px; text-align:center; color:#9aa7b8; font-size:13px; }

/* 线索转客户按钮 */
.btn-success { background:#22c55e; color:#fff; border:none; border-radius:8px; padding:9px 16px; font-size:14px; font-weight:600; cursor:pointer; transition:opacity .15s; }
.btn-success:hover { opacity:.9; }
.converted-tag { display:inline-block; padding:2px 10px; border-radius:10px; font-size:11px; background:#d1fae5; color:#065f46; }

/* ===== 抽屉式宽表单（deals 成交记录 新增/编辑） ===== */
.modal.drawer { align-items:stretch; justify-content:flex-end; }
.modal.drawer .modal-box { width:780px; max-width:94vw; height:100vh; max-height:100vh; border-radius:16px 0 0 16px; display:flex; flex-direction:column; animation:drawerIn .22s ease; }
@keyframes drawerIn { from{ transform:translateX(48px); opacity:.35; } to{ transform:translateX(0); opacity:1; } }
.modal.drawer .modal-box .modal-body { max-height:none; flex:1; overflow:auto; padding:22px 26px 26px; }
.modal.drawer .modal-box .modal-foot { padding:14px 26px 20px; }
.fld-grid { display:grid; grid-template-columns:1fr 1fr; gap:14px 22px; }
.fld-grid .fld { margin-bottom:0; }
.fld-grid .fld.full { grid-column:1 / -1; }
.fld-grid .fld textarea { min-height:80px; max-height:160px; }
/* 事由等多行说明：限高 160px，超出滚动；和基础 modal 一致，避免被弹窗整高 */
.fld-group { grid-column:1 / -1; font-size:13px; font-weight:700; color:var(--blue); margin:16px 0 2px; padding:9px 12px; background:#f2f6fc; border-radius:8px; border-left:3px solid var(--blue2); }
.fld-group:first-child { margin-top:0; }
/* ===== 费用弹窗 v3 视觉：顶部类别 tab + 加项/减项标签 + 底部金额横条 ===== */
.fld-grid .exp-tabs { grid-column:1 / -1; display:flex; gap:4px; flex-wrap:wrap; padding:8px 0 4px; border-bottom:1px solid var(--line); margin-bottom:6px; }
.fld-grid .exp-tab { padding:7px 14px; border:1px solid var(--line); border-bottom:none; background:#fff; color:var(--text2); border-radius:8px 8px 0 0; cursor:pointer; font-size:13px; transition:.15s; }
.fld-grid .exp-tab:hover { color:var(--blue2); }
.fld-grid .exp-tab.active { background:var(--blue); color:#fff; border-color:var(--blue); font-weight:600; }
.fld-grid .fld .am-badge { display:inline-block; font-size:10px; font-weight:400; padding:1px 6px; border-radius:10px; margin-left:6px; vertical-align:middle; }
.fld-grid .fld .am-badge.am-add { color:#1f9d55; background:#e7f6ee; border:1px solid #b9e6cb; }
.fld-grid .fld .am-badge.am-sub { color:#a45a18; background:#fdf2e3; border:1px solid #f3d6a8; }
.fld-grid .fld input.calc { background:var(--bg); color:var(--blue); font-weight:600; }
/* 金额横条：移出 fld-grid，作为 modal-body 内 block 节点紧贴 grid 下方，
   由 modal-foot 直接接手。取消 grid-column:1/-1，避免被栅格拉伸/撑高 */
#modal-body > .exp-amount-bar { display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:8px; margin:8px 0 0; padding:12px 18px; border-radius:10px; background:linear-gradient(90deg,#0e3f8f,#1a5fd0); color:#fff; }
#modal-body > .exp-amount-bar.manual { background:linear-gradient(90deg,#5b6470,#7a869a); }
#modal-body > .exp-amount-bar .exp-amount-calc { font-size:12.5px; opacity:.92; line-height:1.6; max-width:62%; }
#modal-body > .exp-amount-bar .exp-amount-val { font-size:26px; font-weight:700; letter-spacing:.5px; }
#modal-body > .exp-amount-bar .exp-amount-val small { font-size:14px; font-weight:400; opacity:.85; margin-right:3px; }
/* 兼容：极少数老路径仍可能在 fld-grid 内，放一份 fallback，颜色一致 */
.fld-grid > .exp-amount-bar { display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:8px; margin:8px 0 0; padding:12px 18px; border-radius:10px; color:#fff; background:linear-gradient(90deg,#0e3f8f,#1a5fd0); }
.fld-grid > .exp-amount-bar.manual { background:linear-gradient(90deg,#5b6470,#7a869a); }
.fld-grid > .exp-amount-bar .exp-amount-calc { font-size:12.5px; opacity:.92; line-height:1.6; max-width:62%; }
.fld-grid > .exp-amount-bar .exp-amount-val { font-size:26px; font-weight:700; letter-spacing:.5px; }
.fld-grid > .exp-amount-bar .exp-amount-val small { font-size:14px; font-weight:400; opacity:.85; margin-right:3px; }
/* ===== 富文本编辑器（工单解决方案） ===== */
.rte-wrap { border:1px solid var(--line); border-radius:10px; background:#fff; overflow:hidden; }
.rte-toolbar { display:flex; align-items:center; gap:4px; padding:6px 8px; background:#f7f9fc; border-bottom:1px solid var(--line); flex-wrap:wrap; }
.rte-toolbar button { width:30px; height:28px; border:1px solid #d9e0ea; border-radius:6px; background:#fff; color:#445; font-size:13px; font-weight:600; cursor:pointer; transition:all .15s; }
.rte-toolbar button:hover { border-color:var(--blue2); color:var(--blue2); background:#f0f5fd; }
.rte-hint { margin-left:auto; font-size:12px; color:var(--muted); }
.rte-editor { min-height:120px; max-height:320px; overflow:auto; padding:10px 12px; line-height:1.7; outline:none; }
.rte-editor:empty:before { content:'可输入文字、加粗、列表；截图/复制图片后 Ctrl+V 粘贴'; color:#aab4c2; }
.rte-editor p { margin:0 0 8px; }
.rte-editor ul, .rte-editor ol { margin:0 0 8px 18px; }
.rte-editor img { max-width:100%; border:1px solid var(--line); border-radius:6px; margin:4px 0; }
.rte-editor a { color:var(--blue2); text-decoration:underline; }
#modal-body .fld .rte-wrap textarea { display:none; }
.kv-rich { flex-direction:column; align-items:flex-start !important; }
.kv-rich .rte-view { width:100%; padding:10px 12px; background:#fbfbfb; border:1px solid var(--line); border-radius:8px; line-height:1.7; min-height:60px; }
.kv-rich .rte-view img { max-width:100%; border-radius:6px; }
.kv-rich .rte-view p { margin:0 0 6px; }
.kv-rich .rte-view ul, .kv-rich .rte-view ol { margin:0 0 6px 18px; }

/* ===== 导航序号拖拽排序 ===== */
.navcfg-row { transition: background .15s, border-color .15s; }
.navcfg-row[draggable="true"] { cursor: grab; }
.navcfg-row[draggable="true"]:active { cursor: grabbing; }
.navcfg-row.dragging { opacity:.4; background:#f7f9fc; }
.navcfg-row.drag-over { border-color:var(--blue2) !important; box-shadow:0 0 0 2px rgba(11,87,208,.12); background:#f0f5fd; }
.navcfg-handle { font-size:18px; color:#9aa; cursor:grab; padding:0 4px; user-select:none; }
.navcfg-handle:hover { color:var(--blue2); }
.navcfg-actions { display:inline-flex; gap:2px; margin-right:6px; }
.navcfg-move { width:24px; height:24px; border:1px solid #e3e8ef; border-radius:4px; background:#fff; color:#556; font-size:13px; cursor:pointer; transition:all .12s; }
.navcfg-move:hover { border-color:var(--blue2); color:var(--blue2); background:#f0f5fd; }

/* ===== 跟进延续链：回复上一条 ===== */
.tl-reply { margin-top:5px; font-size:12px; color:#0e3f8f; background:#f0f5fd; border:1px solid #dbe6f5; border-radius:5px; padding:4px 8px; cursor:pointer; display:inline-block; max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.tl-reply:hover { background:#e2edfa; border-color:#b5cdf0; }
/* ===== 详情页：大段文本字段（备注/需求描述/解决方案）专属展示区 ===== */
.detail-multi { margin-top:14px; background:#fafbfd; border:1px solid #eef1f6; border-radius:8px; padding:12px 16px; }
.detail-multi .dm-label { font-size:13px; color:#0e3f8f; font-weight:600; margin-bottom:6px; }
.detail-multi .dm-content { font-size:13px; color:#334; line-height:1.75; white-space:pre-wrap; word-break:break-word; max-height:340px; overflow:auto; }
/* 工单客户截图网格（公网表单提交，ticket_images，详情页只读展示） */
.tk-img-grid { display:flex; flex-wrap:wrap; gap:10px; margin-top:4px; }
.tk-img { display:block; width:120px; height:120px; border:1px solid #e5e8ef; border-radius:8px; overflow:hidden; background:#fff; transition:border-color .15s, box-shadow .15s; }
.tk-img img { width:100%; height:100%; object-fit:cover; cursor:zoom-in; display:block; }
.tk-img:hover { border-color:#2563eb; box-shadow:0 2px 8px rgba(37,99,235,.15); }

/* ===== 知识库 FAQ 卡片模式（胶囊/卡片式浏览） ===== */
.kb-card-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(280px, 1fr)); gap:14px; padding:4px 0; }
.kb-card { background:#fff; border:1px solid #e3e8ef; border-radius:12px; padding:14px 16px 10px; display:flex; flex-direction:column; gap:8px; transition:box-shadow .15s, border-color .15s, transform .12s; cursor:default; }
.kb-card:hover { border-color:#b5cdf0; box-shadow:0 4px 14px rgba(11,87,208,.08); transform:translateY(-1px); }
.kb-card-head { display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
.kb-card-cat { display:inline-block; font-size:11px; font-weight:600; padding:3px 10px; border-radius:11px; background:#eef2fb; color:#0e3f8f; line-height:1.4; }
.kb-card-cat[data-cat="售后技术类"], .kb-card-cat[data-cat="售后服务类"], .kb-card-cat[data-cat="售后"] { background:#fef3f2; color:#a32d2d; }
.kb-card-cat[data-cat="产品技术类"] { background:#f0fdf4; color:#166534; }
.kb-card-cat[data-cat="合同商务类"] { background:#fefce8; color:#854d0e; }
.kb-card-cat[data-cat="售前销售类"] { background:#ecfdf5; color:#065f46; }
.kb-card-cat[data-cat="案例沉淀类"] { background:#f5f3ff; color:#5b21b6; }
.kb-card-cat[data-cat="实施交付类"] { background:#f0f9ff; color:#075985; }
.kb-card-title { font-size:14px; font-weight:600; color:#1c2c4e; line-height:1.5; cursor:pointer; }
.kb-card-title:hover { color:var(--blue2); }
.kb-card-excerpt { font-size:12.5px; color:#667; line-height:1.6; max-height:54px; overflow:hidden; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; }
.kb-card-tags { display:flex; gap:5px; flex-wrap:wrap; }
.kb-pill { display:inline-block; font-size:11px; color:#556; background:#f3f5f9; padding:2px 8px; border-radius:10px; }
.kb-pill.warn { background:#fef3f2; color:#a32d2d; }
.kb-card-meta { display:flex; gap:14px; font-size:11.5px; color:#889; }
.kb-card-meta .warn { color:#a32d2d; }
.kb-card-source { font-size:11.5px; padding-top:6px; border-top:1px dashed #eef1f6; }
.kb-source-ticket { color:#0e3f8f; text-decoration:none; padding:2px 8px; background:#f0f5fd; border-radius:6px; display:inline-block; }
.kb-source-ticket:hover { background:#e2edfa; text-decoration:underline; }
.kb-card-ops { display:flex; justify-content:flex-end; gap:4px; margin-top:auto; padding-top:6px; }
.kb-card-ops .icon-btn { width:26px; height:26px; border:none; background:transparent; cursor:pointer; border-radius:6px; font-size:13px; }
.kb-card-ops .icon-btn:hover { background:#f3f5f9; }
.kb-card-ops .icon-btn.del:hover { background:#fef3f2; }
/* 移动端：单列 */
@media (max-width:640px) {
  .kb-card-grid { grid-template-columns:1fr; }
  /* 类别 Tab 过多时（如费用管理 9 类）横向滚动，不换行挤占纵向空间 */
  .page-tabs { flex-wrap:nowrap; overflow-x:auto; -webkit-overflow-scrolling:touch; padding-bottom:4px; }
  .page-tab { flex:0 0 auto; }
}
