/* 经营看板样式基座（K1-2）
   ─────────────────────────────────────────────────────────────
   1. 独立文件：不加载录入页的样式表（方案 C-3）。两套样式混用会互相污染 ——
      录入页那套的 body{overflow:hidden} 之外还有 .topbar/.progress 等同名灰块，看板会被带歪。
      色值在这里以 --kb-* 变量复制一份：观感统一，文件独立。
   2. 一屏装完：老板在会上不会往下翻页。body 锁死 100vh + overflow:hidden，
      主区高度用 calc(100vh − 顶栏 − 口径条 − 底栏 − 间距) 算；需要滚的只有卡片内部。
      禁止按 1080 逐块累加块高 —— 1920×1080 是屏幕分辨率，浏览器可视区只有约 960~980 的
      高度，累加必然溢出，F-001D 底部会被切掉（02 §1.1）。
   3. 速达风格：无圆角、无阴影、无渐变、宋体。
   ───────────────────────────────────────────────────────────── */

:root {
  /* 窗体 / 面板 / 线 */
  --kb-bg: #f0f0f0;
  --kb-panel: #ffffff;
  --kb-panel-alt: #fafafa;      /* "此块未启用"的灰一档底（F-006 门控态） */
  --kb-line: #c8c7c7;           /* 表格线、分隔线、进度条底 */
  --kb-frame: #8f8f8f;          /* 模块外框、抽屉左边框 */
  /* 文字 */
  --kb-text: #000000;
  --kb-muted: #666666;
  --kb-excluded: #999999;       /* 被剔除/排除的行说明 */
  /* 强调 */
  --kb-accent: #2f5c93;         /* 可点数字、主按钮、进度条填充 */
  --kb-accent-pale: #eaf2fb;    /* 表头、结论卡底 */
  /* 警示（未审核占比过高、门槛未达） */
  --kb-warn-fg: #8a4b00;
  --kb-warn-bg: #fff8e6;
  --kb-warn-bd: #d98b00;
  /* 错误（金额未识别） */
  --kb-bad-fg: #cc0000;
  --kb-bad-bg: #fdecec;
  /* 达标 */
  --kb-ok-fg: #008000;
  --kb-ok-bg: #f0f9f0;
  --kb-ok-bd: #b8ddb8;
  /* 未知桶（未填供应商） */
  --kb-unknown-bg: #f5f5f5;
  --kb-unknown-fg: #333333;
  --kb-unknown-bar: #a9a9a9;
  /* 其它 */
  --kb-mask: rgba(0, 0, 0, .18);
  --kb-scroll-thumb: #cdcdcd;
  --kb-scroll-thumb-bd: #a6a6a6;
}

/* 全站无圆角、无阴影、无渐变 —— 速达是 Windows 老程序，加了这些就不像了 */
* {
  box-sizing: border-box;
  border-radius: 0;
  box-shadow: none;
  background-image: none;
}

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;            /* A-01 的地基：整页不许出现纵向滚动条 */
}

body {
  font-family: "SimSun", "宋体", NSimSun, "Microsoft YaHei", sans-serif;
  font-size: 13px;
  color: var(--kb-text);
  background: var(--kb-bg);
}

/* 经典灰滚动条，跟录入页同一款（一格一格的），只出现在卡片内部 */
::-webkit-scrollbar { width: 13px; height: 13px; }
::-webkit-scrollbar-track { background: #f0f0f0; }
::-webkit-scrollbar-thumb { background: var(--kb-scroll-thumb); border: 1px solid var(--kb-scroll-thumb-bd); }
::-webkit-scrollbar-corner { background: #f0f0f0; }

/* ── 骨架容器 ─────────────────────────────────────────── */

/* 顶栏 / 抽屉头的按钮共用一副皮：白底灰边、无圆角，hover 淡蓝 */
.kb-topbar button,
.kb-drawer-top button {
  flex: none;
  font: inherit;
  white-space: nowrap;
  border: 1px solid var(--kb-line);
  background: var(--kb-panel);
  color: var(--kb-text);
  cursor: pointer;
}

.kb-topbar button:hover,
.kb-drawer-top button:hover {
  background: var(--kb-accent-pale);
  border-color: var(--kb-frame);
}

/* 刷新中/不可点：用 :disabled 属性表达，清单里没有"禁用态"类名 */
.kb-topbar button:disabled,
.kb-drawer-top button:disabled {
  opacity: .45;
  cursor: not-allowed;
}

.kb-app {
  display: flex;
  flex-direction: column;
  height: 100vh;
  overflow: hidden;
}

.kb-hide { display: none !important; }

/* ── 顶栏 44px（看板页自带；方案图里的"现有 topbar"在独立页面里不存在） ── */

.kb-topbar {
  flex: none;
  height: 44px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 10px;
  background: var(--kb-bg);
  border-bottom: 1px solid var(--kb-frame);
}

#kbTitle {
  margin: 0 auto 0 0;          /* 标题靠左，右侧按钮自动被推到最右 */
  font-size: 14.5px;
  font-weight: 700;
  letter-spacing: .5px;
  white-space: nowrap;
}

#kbAsOf {
  font-size: 11px;
  color: var(--kb-muted);
  white-space: nowrap;
}

#kbAsOf:empty { display: none; }  /* 顶栏不显示时间，留位（§3.1） */

/* 顶栏按钮比抽屉头大一号 */
.kb-topbar button { font-size: 13px; padding: 3px 12px; }

/* ── F-001 口径条 34px：单行、全宽、固定不滚 ───────────── */

.kb-seal {
  flex: none;
  height: 34px;                /* 警示态只换底色，不撑高，否则 1080 下把主区挤出去 */
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 10px;
  overflow: hidden;
  white-space: nowrap;
  background: var(--kb-panel);
  border-bottom: 1px solid var(--kb-line);
  position: relative;
  z-index: 30;                 /* 必须高于抽屉（A-15：抽屉开着时口径仍可读） */
  font-size: 12px;
}

.kb-seal-seg {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.kb-seal-sep {
  flex: none;
  width: 1px;
  height: 16px;
  background: var(--kb-line);
}

/* ── 主区：三列 ────────────────────────────────────────── */

.kb-main {
  height: calc(100vh - 44px - 34px - 22px - 16px);
  margin: 8px 0;
  display: flex;
  gap: 8px;
  min-height: 0;
}

.kb-col {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  min-height: 0;
}

/* 三列 620 / 656 / 628 ≈ 32.6% / 34.5% / 33.0%。
   用 flex 百分比 + gap：合计 100% 加 16px 间距要能被收缩掉，否则出横向滚动条。 */
.kb-col-l { flex: 0 1 32.6%; }
.kb-col-m { flex: 0 1 34.5%; }
.kb-col-r { flex: 0 1 33.0%; }

/* ── 模块块 ────────────────────────────────────────────── */

.kb-card {
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  background: var(--kb-panel);
  border: 1px solid var(--kb-line);
}

/* 块高按比例分，不写死 px：1920×1080 下正好落在 252/252/444 与 564/392，
   视口一矮就整体等比压缩，不会把最后一块顶出屏幕。
   252+252+444+16 = 564+392+8 = main 高度（1080 视口下约 964）。 */
#kbCard002   { flex: 252 1 0; }
#kbCard006   { flex: 252 1 0; }
#kbCard001D  { flex: 444 1 0; }
#kbCard004   { flex: 1 1 0; }     /* 中列唯一一块，吃满列高 */
#kbCard003   { flex: 564 1 0; }
#kbCard007   { flex: 392 1 0; }

/* 1366 降级：F-006 / F-007 折成 48px 单行条时给卡片加这个类。
   id 上的 flex 比例优先级高于单个类名，所以这两个 id 要单独列一条 ——
   否则类名加上了卡片也不动（实测过：只写 .kb-card.kb-condensed 时高仍是 169/264）。
   条里放什么由 K2-3 填，这里只管住几何。 */
.kb-card.kb-condensed,
#kbCard006.kb-condensed,
#kbCard007.kb-condensed {
  flex: 0 0 48px;
  min-height: 48px;
  max-height: 48px;
  overflow: hidden;
}

.kb-card-hd {
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 10px;
  background: var(--kb-accent-pale);
  border-bottom: 1px solid var(--kb-line);
}

.kb-card-title {
  margin: 0;
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
}

/* 标题行右侧的结论句/口径说明位 */
.kb-card-note {
  margin-left: auto;
  min-width: 0;
  font-size: 11px;
  color: var(--kb-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.kb-card-bd {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;              /* 全屏不滚，只有卡片内部滚 */
  padding: 8px 10px;
}

.kb-card-ft {
  flex: none;
  padding: 4px 10px;
  background: var(--kb-unknown-bg);
  border-top: 1px solid var(--kb-line);
  font-size: 10.5px;
  color: var(--kb-muted);
}

/* ── 底栏 22px ────────────────────────────────────────── */

.kb-footbar {
  flex: none;
  height: 22px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 10px;
  overflow: hidden;
  white-space: nowrap;
  background: var(--kb-bg);
  border-top: 1px solid var(--kb-line);
  font-size: 10.5px;
  color: var(--kb-muted);
}

.kb-footbar .kb-numtag { margin-left: auto; }

/* ── 数字与结论 ────────────────────────────────────────── */

/* 所有可点数字统一用它（02 §2 通用数字格式）：蓝字 + 1px 点线下边框，hover 变实线 */
.kb-numtag {
  color: var(--kb-accent);
  border-bottom: 1px dotted var(--kb-accent);
  cursor: pointer;
  text-decoration: none;
  font-variant-numeric: tabular-nums;
}

.kb-numtag:hover { border-bottom-style: solid; }

/* 结论主数字：老板隔着一张桌子要看得见，32px 粗体不商量 */
.kb-money-main {
  font-size: 32px;
  font-weight: 700;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
}

.kb-subline {
  margin-top: 4px;
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}

.kb-note { font-size: 10.5px; color: var(--kb-muted); }
.kb-muted { color: var(--kb-muted); }

/* 空缺统一 —，且要一眼看出是"没有"而不是"零" */
.kb-miss { color: var(--kb-excluded); }

/* ── 警示条 / 徽标 ────────────────────────────────────── */

.kb-alert {
  display: block;
  margin-top: 4px;
  padding: 2px 8px;
  font-size: 12px;
  border-left: 3px solid transparent;
}

/* R5 是"提醒"不是"报错"：橙色、不弹窗、不遮挡 */
.kb-alert-warn {
  color: var(--kb-warn-fg);
  background: var(--kb-warn-bg);
  border-left-color: var(--kb-warn-bd);
}

.kb-alert-info {
  color: var(--kb-muted);
  background: transparent;
  border-left-color: var(--kb-line);
}

/* R5 口径条警示态：整条换底色 + 左橙边，高度仍锁 34px（撑高就把主区挤出去了）。
   JS 只需给 #kbSeal 加 kb-alert-warn，不要再加 kb-alert（那是块级警示条，会改内边距）。 */
.kb-seal.kb-alert-warn {
  padding-left: 7px;
  border-left: 3px solid var(--kb-warn-bd);
}

/* 徽标 / 状态：同一副方块，只换前景底色（已审核绿、待审核橙、附注灰） */
.kb-badge,
.kb-status-done,
.kb-status-recog {
  display: inline-block;
  flex: none;
  padding: 0 5px;
  font-size: 10.5px;
  line-height: 16px;
  border: 1px solid var(--kb-line);
  white-space: nowrap;
}

.kb-badge-pass,
.kb-status-done { color: var(--kb-ok-fg); background: var(--kb-ok-bg); border-color: var(--kb-ok-bd); }
.kb-badge-fail,
.kb-status-recog { color: var(--kb-warn-fg); background: var(--kb-warn-bg); border-color: var(--kb-warn-bd); }
.kb-badge-note { color: var(--kb-muted); background: var(--kb-unknown-bg); border-color: var(--kb-line); }

/* ── 排行表 / 占比条 ──────────────────────────────────── */

.kb-ranktable {
  width: 100%;
  border-collapse: collapse;
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}

.kb-rank-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 26px;
  border-bottom: 1px solid var(--kb-line);
}

.kb-rank-row:last-child { border-bottom: none; }

.kb-rank-no {
  flex: none;
  width: 28px;
  text-align: center;
  color: var(--kb-muted);
}

.kb-rank-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 条形：kb-bar 是轨道、kb-bar-fill 是填充，kb-rank-bar 是排行行里给条留的位置。
   两个都按轨道写 —— JS 少套一层（fill 直接放 rank-bar 里）或多套一层，条都不会被压成 0 高。 */
.kb-rank-bar,
.kb-bar {
  flex: 1 1 auto;
  min-width: 0;
  display: block;
  height: 10px;
  background: var(--kb-line);
  overflow: hidden;
}

/* 覆盖度进度条填充的三态（清单里没有对应类名，用 data-state 属性表达）：
   ok  = 达标         → 蓝（02 的默认填充色）
   warn= 未达门槛     → 橙（02 明文"不达标用橙不用红"，说的是这种）
   fail= 数据对不上/读不出来 → 红（比"不达标"更重，只给口径自校验失败用） */
.kb-cov-fill[data-state="ok"] { background: var(--kb-accent); }
.kb-cov-fill[data-state="warn"] { background: var(--kb-warn-bd); }
.kb-cov-fill[data-state="fail"] { background: var(--kb-bad-fg); }

.kb-bar-fill {
  display: block;
  height: 100%;
  width: 0;
  background: var(--kb-accent);
}

/* 金额 / 占比 / 张数三列：定宽右对齐，数字才不会跟着品名长短抖动 */
.kb-rank-amt,
.kb-rank-pct,
.kb-rank-docs {
  flex: none;
  text-align: right;
}

.kb-rank-amt { width: 96px; }
.kb-rank-pct { width: 56px; }
.kb-rank-docs { width: 44px; }

/* 未知桶（未填供应商）：虚线灰底 + 灰条，与实体供应商一眼区分开（A-05 的唯一识别特征） */
.kb-unknown-bucket {
  background: var(--kb-unknown-bg);
  border: 1px dashed var(--kb-line);
  color: var(--kb-unknown-fg);
}

.kb-unknown-bucket .kb-bar-fill { background: var(--kb-unknown-bar); }

.kb-unknown-hint {
  margin-left: 4px;
  font-size: 10.5px;
  color: var(--kb-muted);
}

/* ── 门控块（F-006 默认态：整块是说明，不画图） ────────── */

.kb-gate {
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: 12px 14px;
  background: var(--kb-panel-alt);
  border: 1px solid var(--kb-line);
}

.kb-gate-headline {
  font-size: 16px;
  font-weight: 700;
  color: var(--kb-muted);
}

.kb-gate-reason {
  margin-top: 8px;
  font-size: 12.5px;
  line-height: 1.7;
  color: var(--kb-text);
}

.kb-gate-progress {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
}

.kb-gate-track {
  flex: 1 1 auto;
  height: 4px;
  background: var(--kb-line);
  overflow: hidden;
}

.kb-gate-fill {
  display: block;
  height: 100%;
  width: 0;
  background: var(--kb-accent);
}

.kb-gate-preview {
  margin-top: 8px;
  font-size: 10.5px;
  line-height: 1.6;
  color: var(--kb-muted);
}

/* 门控/空态的按钮同尺寸：26px 高、无圆角，主色实心 vs 描边两种皮 */
.kb-gate-btn,
.kb-empty-action {
  display: inline-block;
  flex: none;
  padding: 0 12px;
  height: 26px;
  line-height: 24px;
  font-size: 12.5px;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}

.kb-gate-btn {
  align-self: flex-start;
  margin-top: auto;
  color: #ffffff;
  background: var(--kb-accent);
  border: 1px solid var(--kb-accent);
}

/* ── 空态块（R6：现象 / 原因 / 动作，三行结构） ────────── */

.kb-empty {
  height: 100%;
  min-height: 60px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px;
  text-align: center;
}

.kb-empty-headline { font-size: 13px; font-weight: 700; }
.kb-empty-reason { font-size: 12.5px; line-height: 1.6; }

.kb-empty-action {
  margin-top: 4px;
  color: var(--kb-accent);
  background: var(--kb-panel);
  border: 1px solid var(--kb-frame);
}

/* ── 覆盖度面板（F-001D：指标名 / 分数 / 条 / 门槛 / 徽标） ── */

.kb-cov-panel {
  width: 100%;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.kb-cov-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 42px;
  border-bottom: 1px solid var(--kb-line);
  cursor: pointer;
}

.kb-cov-row:last-child { border-bottom: none; }

.kb-cov-label {
  flex: none;
  width: 96px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.kb-cov-score {
  flex: 0 1 148px;             /* 金额型那行就地量出来要 147px，给 148 才不折两行 */
  min-width: 0;                /* 空间不够时先缩它自己 —— 一屏装完优先于不折行 */
  text-align: right;
}

.kb-cov-track {
  flex: 1 1 60px;
  min-width: 60px;             /* 条再窄就没法看了，宁可让分数列折行 */
  height: 6px;
  background: var(--kb-line);
  position: relative;          /* 门槛刻度线以它为定位基准 */
}

.kb-cov-fill {
  display: block;
  height: 100%;
  width: 0;
  background: var(--kb-accent);
}

/* 门槛位置的 1px 竖线刻度，left 由 JS 按门槛值给 */
.kb-cov-thline {
  position: absolute;
  top: 0;
  width: 1px;
  height: 100%;
  background: var(--kb-frame);
}

.kb-cov-th {
  flex: none;
  width: 64px;
  text-align: right;
  font-size: 10.5px;
  color: var(--kb-muted);
}

/* 徽标列：56px 是按"达标/不可用"两个字的宽度定的，但"54 行角分差异"要 81px，
   放 56px 里会被卡片右边框裁掉。定宽 84px 让 9 行仍对齐，内容也不再被切。

   KB-15 之后「金额自洽」那行要说「57 行不自洽（其中 54 行角分差异）」，实测 185px：
   84px 会横向溢出 101px 直接被卡边裁掉（屏上只剩半句）。所以放宽到 196px，
   但**可收缩 + 省略号**：1920（设计目标档）实测 196px 全句可见、行不溢出、面板 0 滚；
   1600/1536/1440 这种窄档自动缩到 138/126/108px 打省略号 —— 卡内竖直滚动保持原来的 0/10px，
   不会因为这一列变高。定宽不收的话窄档行高会涨（1536 卡内滚 10 → 42px）。 */
.kb-cov-badge {
  flex: 0 1 196px;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: right;
}

.kb-cov-foot {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid var(--kb-line);
  font-size: 10.5px;
  color: var(--kb-muted);
}

/* 可点锚点统一手型（KB-07）：64 个可点位置里 39 个原来没有 cursor:pointer ——
   38 个 .kb-rank-row（整行可点）和 1 个未填供应商桶。逐个类去补必然漏，
   直接在属性钩子上给：凡是带 data-src / data-more 的就是"能点进去"，
   手型跟着属性走，以后新增锚点不用记得加。 */
[data-src],
[data-more] {
  cursor: pointer;
}

.kb-cov-pill {
  display: inline-block;
  margin: 0 6px 0 0;
  padding: 2px 8px;
  font-size: 10.5px;
  background: var(--kb-panel);
  border: 1px solid var(--kb-line);
  cursor: pointer;
  white-space: nowrap;
}

/* ── F-005 追溯抽屉 ──────────────────────────────────── */

.kb-drawer {
  position: fixed;
  top: 78px;                   /* 顶栏 44 + 口径条 34：抽屉从口径条下沿开始 */
  right: 0;
  bottom: 22px;                /* 不盖底栏：数据截至时间要常驻可读 */
  /* 12 列装不下 720（实测自然宽 1421 / 可用 719，硬压只能把品名压到 42px）。
     860 是让 12 列都能读的最小值。**这是 02 §F-005 定宽的变更，已上报待追认**；
     若退回 720，表会横滚、品名只剩 42px（不建议）。 */
  width: min(860px, 86vw);
  z-index: 20;                 /* 必须低于 #kbSeal 的 30 */
  display: flex;
  flex-direction: column;
  background: var(--kb-panel);
  border-left: 1px solid var(--kb-frame);
  /* 开合：关闭态在屏外 + 不可聚焦（body overflow:hidden 兜住，不出横向滚动条）。
     打开 = JS 给 #kbDrawer 加 kb-open，transform 回来这 160ms 由 transition 负责。
     visibility 用 0s 延迟切换，让关闭动画先跑完再失焦，不然抽屉会"啪"地消失。 */
  transform: translateX(100%);
  visibility: hidden;
  transition: transform 160ms linear, visibility 0s linear 160ms;
}

#kbDrawer.kb-open {
  transform: translateX(0);
  visibility: visible;
  transition: transform 160ms linear;
}

.kb-drawer-mask {
  position: fixed;
  top: 78px;
  right: 0;
  bottom: 22px;
  left: 0;
  z-index: 10;
  background: var(--kb-mask);
}

.kb-drawer-top {
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 6px 10px;
  background: var(--kb-accent-pale);
  border-bottom: 1px solid var(--kb-line);
}

/* 面包屑挤占剩余宽度，放不下就省略，不许把按钮顶出去 */
.kb-crumb {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 4px;
  overflow: hidden;
  white-space: nowrap;
  font-size: 12px;
}

.kb-crumb-seg { color: var(--kb-accent); cursor: pointer; }
.kb-crumb-seg:last-child { color: var(--kb-text); cursor: default; }

/* 合计/命中行独占第二行（order 提到按钮之后） */
.kb-drawer-sum {
  flex: 1 1 100%;
  order: 9;
  min-width: 0;
  font-size: 10.5px;
  color: var(--kb-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 抽屉头按钮比顶栏小一号（720px 里要塞面包屑 + 三个按钮） */
.kb-drawer-top button { font-size: 12.5px; padding: 2px 10px; }

.kb-drawer-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
}

.kb-drawer-foot {
  flex: none;
  padding: 4px 10px;
  background: var(--kb-unknown-bg);
  border-top: 1px solid var(--kb-line);
  font-size: 10.5px;
  color: var(--kb-muted);
}

/* ── 表格（抽屉清单用） ──────────────────────────────── */

.kb-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  /* 自动列宽会让最长的品名(496)和供应商(301)把其余 10 列挤到 38~68px，
     于是日期折两行、标记和操作被推出抽屉外。定宽 + 品名吃剩余才稳。 */
  table-layout: fixed;
}

/* 12 列定宽（按实测的"不折行需要宽度"，仅品名/供应商用省略号收）
   品名不写宽度 —— 定宽表里没写宽度的列吃掉剩余空间 */
.kb-table th:nth-child(1),  .kb-table td:nth-child(1)  { width: 52px; }   /* 单据ID */
.kb-table th:nth-child(2),  .kb-table td:nth-child(2)  { width: 108px; }  /* 单据日期（'26年10月31日' 要 107） */
.kb-table th:nth-child(3),  .kb-table td:nth-child(3)  { width: 90px; }   /* 供应商（长名字省略号收） */
.kb-table th:nth-child(4),  .kb-table td:nth-child(4)  { width: 38px; }   /* 行号 */
.kb-table th:nth-child(6),  .kb-table td:nth-child(6)  { width: 47px; }   /* 数量 */
.kb-table th:nth-child(7),  .kb-table td:nth-child(7)  { width: 48px; }   /* 单位（含 '12-16#' 这类脏值） */
.kb-table th:nth-child(8),  .kb-table td:nth-child(8)  { width: 74px; }   /* 单价 */
.kb-table th:nth-child(9),  .kb-table td:nth-child(9)  { width: 88px; }   /* 金额 */
.kb-table th:nth-child(10), .kb-table td:nth-child(10) { width: 60px; }   /* 状态（'待审核' 徽标含内边距） */
.kb-table th:nth-child(11), .kb-table td:nth-child(11) { width: 66px; }   /* 标记（'金额未识别' 要 65） */
.kb-table th:nth-child(12), .kb-table td:nth-child(12) { width: 52px; }   /* 操作 */

.kb-th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 4px 6px;
  overflow: hidden;
  text-overflow: ellipsis;
  background: var(--kb-accent-pale);
  border-bottom: 1px solid var(--kb-frame);
  font-weight: 400;
  text-align: left;
  white-space: nowrap;
}

.kb-td {
  padding: 3px 6px;
  border-bottom: 1px solid var(--kb-line);
  vertical-align: top;
  /* 定宽表里必须 nowrap + 省略号，否则长品名会把行撑成两三行（行高 37px） */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── 标记 / 状态徽标 ─────────────────────────────────── */

/* 角分差异：橙不是红 —— 73 行最大差 0.9 元，是舍入不是 OCR 大错 */
.kb-mark-diff { color: var(--kb-warn-fg); font-size: 10.5px; }

/* 金额未识别：红。这是"缺失"，跟"算错"必须分开 */
.kb-mark-unrec { color: var(--kb-bad-fg); font-size: 10.5px; }

/* 无法判定：灰，不上警示色（可能是赠品/样品，业务上真实存在） */
.kb-mark-unknown { color: var(--kb-excluded); font-size: 10.5px; }

/* ── 三态：加载 / 出错 / 单块出错 ─────────────────────── */

.kb-loading {
  height: 100%;
  min-height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font-size: 12.5px;
  color: var(--kb-muted);
}

.kb-skeleton {
  display: inline-block;
  width: 48px;
  height: 10px;
  background: var(--kb-line);
}

.kb-error {
  display: block;
  margin-top: 4px;
  padding: 2px 8px;
  font-size: 12.5px;
  color: var(--kb-bad-fg);
  background: var(--kb-bad-bg);
  border-left: 3px solid var(--kb-bad-fg);
}

/* 单块失败只坏自己那一块，不许拖垮整屏（方案 §3.4） */
.kb-block-error {
  height: 100%;
  min-height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px;
  font-size: 12.5px;
  text-align: center;
  color: var(--kb-bad-fg);
  background: var(--kb-bad-bg);
  border: 1px solid var(--kb-line);
}

/* ══════════════════════════════════════════════════════════════════
   K2-3 模块层：品类结构 / 单品排行 / 折叠态 / 视口断点
   ──────────────────────────────────────────────────────────────────
   折叠态两个名字（04a 裁定）：kb-condensed = 48px 单行条（F-006/F-007，1366 宽）；
   kb-condensed-lg = 110px 胶囊条（F-001D，视口高 < 1000）。
   折叠条里必须"带数字"——收起 ≠ 删掉。数字都取自现成的 DOM：
   卡片标题行的 kb-card-note（结论句）+ 卡底栏 kb-card-ft（四段闭合行），CSS 编不出数字。
   ══════════════════════════════════════════════════════════════════ */

/* ── F-006 品类采购结构 ─────────────────────────────────────────── */

/* 降级态（默认）：这是"业务上还没做到"，不是"数据坏了" ——
   所以只靠 16px 粗体标题和具体数字把话说重，底色/边框一律保持中性灰，不进红橙。 */
#kbCard006 .kb-gate { padding: 10px 12px; }
#kbCard006 .kb-gate-reason { margin-top: 6px; }

/* 达标态：7 个品类的横向条形，复用 kb-ranktable + kb-bar（04a：不新增类名）。
   26px × 7 = 182，252px 卡的内容区 224px 装得下，不需要压缩行高。 */
#kbCard006 .kb-rank-row { min-height: 26px; }

/* ── F-004 单品采购排行 ─────────────────────────────────────────── */

/* 等宽数字：20 行扫下来数字不能跳。名次/金额/占比/张数四列点名写死，
   防止将来有人给某一列换了字体而丢掉 .kb-ranktable 上的 tabular-nums。 */
#kbCard004 .kb-rank-no,
#kbCard004 .kb-rank-amt,
#kbCard004 .kb-rank-pct,
#kbCard004 .kb-rank-docs { font-variant-numeric: tabular-nums; }

/* 条形留呼吸：fill 的 width:100% 是"轨道内容宽度"的 100%，
   轨道给 3px 右内边距，最长那根就自然离右侧金额列 3px，不会贴死。 */
.kb-rank-bar { padding-right: 3px; }

/* 两个汇总桶（品名未识别 / 非货名）在卡底栏：10.5px 灰字 + 与榜上 12.5px 正文拉开，
   视觉上是从属关系，不会让人当成第 21、22 项。 */
#kbCard004 .kb-card-ft .kb-note + .kb-note { margin-top: 2px; }

/* ── 折叠态：48px 单行条（kb-condensed）────────────────────────── */

/* 内容区收掉，只留标题行：标题 + kb-card-note（结论句，带数字）+ 「展开 ›」提示。
   提示用 ::after 生成 —— 冻结清单里没有"展开"类名，不许新造。 */
.kb-card.kb-condensed .kb-card-bd,
.kb-card.kb-condensed .kb-card-ft { display: none; }

/* 标题行吃满 48px 并垂直居中：不撑满的话 26px 的标题会挤在条的上半截 */
.kb-card.kb-condensed .kb-card-hd { flex: 1 1 auto; }

.kb-card.kb-condensed .kb-card-hd::after {
  content: "展开 ›";
  flex: none;
  margin-left: 8px;
  font-size: 11px;
  color: var(--kb-accent);
  cursor: pointer;
}

/* ── 折叠态：110px 胶囊条（kb-condensed-lg）────────────────────── */

/* 9 行面板收起，只留标题行 + 胶囊位 + 卡底栏的四段闭合行。
   胶囊（kb-cov-pill）由 JS 往内容区放；今天没有也不会占高度（内容区是空的）。 */
.kb-card.kb-condensed-lg .kb-cov-panel { display: none; }

/* 内容区不再吃 flex:1 —— 胶囊没渲染时它的高度必须是 0，
   否则 110px 里会凭空多出一块 60px 的空白。底栏用 margin-top:auto 贴条底。 */
.kb-card.kb-condensed-lg .kb-card-bd { flex: 0 0 auto; display: block; padding: 0 10px; overflow: hidden; }
.kb-card.kb-condensed-lg .kb-card-hd { flex: 1 1 auto; }   /* 吃掉中间空白，标题+结论句居中 */
.kb-card.kb-condensed-lg .kb-card-ft { margin-top: auto; }  /* 四段闭合行贴条底 */
.kb-card.kb-condensed-lg .kb-card-hd::after {
  content: "展开 ›";
  flex: none;
  margin-left: 8px;
  font-size: 11px;
  color: var(--kb-accent);
  cursor: pointer;
}

/* ── 三档视口断点（02 §1.1 / §1.3）────────────────────────────── */

/* 档 1：视口高 ≥ 1000 —— 三列全展开，F-001D 9 行完整面板。
   这一档显式把折叠"钉死"：万一 JS 上挂了折叠类、或从矮屏拉回来没摘类名，
   大屏也不会缩成条（档 2/3 的规则反过来会盖掉它，所以必须写在最前）。 */
@media (min-height: 1000px) {
  /* 每块要回到它自己的基准比例，不能都写 252 —— F-007 的基准是 392，
     写成 252 会把右列压扁（实测 007 从 392 掉到 296，右列比例全乱） */
  #kbCard006.kb-condensed {
    flex: 252 1 0;
    min-height: 0;
    max-height: none;
  }

  #kbCard007.kb-condensed {
    flex: 392 1 0;
    min-height: 0;
    max-height: none;
  }

  #kbCard006.kb-condensed .kb-card-bd,
  #kbCard007.kb-condensed .kb-card-bd,
  #kbCard001D.kb-condensed-lg .kb-card-bd { display: block; }

  #kbCard001D.kb-condensed-lg {
    flex: 444 1 0;
    min-height: 0;
    max-height: none;
  }

  #kbCard001D.kb-condensed-lg .kb-cov-panel { display: block; }
  #kbCard001D.kb-condensed-lg .kb-card-bd { flex: 1 1 auto; padding: 8px 10px; }
  #kbCard001D.kb-condensed-lg .kb-card-hd { flex: none; }
  #kbCard001D.kb-condensed-lg .kb-card-ft { margin-top: 0; }
}

/* 档 2：视口高 900~999 —— 主区压缩，F-001D 折成 110px 胶囊条（02 §1.3）。
   不挂类名也生效：矮屏是环境事实，不该等 JS 通知。 */
@media (max-height: 999px) {
  #kbCard001D {
    flex: 0 0 110px;
    min-height: 110px;
    max-height: 110px;
    overflow: hidden;
  }

  #kbCard001D .kb-cov-panel { display: none; }
  #kbCard001D .kb-card-bd { flex: 0 0 auto; display: block; padding: 0 10px; overflow: hidden; }
  #kbCard001D .kb-card-hd { flex: 1 1 auto; }
  #kbCard001D .kb-card-ft { margin-top: auto; }

  #kbCard001D .kb-card-hd::after {
    content: "展开 ›";
    flex: none;
    margin-left: 8px;
    font-size: 11px;
    color: var(--kb-accent);
    cursor: pointer;
  }
}

/* 档 3：视口高 < 900 或 宽度 ≤ 1400（老板的 1366×768 笔记本）——
   三列收两列（左 38% / 右 62%），F-006 / F-007 折成 48px 单行条。
   用 fr 而不是百分比：百分比 + gap 会溢出一行。 */
@media (max-height: 899px), (max-width: 1400px) {
  #kbMain {
    display: grid;
    grid-template-columns: 0.38fr 0.62fr;
    grid-template-rows: 1fr 1fr;
  }

  #kbColL { grid-column: 1; grid-row: 1 / 3; }
  #kbColM { grid-column: 2; grid-row: 1; }
  #kbColR { grid-column: 2; grid-row: 2; }

  #kbCard006,
  #kbCard007 {
    flex: 0 0 48px;
    min-height: 48px;
    max-height: 48px;
    overflow: hidden;
  }

  #kbCard006 .kb-card-bd,
  #kbCard007 .kb-card-bd,
  #kbCard006 .kb-card-ft,
  #kbCard007 .kb-card-ft { display: none; }

  /* 标题行吃满 48px 并垂直居中（和 .kb-card.kb-condensed 那条同一个理由） */
  #kbCard006 .kb-card-hd,
  #kbCard007 .kb-card-hd { flex: 1 1 auto; }

  #kbCard006 .kb-card-hd::after,
  #kbCard007 .kb-card-hd::after {
    content: "展开 ›";
    flex: none;
    margin-left: 8px;
    font-size: 11px;
    color: var(--kb-accent);
    cursor: pointer;
  }
}
