/* ============================================================================
 * components-v2.css —— 报价系统 UI v2 组件层（类名前缀统一 `zj2-`）
 *
 * 依赖：public/css/tokens.css（本文件**零裸色值**：所有颜色/尺寸都走 var(--…)）
 * 不接线：现有页面（public/index.html 只引 /css/style.css）一个字节没动，
 *         本文件此刻无人引用；第二期起由新骨架页按需引入。
 *
 * 命名约定：
 *   块       .zj2-card
 *   元素     .zj2-card__hd
 *   变体     .zj2-card--line / .zj2-btn--primary
 *   状态     .is-on / .is-here（布尔态一律 is-*，不写 .active —— 免得和 :active 混淆）
 *
 * 组件清单（与 docs/design/DESIGN-SYSTEM.md 的选用表一一对应）：
 *   1. 按钮 .zj2-btn               5. 卡片 .zj2-card            9. 空态/骨架/错误态
 *   2. 输入与选择 .zj2-field       6. KPI .zj2-kpi             10. 分页 .zj2-pager
 *   3. 标签 .zj2-chip              7. 分段 .zj2-seg            11. 面包屑 .zj2-crumbs
 *   4. 表格 .zj2-table             8. 抽屉 .zj2-panel           12. 提示条 .zj2-alert
 * ========================================================================== */

/* ─────────────────────────────────────────────────────────────────────────────
 * 0. 小工具（其余组件共用）
 * ────────────────────────────────────────────────────────────────────────── */
.zj2-num {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}
.zj2-r { text-align: right; }
.zj2-muted { color: var(--color-text-3); }
.zj2-sub { color: var(--color-text-2); }
.zj2-danger { color: var(--color-error); }
.zj2-nowrap { white-space: nowrap; }

/* 键位提示（键盘流页面用；文字用中文键名，不用 emoji 当图标） */
.zj2-kbd {
  display: inline-flex;
  align-items: center;
  height: 18px;
  padding: 0 var(--space-1);
  border: 1px solid var(--color-border);
  border-bottom-width: 2px;
  border-radius: var(--radius-1);
  background: var(--color-card);
  font-family: var(--font-num);
  font-size: var(--fs-12);
  color: var(--color-text-2);
  white-space: nowrap;
}

/* 工具条：表格/面板顶上的一条操作栏（左标题 + 右操作） */
.zj2-toolbar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--ctl-md);
  padding: 0 var(--space-5);
  border-bottom: 1px solid var(--color-border);
  background: var(--color-hover);
  font-size: var(--fs-12-5);
  color: var(--color-text-2);
}
.zj2-toolbar__sp {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.zj2-toolbar strong {
  color: var(--color-text);
  font-size: var(--fs-13);
  font-weight: 600;
}

/* ─────────────────────────────────────────────────────────────────────────────
 * 1. 按钮 —— 三型（主 / 次 / 幽灵）× 两尺寸（sm / md）
 *    一屏只准有 1 个主按钮；破坏性操作也用「次」+ 红色文字，不新增第四型。
 * ────────────────────────────────────────────────────────────────────────── */
.zj2-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: var(--ctl-md);
  padding: 0 var(--space-7);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-4);
  background: var(--color-card);
  color: var(--color-text);
  font-family: inherit;
  font-size: var(--fs-13-5);
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--dur-1) var(--ease-1),
              border-color var(--dur-1) var(--ease-1),
              box-shadow var(--dur-1) var(--ease-1);
}
.zj2-btn:hover { background: var(--color-hover); }
.zj2-btn:focus-visible { outline: none; box-shadow: var(--ring-primary); }
.zj2-btn:disabled,
.zj2-btn[aria-disabled="true"] {
  background: var(--color-hover);
  border-color: var(--color-border-light);
  color: var(--color-text-3);
  cursor: not-allowed;
}

/* 主：一屏一个，落在「导出报价单 / 保存」这类决定动作上 */
.zj2-btn--primary {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-on-primary);
  font-weight: 500;
}
.zj2-btn--primary:hover { background: var(--color-primary-dark); border-color: var(--color-primary-dark); }
.zj2-btn--primary:disabled,
.zj2-btn--primary[aria-disabled="true"] { color: var(--color-on-primary); }

/* 次：默认型（白底描边）。危险动作用 .zj2-btn--primary 也不许 —— 用本型 + .zj2-danger 文字色 */
.zj2-btn--secondary { background: var(--color-card); }

/* 幽灵：无边框，只用于表格行尾/工具条等密集处 */
.zj2-btn--ghost {
  background: transparent;
  border-color: transparent;
  color: var(--color-text-2);
}
.zj2-btn--ghost:hover { background: var(--color-hover); color: var(--color-text); }

.zj2-btn--sm {
  height: var(--ctl-sm);
  padding: 0 var(--space-5);
  border-radius: var(--radius-3);
  font-size: var(--fs-13);
}
.zj2-btn--block { width: 100%; }

/* ─────────────────────────────────────────────────────────────────────────────
 * 2. 输入与选择 —— 高度对齐 --ctl-md，键盘聚焦用可见环（鼠标点击不出现）
 * ────────────────────────────────────────────────────────────────────────── */
.zj2-fields {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-6) var(--space-7);
}
.zj2-field { display: grid; gap: var(--space-2); min-width: 0; }
.zj2-field--full { grid-column: 1 / -1; }
.zj2-label {
  font-size: var(--fs-12-5);
  color: var(--color-text-2);
  line-height: var(--lh-tight);
}
.zj2-label__req { color: var(--color-error); }
.zj2-help { font-size: var(--fs-12); color: var(--color-text-3); }

.zj2-input {
  width: 100%;
  height: var(--ctl-md);
  padding: 0 var(--space-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-4);
  background: var(--color-card);
  color: var(--color-text);
  font-family: inherit;
  font-size: var(--fs-13-5);
  line-height: var(--lh-tight);
  transition: border-color var(--dur-1) var(--ease-1),
              box-shadow var(--dur-1) var(--ease-1);
}
.zj2-input::placeholder { color: var(--color-text-3); }
.zj2-input:focus-visible {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: var(--ring-primary);
}
.zj2-input--sm { height: var(--ctl-sm); font-size: var(--fs-13); padding: 0 var(--space-4); }
.zj2-input--invalid { border-color: var(--color-error); }
.zj2-input--invalid:focus-visible { border-color: var(--color-error); box-shadow: var(--ring-error); }
.zj2-input:disabled,
.zj2-input[readonly] { background: var(--color-hover); color: var(--color-text-3); }

/* 选择框：箭头用 CSS 画（不用 emoji / 不用内联 SVG data-uri 带色值） */
.zj2-select-wrap { position: relative; display: block; min-width: 0; }
.zj2-select-wrap::after {
  content: "";
  position: absolute;
  right: var(--space-5);
  top: 50%;
  width: 6px;
  height: 6px;
  border-right: 1.5px solid var(--color-text-3);
  border-bottom: 1.5px solid var(--color-text-3);
  transform: translateY(-70%) rotate(45deg);
  pointer-events: none;
}
.zj2-select {
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  padding-right: var(--space-11);
}

/* 多行：只给备注/条款用；行高走 --lh-normal */
.zj2-textarea {
  height: auto;
  min-height: 76px;
  padding: var(--space-3) var(--space-5);
  line-height: var(--lh-normal);
  resize: vertical;
}

/* ─────────────────────────────────────────────────────────────────────────────
 * 3. 标签 chip —— 三态：默认 / 待审(pending) / 已生效(ok)
 *    状态色只借 tint（8% 底）+ 真值文字色，不做实心色块。
 * ────────────────────────────────────────────────────────────────────────── */
.zj2-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  height: 20px;
  padding: 0 var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--color-hover);
  color: var(--color-text-2);
  font-size: var(--fs-12);
  white-space: nowrap;
}
.zj2-chip::before {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--color-text-3);
}
.zj2-chip--pending { background: var(--tint-primary-8); color: var(--color-primary); }
.zj2-chip--pending::before { background: var(--color-secondary); }
.zj2-chip--ok { background: var(--tint-success-8); color: var(--color-success); }
.zj2-chip--ok::before { background: var(--color-success); }
.zj2-chip--plain::before { display: none; }

/* ─────────────────────────────────────────────────────────────────────────────
 * 4. 表格 —— 三档密度（compact 30 / normal 36 / comfy 44）
 *    数字列：td.zj2-r + .zj2-num（等宽 + tabular-nums，右对齐按位可比）
 *    分组行：tr.zj2-group
 * ────────────────────────────────────────────────────────────────────────── */
.zj2-table-wrap { overflow-x: auto; }
.zj2-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  background: var(--color-card);
  font-size: var(--fs-13-5);
  --zj2-row: var(--row-normal);
}
.zj2-table--compact { --zj2-row: var(--row-compact); font-size: var(--fs-13); }
.zj2-table--comfy { --zj2-row: var(--row-comfy); }

.zj2-table thead th {
  height: var(--row-th);
  padding: 0 var(--space-4);
  background: var(--color-hover);
  border-bottom: 1px solid var(--color-border);
  color: var(--color-text-3);
  font-size: var(--fs-12-5);
  font-weight: 500;
  letter-spacing: 0.04em;
  text-align: left;
  white-space: nowrap;
}
.zj2-table tbody td {
  height: var(--zj2-row);
  padding: 0 var(--space-4);
  border-bottom: 1px solid var(--color-border-light);
  color: var(--color-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.zj2-table tbody tr:last-child td { border-bottom: none; }
.zj2-table tbody tr:hover td { background: var(--color-hover); }

.zj2-table th.zj2-r,
.zj2-table td.zj2-r { text-align: right; }

/* 选中行：左 3px 主色条 + 8% 主色底（d2 的键盘流选中态） */
.zj2-table tbody tr.is-on td { background: var(--tint-primary-8); }
.zj2-table tbody tr.is-on td:first-child {
  box-shadow: inset 3px 0 0 var(--color-primary);
  font-weight: 600;
}

/* 分组行：按国家/日期/操作人分组时的一行小标题（不参与数字对齐） */
.zj2-table tbody tr.zj2-group td {
  height: 26px;
  background: var(--color-hover);
  color: var(--color-text-2);
  font-size: var(--fs-12);
  font-weight: 500;
  letter-spacing: 0.06em;
}
.zj2-table tbody tr.zj2-group:hover td { background: var(--color-hover); }

/* ─────────────────────────────────────────────────────────────────────────────
 * 5. 卡片 —— 皮肤取 d3：12px 圆角 + 一级阴影，不做描边重线
 *    --line 变体给密集后台页用（描边、无阴影，省掉阴影叠影）
 * ────────────────────────────────────────────────────────────────────────── */
.zj2-card {
  background: var(--color-card);
  border-radius: var(--radius-6);
  box-shadow: var(--shadow-1);
  min-width: 0;
}
.zj2-card--line {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-5);
  box-shadow: none;
}
.zj2-card__hd {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-7) var(--space-9) 0;
  font-size: var(--fs-14);
  font-weight: 600;
  color: var(--color-text);
}
.zj2-card__hd small {
  margin-left: auto;
  font-size: var(--fs-12-5);
  font-weight: 400;
  color: var(--color-text-3);
}
.zj2-card__bd { padding: var(--space-7) var(--space-9) var(--space-8); }
.zj2-card__ft {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-5) var(--space-9);
  border-top: 1px solid var(--color-border-light);
  font-size: var(--fs-12-5);
  color: var(--color-text-3);
}

/* ─────────────────────────────────────────────────────────────────────────────
 * 6. KPI 卡 —— 数值等宽右可比；hot 变体只给「要人今天处理」的那个数
 * ────────────────────────────────────────────────────────────────────────── */
.zj2-kpis {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-6);
}
.zj2-kpi {
  background: var(--color-card);
  border-radius: var(--radius-6);
  box-shadow: var(--shadow-1);
  padding: var(--space-7) var(--space-8);
  min-width: 0;
}
.zj2-kpi__t { font-size: var(--fs-12-5); color: var(--color-text-2); }
.zj2-kpi__v {
  margin-top: var(--space-1);
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-26);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--color-text);
}
.zj2-kpi__d { margin-top: var(--space-1); font-size: var(--fs-12); color: var(--color-text-3); }
.zj2-kpi--hot .zj2-kpi__v { color: var(--color-primary); }

/* ─────────────────────────────────────────────────────────────────────────────
 * 7. 分段控件 segmented —— 切换同一份数据的看法（按国家/按类别、今天/本周）
 *    --line 变体 = 密集页里的细边框版（d2 口径）
 * ────────────────────────────────────────────────────────────────────────── */
.zj2-seg {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border-radius: var(--radius-4);
  background: var(--color-bg);
}
.zj2-seg__item {
  appearance: none;
  border: none;
  background: none;
  height: 28px;
  padding: 0 var(--space-5);
  border-radius: var(--radius-3);
  color: var(--color-text-2);
  font-family: inherit;
  font-size: var(--fs-13);
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--dur-1) var(--ease-1), color var(--dur-1) var(--ease-1);
}
.zj2-seg__item:hover { color: var(--color-text); }
.zj2-seg__item:focus-visible { outline: none; box-shadow: var(--ring-primary); }
.zj2-seg__item.is-on {
  background: var(--color-card);
  color: var(--color-text);
  font-weight: 500;
  box-shadow: 0 1px 2px var(--tint-text-8);
}
.zj2-seg--line {
  gap: 0;
  padding: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-1);
  background: var(--color-card);
  overflow: hidden;
}
.zj2-seg--line .zj2-seg__item { height: 30px; border-radius: 0; padding: 0 var(--space-4); font-size: var(--fs-12); }
.zj2-seg--line .zj2-seg__item.is-on {
  background: var(--tint-primary-8);
  color: var(--color-primary);
  font-weight: 600;
  box-shadow: none;
}

/* ─────────────────────────────────────────────────────────────────────────────
 * 8. 抽屉抽屉 panel —— 右侧滑出，宽 460px（≤92vw）；遮罩用 14% 文字色
 *    --static 只用于组件预览页/内嵌说明，生产一律用浮层版
 * ────────────────────────────────────────────────────────────────────────── */
.zj2-scrim {
  position: fixed;
  inset: 0;
  background: var(--tint-text-14);
  z-index: var(--z-scrim);
}
.zj2-panel {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: var(--z-panel);
  display: flex;
  flex-direction: column;
  width: min(460px, 92vw);
  background: var(--color-card);
  border-left: 1px solid var(--color-border);
  box-shadow: var(--shadow-2);
}
.zj2-panel__hd {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-7) var(--space-8);
  border-bottom: 1px solid var(--color-border);
  font-size: var(--fs-14);
  font-weight: 600;
}
.zj2-panel__hd .zj2-btn--ghost { margin-left: auto; }
.zj2-panel__bd { flex: 1; overflow: auto; padding: var(--space-8); }
.zj2-panel__ft {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  justify-content: flex-end;
  padding: var(--space-5) var(--space-8);
  border-top: 1px solid var(--color-border);
  background: var(--color-hover);
}
.zj2-panel--static {
  position: static;
  width: auto;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-5);
  box-shadow: var(--shadow-1);
}

/* ─────────────────────────────────────────────────────────────────────────────
 * 9. 空态 / 加载骨架 / 错误态
 * ────────────────────────────────────────────────────────────────────────── */
.zj2-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  padding: var(--space-11) var(--space-8);
  text-align: center;
}
.zj2-empty__icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-6);
  background: var(--color-bg);
  color: var(--color-text-3);
}
.zj2-empty__t { font-size: var(--fs-13-5); color: var(--color-text-2); }
.zj2-empty__d { font-size: var(--fs-12-5); color: var(--color-text-3); }
.zj2-empty__act { margin-top: var(--space-2); }

.zj2-sk {
  border-radius: var(--radius-1);
  background: linear-gradient(
    90deg,
    var(--color-border-light) 25%,
    var(--color-hover) 37%,
    var(--color-border-light) 63%
  );
  background-size: 400% 100%;
  animation: zj2-sk-sweep 1.2s var(--ease-1) infinite;
}
@keyframes zj2-sk-sweep {
  0% { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}
@media (prefers-reduced-motion: reduce) {
  .zj2-sk { animation: none; }
}
.zj2-sk--line { height: var(--fs-12); width: 100%; }
.zj2-sk--num { width: 64px; }
.zj2-sk--row { height: var(--row-normal); border-radius: 0; }
.zj2-sk--title { height: var(--fs-17); width: 40%; }

.zj2-error {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  padding: var(--space-5) var(--space-7);
  border: 1px solid var(--color-error);
  border-radius: var(--radius-5);
  background: var(--tint-error-8);
}
.zj2-error__t { font-size: var(--fs-13-5); font-weight: 600; color: var(--color-error); }
.zj2-error__d { margin-top: var(--space-1); font-size: var(--fs-12-5); color: var(--color-text-2); }
.zj2-error__act { margin-top: var(--space-3); }

/* ─────────────────────────────────────────────────────────────────────────────
 * 10. 分页 —— 左「共 N 条」右页码；当前页用主色 + 边框，不用实心块
 * ────────────────────────────────────────────────────────────────────────── */
.zj2-pager {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--fs-13);
  color: var(--color-text-2);
}
.zj2-pager__info {
  margin-right: auto;
  font-size: var(--fs-12-5);
  color: var(--color-text-3);
}
.zj2-pager__item {
  appearance: none;
  min-width: 28px;
  height: 28px;
  padding: 0 var(--space-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid transparent;
  border-radius: var(--radius-1);
  background: none;
  color: var(--color-text-2);
  font-family: var(--font-num);
  font-size: var(--fs-12-5);
  cursor: pointer;
}
.zj2-pager__item:hover { background: var(--color-hover); }
.zj2-pager__item:focus-visible { outline: none; box-shadow: var(--ring-primary); }
.zj2-pager__item.is-on {
  border-color: var(--color-border);
  background: var(--color-card);
  color: var(--color-primary);
  font-weight: 600;
}
.zj2-pager__item:disabled { color: var(--color-text-3); cursor: not-allowed; }
.zj2-pager__item:disabled:hover { background: none; }

/* ─────────────────────────────────────────────────────────────────────────────
 * 11. 面包屑 —— 分隔符用「/」，不用「·」（中点串已列为禁则）
 * ────────────────────────────────────────────────────────────────────────── */
.zj2-crumbs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
  font-size: var(--fs-12-5);
  color: var(--color-text-3);
}
.zj2-crumbs__item { color: var(--color-text-2); text-decoration: none; }
.zj2-crumbs__item:hover { color: var(--color-primary); }
.zj2-crumbs__item:focus-visible { outline: none; box-shadow: var(--ring-primary); border-radius: var(--radius-1); }
.zj2-crumbs__item.is-here { color: var(--color-text); font-weight: 500; }
.zj2-crumbs__sep { color: var(--color-border); }

/* ─────────────────────────────────────────────────────────────────────────────
 * 12. 提示条 —— info/ok/err/warn 四型，只做一行说明；动作永远是一个文字按钮
 * ────────────────────────────────────────────────────────────────────────── */
.zj2-alert {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-2);
  background: var(--color-hover);
  font-size: var(--fs-12-5);
  line-height: var(--lh-loose);
  color: var(--color-text-2);
}
.zj2-alert__t { color: var(--color-text); font-weight: 500; }
.zj2-alert__act { margin-left: auto; }
.zj2-alert--info { border-color: var(--tint-primary-14); background: var(--tint-primary-8); color: var(--color-primary-dark); }
.zj2-alert--info .zj2-alert__t { color: var(--color-primary); }
.zj2-alert--ok { border-color: var(--tint-success-8); background: var(--tint-success-8); }
.zj2-alert--ok .zj2-alert__t { color: var(--color-success); }
.zj2-alert--err { border-color: var(--color-error); background: var(--tint-error-8); }
.zj2-alert--err .zj2-alert__t { color: var(--color-error); }
.zj2-alert--warn { border-color: var(--tint-secondary-8); background: var(--tint-secondary-8); }
.zj2-alert--warn .zj2-alert__t { color: var(--color-text); }

/* ─────────────────────────────────────────────────────────────────────────────
 * 合价/汇总块（第二期骨架页直接复用；一页只准一个 --big）
 * ────────────────────────────────────────────────────────────────────────── */
.zj2-kv {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-5);
  padding: var(--space-2) 0;
  font-size: var(--fs-13-5);
  color: var(--color-text-2);
  border-bottom: 1px solid var(--color-border-light);
}
.zj2-kv:last-child { border-bottom: none; }
.zj2-kv b { color: var(--color-text); font-weight: 500; }
.zj2-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-5);
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
  font-size: var(--fs-13-5);
  color: var(--color-text-2);
}
.zj2-total__v {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-34);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--color-primary);
}
.zj2-total__v--md { font-size: var(--fs-23); }

/* ═══════════════════════════════════════════════════════════════════════════════
 * 10. 应用外壳 + 后台域页布局（卡 t_5e434e6f · UI 2/3 · **补缺类台账**）
 *
 * 为什么落在这里而不是 layout.css：`layout.css` 是 v1.0.x 时代 layout 段的**旧副本**
 * （style.css 里有一份更新过的同源段落），一旦把它 <link> 进 index.html，旧规则会在
 * 报价页上生效并造成 30px 级位移 —— 实测 `scripts/verify-smallheight-rows-ui.mjs`
 * 的 E「大屏零变化」4 条断言因此转红；把 layout.css 的 link 去掉后立即 64/64 全绿。
 * 故：**layout.css 一个字节不改**（回退面更小），外壳的 zj2- 类全部登记在本文件。
 *
 * 台账（新增类名，全部只出现在外壳/后台域页结构上，不与既有页面撞车）：
 *   .zj2-app / .zj2-app.is-bare / .zj2-app__nav / .zj2-app__main / .zj2-app__top
 *   .zj2-app__navtoggle (--foot)（卡 t_de7d978b 立 · 卡 t_863d5cb9 挪到导航栏底部 .zj2-nav__foot）
 *   .zj2-app.is-nav-collapsed（卡 t_de7d978b：抽屉收起态；宽只靠 --zj2-nav-w 变量，56px 图标栏）
 *   .zj2-nav__brand / .zj2-nav__group / .zj2-nav__gt / .zj2-nav__item / .zj2-nav__label / .zj2-nav__foot
 *   .zj2-app__search / .zj2-app__hint / .zj2-app__user / .zj2-app__who
 *   .zj2-admin / .zj2-admin__hd (__sub / __back) / .zj2-admin__bar (__filter) / .zj2-admin__kpis / .zj2-admin__cols
 *   .zj2-admin__kpi-ver（沿用 --fs-20，见 DESIGN-SYSTEM.md §二「KPI 变体」）
 *   .zj2-scrim[hidden] / .zj2-panel[hidden]（收起态开关；组件本体仍在 §8）
 * 纪律：本段**零裸色值/零裸字号/零裸间距**，像素常量只有三项结构尺寸
 *       （导航 200px / 顶栏 56px / 折叠栏 56px），其余全部 var(--…)。
 * ═══════════════════════════════════════════════════════════════════════════════ */
/* ============================================================================
   卡 t_5e434e6f（UI 2/3）：应用外壳 + 后台域页布局
   ----------------------------------------------------------------------------
   纪律（DESIGN-SYSTEM.md §6 禁则 1）：本段**不写任何裸色值/裸字号/裸间距**，
   一律 var(--…) 取 tokens.css 的令牌。本文件只写布局（grid/flex/断点/结构尺寸），
   观感（颜色、字阶、圆角、阴影）全部来自 tokens.css + components-v2.css。
   像素常量只留「结构尺寸」三项：导航 200px、顶栏 56px、折叠栏 56px。
   ========================================================================== */

/* ── 外壳骨架 ───────────────────────────────────────────────────────────── */
.zj2-app {
  display: grid;
  /* 卡 t_de7d978b（2026-10-26）：导航宽抽成**唯一变量** --zj2-nav-w（展开 200 / 收起 56）。
     网格列与右栏 clamp 都读它 ⇒ 「收起 = 展开 + 144」由变量驱动，不再有两份常数要同步。 */
  --zj2-nav-w: 200px;
  grid-template-columns: var(--zj2-nav-w) minmax(0, 1fr);
  min-height: 100vh;
  background: var(--color-bg);
  /* 收起/展开走过渡（卡面要求 ≤200ms ⇒ 用现役 --dur-1=120ms）；**只在用户点开关时挂**（.is-nav-anim，
     由 app.js 临时加上），否则窗口缩放时 1fr 列宽变化也会被动画化，测量与重排会拿到过渡中的尺寸。 */
}
.zj2-app.is-nav-anim {
  transition: grid-template-columns var(--dur-1) var(--ease-1);
}
@media (prefers-reduced-motion: reduce) {
  .zj2-app.is-nav-anim { transition: none; }
}

/* is-bare = 未登录/对外分享页：外壳整体退场，#app 占满（与改造前逐像素一致） */
.zj2-app.is-bare {
  display: block;
  background: transparent;
  /* 卡 t_de7d978b：bare 页外壳退场，导航不存在 ⇒ 导航宽必须钉回展开值，
     否则「先收起导航再进登录/分享页」会让下面那条右栏 clamp 少算 144px（is-bare 路径被污染）。
     收起规则全部写成 :not(.is-bare)，这里是第二道保险。 */
  --zj2-nav-w: 200px;
}
.zj2-app.is-bare > .zj2-app__nav,
.zj2-app.is-bare > .zj2-app__main > .zj2-app__top {
  display: none;
}

/* ── 左侧分组导航（200px，sticky 满高） ────────────────────────────────── */
.zj2-app > .zj2-app__nav {
  position: sticky;
  top: 0;
  align-self: start;
  height: 100vh;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-5) var(--space-3) var(--space-3);
  overflow-y: auto;
  background: var(--color-card);
  border-right: 1px solid var(--color-border);
}

.zj2-nav__brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-4) var(--space-6);
  color: var(--color-primary);
  font-size: var(--fs-14);
  font-weight: 700;
  text-decoration: none;
}
.zj2-nav__brand svg { width: 18px; height: 18px; flex-shrink: 0; }

.zj2-nav__group { display: flex; flex-direction: column; gap: 2px; }

.zj2-nav__gt {
  padding: var(--space-3) var(--space-4) var(--space-1);
  color: var(--color-text-3);
  font-size: var(--fs-12);
}

/* 当前项：左侧 3px 主色竖条 + 浅底；其余 = --color-text-2 纯文字 */
.zj2-nav__item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 34px;
  padding: 0 var(--space-4);
  border-radius: var(--radius-3);
  box-shadow: inset 3px 0 0 transparent;
  color: var(--color-text-2);
  font-size: var(--fs-13-5);
  line-height: var(--lh-tight);
  text-decoration: none;
  transition: background var(--dur-1) var(--ease-1), color var(--dur-1) var(--ease-1);
}
.zj2-nav__item svg { width: 16px; height: 16px; flex-shrink: 0; }
.zj2-nav__item:hover { background: var(--color-hover); color: var(--color-text); }
.zj2-nav__item.is-on {
  background: var(--tint-primary-8);
  box-shadow: inset 3px 0 0 var(--color-primary);
  color: var(--color-primary);
  font-weight: 600;
}
.zj2-nav__item:focus-visible { outline: none; box-shadow: var(--ring-primary); }

.zj2-nav__foot { margin-top: auto; padding-top: var(--space-5); }

/* ── 卡 t_de7d978b（2026-10-26）：导航抽屉 —— 用户手动收起态 ──────────────────
 * 收起 = 56px 图标窄栏（**不收到 0**：图标仍可点，title 悬停出文字），展开 = 200px（现状）。
 * 两态只做两件事：① 改 --zj2-nav-w（网格列与右栏 clamp 都读它）② 隐文字/居中图标。
 * 视觉规则与下面 `@media (max-width: 1279px)` 的窄屏收起同形（那档是自动收起，本段是手动抽屉）。
 * 全部带 `:not(.is-bare)`：bare 页（未登录/对外分享）外壳整体退场，不受抽屉状态影响。 */
.zj2-app.is-nav-collapsed:not(.is-bare) {
  --zj2-nav-w: 56px;
}
.zj2-app.is-nav-collapsed:not(.is-bare) > .zj2-app__nav {
  align-items: center;
  padding: var(--space-4) var(--space-2);
}
.zj2-app.is-nav-collapsed:not(.is-bare) .zj2-nav__label,
.zj2-app.is-nav-collapsed:not(.is-bare) .zj2-nav__gt {
  display: none;
}
.zj2-app.is-nav-collapsed:not(.is-bare) .zj2-nav__brand {
  justify-content: center;
  padding: var(--space-2) 0 var(--space-5);
}
.zj2-app.is-nav-collapsed:not(.is-bare) .zj2-nav__item {
  justify-content: center;
  width: 40px;
  padding: 0;
}
.zj2-app.is-nav-collapsed:not(.is-bare) .zj2-nav__foot .zj2-btn {
  width: 40px;
  padding: 0;
}

/* 折叠开关：卡 t_863d5cb9 起在**左侧导航栏底部**（.zj2-nav__foot 第一个元素，退出之上），
   **两态都在**（收起后也点得到 —— 「收起来找不到入口」的反例） */
.zj2-app__navtoggle {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-3);
  background: var(--color-card);
  color: var(--color-text-2);
  cursor: pointer;
  transition: background var(--dur-1) var(--ease-1), color var(--dur-1) var(--ease-1);
}
.zj2-app__navtoggle:hover { background: var(--color-hover); color: var(--color-text); }
.zj2-app__navtoggle:focus-visible { outline: none; box-shadow: var(--ring-primary); }
.zj2-app__navtoggle svg { width: 16px; height: 16px; }

/* ── 卡 t_863d5cb9：开关挪到导航底部（`.zj2-nav__foot` 第一个元素，退出登录之上）─────
 * 展开态：占满整行（100%），图标 + 文字「收起导航」横排居中，下留 8px 与「退出」分开；
 * 收起态：56px 窄栏里只留 40px 图标块居中（栏内可用 56 − 2×--space-2 = 44px ⇒ 40 不溢出、不压退出）。
 * 文字用既有的 `.zj2-nav__label`：收起态 / ≤1279 两处现成规则会一起把它隐掉，不再另写一份开关。 */
.zj2-app__navtoggle--foot {
  display: flex;
  width: 100%;
  gap: var(--space-3);
  margin: 0 0 var(--space-3);
}
.zj2-app__navtoggle--foot .zj2-nav__label { white-space: nowrap; }
.zj2-app.is-nav-collapsed:not(.is-bare) .zj2-app__navtoggle--foot {
  width: 40px;
  gap: 0;
  margin-left: auto;
  margin-right: auto;
}

/* ── 主区 + 顶栏 56px ──────────────────────────────────────────────────── */
.zj2-app__main {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.zj2-app__main > #app { min-width: 0; }

.zj2-app__top {
  position: sticky;
  top: 0;
  z-index: 30;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: var(--space-6);
  height: 56px;
  padding: 0 var(--space-8);
  background: var(--color-card);
  border-bottom: 1px solid var(--color-border);
}

.zj2-app__search {
  position: relative;
  display: flex;
  align-items: center;
  flex: 0 1 420px;
  min-width: 0;
}
.zj2-app__search svg {
  position: absolute;
  left: var(--space-4);
  width: 14px;
  height: 14px;
  color: var(--color-text-3);
  pointer-events: none;
}
.zj2-app__search .zj2-input {
  width: 100%;
  padding-left: 30px;
}

.zj2-app__hint {
  min-width: 0;
  overflow: hidden;
  color: var(--color-text-3);
  font-size: var(--fs-12);
  white-space: nowrap;
  text-overflow: ellipsis;
}

.zj2-app__user {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-left: auto;
  color: var(--color-text-2);
  font-size: var(--fs-13);
  white-space: nowrap;
}
.zj2-app__user .zj2-app__who { color: var(--color-text); font-weight: 600; }

/* ── 后台域页（card t_5e434e6f §2/§3）───────────────────────────────────── */
.zj2-admin {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  padding: var(--space-8) var(--space-10) var(--space-11);
}
.zj2-admin__hd {
  display: flex;
  align-items: baseline;
  gap: var(--space-5);
  flex-wrap: wrap;
}
.zj2-admin__hd h1 {
  margin: 0;
  color: var(--color-text);
  font-size: var(--fs-23);
  font-weight: 700;
  line-height: var(--lh-tight);
}
.zj2-admin__hd .zj2-admin__sub {
  color: var(--color-text-3);
  font-size: var(--fs-12-5);
}
.zj2-admin__hd .zj2-admin__back {
  margin-left: auto;
  color: var(--color-text-2);
  font-size: var(--fs-12-5);
  text-decoration: none;
}
.zj2-admin__hd .zj2-admin__back:hover { color: var(--color-primary); }

/* 筛选条：域切换（胶囊）→ 域内页签（线型分段）→ 关键词 */
.zj2-admin__bar {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  flex-wrap: wrap;
}
.zj2-admin__bar .zj2-admin__filter {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
  min-width: 0;
}
.zj2-admin__bar .zj2-admin__filter .zj2-input { width: 220px; }

.zj2-admin__kpis {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-8);
}
@media (max-width: 1279px) {
  .zj2-admin__kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.zj2-admin__cols {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  gap: var(--space-8);
  align-items: start;
}
@media (max-width: 1279px) {
  .zj2-admin__cols { grid-template-columns: minmax(0, 1fr); }
}

/* ── <1280：导航收成图标栏（56px）────────────────────────────────────────
   注：响应式断点只作用于外壳自己的类名；public/css/responsive.css 的移动端规则
   一行未改，且它不认识 zj2- 前缀 ⇒ 两者互不影响。 */
@media (max-width: 1279px) {
  .zj2-app { grid-template-columns: 56px minmax(0, 1fr); }
  .zj2-app > .zj2-app__nav {
    align-items: center;
    padding: var(--space-4) var(--space-2);
  }
  .zj2-nav__label,
  .zj2-nav__gt { display: none; }
  .zj2-nav__brand { justify-content: center; padding: var(--space-2) 0 var(--space-5); }
  .zj2-nav__item { justify-content: center; padding: 0; width: 40px; }
  /* 卡 t_863d5cb9：≤1279 外壳本来就窄成 56px，底部开关也只能是 40px 图标块（文字已被上一条隐掉） */
  .zj2-app__navtoggle--foot { width: 40px; margin-left: auto; margin-right: auto; }
  .zj2-app__top { padding: 0 var(--space-6); }
  .zj2-app__search { flex: 1 1 auto; }
  .zj2-app__hint { display: none; }
  .zj2-admin { padding: var(--space-7) var(--space-6) var(--space-10); }
}

/* ── 抽屉：组件本体一律用 components-v2.css 的 .zj2-panel / .zj2-scrim（不新造），
      这里只补一条「收起态」的显示开关：面板/遮罩隐藏时用 hidden 属性即可。 ────── */
.zj2-scrim[hidden],
.zj2-panel[hidden] { display: none; }

/* 版本号这类「非金额」KPI：按 DESIGN-SYSTEM.md §二 用 --fs-20（26 档只给金额/计数） */
.zj2-admin__kpi-ver .zj2-kpi__v { font-size: var(--fs-20); }

/* ═══════════════════════════════════════════════════════════════════════════════
 * 11. 报价录入页三栏工作台（卡 t_220314f4 · UI 3/3 · **补缺类台账**）
 *
 * 骨架照 docs/design/proto-20261025/proto-d2.html（条件 / 明细 / 汇总），
 * 皮肤照 proto-d3（12px 圆角 + 一级阴影 + 等宽数字）。
 *
 * 台账（新增类名，全部只在报价录入页这三栏结构上出现）：
 *   .zj2-wb-cond (__hd / __mode / __body / __row / __v / __note)
 *   .zj2-wb-chips / .zj2-wb-chip (__x) / .zj2-wb-chip--btn
 *   .zj2-wb-mid (__hd / __body / __sp) / .zj2-wb-table / .zj2-wb-c-ctry / .zj2-wb-c-cls
 *   .zj2-wb-grp / .zj2-wb-row / .zj2-wb-cell / .is-ov（覆盖标记）/ .zj2-wb-sub / .zj2-wb-input
 *   .zj2-wb-foot (__l / __v / __meta / __acts) / .zj2-wb-hint / .is-warn
 *
 * 纪律：
 *   · **零裸色值**（只用 tokens.css 的 var(--…)；半透明底只准 --tint-* 两档）；
 *   · **零裸字号/间距**（一律 var(--fs-…)/var(--space-…)）；
 *   · 不改 style.css 一行 —— 三栏宽度只用 :has() 在本文件里"看到中栏才生效"，
 *     旧结构（无中栏）逐字节仍是原来的两栏比例（D30–D36 读的是 style.css 级联值，保持绿）。
 *   · ≤1279px 收起中栏（窄屏回到改造前的两栏行为，不挤、不横向溢出）。
 * ═══════════════════════════════════════════════════════════════════════════════ */

/* ── 三栏宽度配比：仅当 .app-layout 里真有中栏时才生效 ───────────────────── */
.app-layout {
  align-items: stretch;
}
.app-layout:has(> .zj2-wb-mid) > .left-panel {
  flex: 0 0 340px;
  width: 340px;
  min-width: 300px;
}
.app-layout:has(> .zj2-wb-mid) > .right-panel {
  /* 右栏优先 480（协调方 2026-10-25 裁定「回宽到 480」），但明细列不许被挤（同一条裁定的本意）。
     ⚠ 实测：1440 宽下三栏的**可用宽只有 1212px**（外壳左导航 200px + .app-layout padding 14×2
     + 两处 gap 14×2 + 左栏 340 已占 596），故 1440 下「右 480 + 中 ≥620」在算术上不可能
     （需右栏 ≤ 224）。实测裁切读数（scripts/verify-wb-ui.mjs ⑪，同一台机器真 Chromium）：
       右 560 → 中 284，裁切 32 格 ｜ 右 480 → 中 364，裁切 1 格 ｜ 右 444 → 中 400，裁切 0
       右 424 → 中 420，裁切 0 ｜ 右 420 → 中 424，裁切 0
     ⇒ 取 clamp(420, 100vw − 1020, 480)：
       · ≥1500 宽：右栏 480（裁定要求的那一档），中栏 = 100vw − 1076 ≥ 424
       · 1440 宽：右栏 420（=「明细零裁切」的最宽右栏），中栏 424（该屏物理上限）
     1020 = 外壳左导航 200 + padding 28 + gap 28 + 左栏 340 + 中栏下限 424；改动任一项须同步此数。

     ── 卡 t_de7d978b（2026-10-26，zhujie-worker-2）：上面的 1020 已**抽成变量** ──────────
     导航改成可收起的抽屉（展开 200 / 收起 56）后，这个常数必须跟着导航走，否则收起后右栏
     还按 200 算，白省下的 144px 会被右栏吃掉：
       width: clamp(var(--zj2-right-min), calc(100vw − (var(--zj2-nav-w) + 820px)), 480px)
       · var(--zj2-nav-w) 只在 .zj2-app 上定义（展开 200 / 收起 56），bare 页钉回 200；
       · 820 = padding 28 + gap 28 + 左栏 340 + 中栏下限 424（**不再是 1020**：导航宽已单独入变量）。
     ⇒ 现行算式（真 Chromium 实测 10 组，scripts/verify-wb-ui.mjs ⑫）：
       展开：1920 中 844 / 1600 中 524 / 1440 中 424（右 420）/ 1366 中 350 / 1280 中 264
       收起：1920 中 988 / 1600 中 668 / 1440 中 508 / 1366 中 434 / 1280 中 424（右 404）
       「收起 = 展开 + 144」逐档成立（144 = 200 − 56）。
     收起态右栏下限降到 404（协调方 2026-10-26 批准）：用户主动收起就是为了看明细，右栏让 16px
     换来 1280 档「中 424 / 零裁切」。展开态下限仍是 420。 */
  --zj2-right-min: 420px;
  width: clamp(var(--zj2-right-min), calc(100vw - (var(--zj2-nav-w) + 820px)), 480px);
}
/* 收起态：右栏下限让到 404（只改下限变量，clamp 表达式仍**只有一份**） */
.zj2-app.is-nav-collapsed:not(.is-bare) .app-layout:has(> .zj2-wb-mid) > .right-panel {
  --zj2-right-min: 404px;
}
.app-layout:has(> .zj2-wb-mid) > .zj2-wb-mid {
  flex: 1 1 auto;
  min-width: 0;
}

/* ── 左栏「条件」区 ─────────────────────────────────────────────────────── */
.zj2-wb-cond {
  flex: 0 0 auto;
  border-bottom: 1px solid var(--color-border);
  background: var(--color-card);
}
.zj2-wb-cond__hd {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  height: var(--row-th);
  padding: 0 var(--space-5);
  border-bottom: 1px solid var(--color-border-light);
  background: var(--color-hover);
}
.zj2-wb-cond__hd b { font-size: var(--fs-13); color: var(--color-text); }
.zj2-wb-cond__mode {
  margin-left: auto;
  font-size: var(--fs-12);
  color: var(--color-primary);
  background: var(--tint-primary-8);
  border-radius: var(--radius-1);
  padding: 0 var(--space-2);
}
.zj2-wb-cond__body {
  display: grid;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-5) var(--space-5);
}
.zj2-wb-cond__row { display: grid; gap: var(--space-2); }
.zj2-wb-cond__v {
  font-size: var(--fs-12-5);
  color: var(--color-text-2);
  line-height: var(--lh-normal);
}
.zj2-wb-cond__note { min-height: var(--space-11); resize: vertical; font-size: var(--fs-12-5); }

/* chip 组（国家 / 类别） */
.zj2-wb-chips { display: flex; flex-wrap: wrap; gap: var(--space-1); }
.zj2-wb-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  max-width: 100%;
  padding: 0 var(--space-2);
  height: var(--ctl-sm);
  font-size: var(--fs-12);
  color: var(--color-text-2);
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-1);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.zj2-wb-chip__x {
  font-style: normal;
  color: var(--color-text-3);
  font-size: var(--fs-12);
}
.zj2-wb-chip--btn { cursor: pointer; color: var(--color-primary); }
.zj2-wb-chip--btn:hover { background: var(--tint-primary-8); }

/* ── 中栏「明细」─────────────────────────────────────────────────────────── */
.zj2-wb-mid {
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
  background: var(--color-card);
  border-radius: var(--radius-6);
  box-shadow: var(--shadow-1);
  outline: none;
}
.zj2-wb-mid:focus-visible { box-shadow: var(--shadow-1), var(--ring-primary); }
.zj2-wb-mid__hd {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  height: var(--row-th);
  padding: 0 var(--space-5);
  border-bottom: 1px solid var(--color-border);
  background: var(--color-hover);
}
.zj2-wb-mid__hd b { font-size: var(--fs-13); color: var(--color-text); }
.zj2-wb-mid__sp { margin-left: auto; }
.zj2-wb-mid__body { flex: 1 1 auto; min-height: 0; overflow: auto; }
.zj2-wb-table thead th { position: sticky; top: 0; z-index: 1; }
/* 列宽：类别列给固定 px（百分比在 1440 三栏下只剩 29px，'03' 会被裁掉 —— 实测 9 个类别格
   scrollWidth > clientWidth）；国家列同时从 26% 收到 22%，把省下的宽度分给 4 个金额列。 */
.zj2-wb-c-ctry { width: 22%; }
.zj2-wb-c-cls { width: 44px; }
.zj2-wb-grp { cursor: pointer; }
.zj2-wb-row:hover td { background: var(--color-hover); }
.zj2-wb-sub { font-weight: 600; }

/* 可编辑金额格：默认像文本，hover/focus 才露出「可改」的样子 */
.zj2-wb-cell { cursor: text; }
.zj2-wb-cell:hover { background: var(--tint-primary-8); }
.zj2-wb-cell.is-ov { position: relative; color: var(--color-primary); font-weight: 600; }
.zj2-wb-cell.is-ov::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  border-width: 0 6px 6px 0;
  border-style: solid;
  border-color: transparent var(--color-primary) transparent transparent;
}
.zj2-wb-input {
  width: 100%;
  height: calc(var(--row-compact) - 8px);
  padding: 0 var(--space-2);
  font-size: var(--fs-13);
  text-align: right;
  color: var(--color-text);
  background: var(--color-card);
  border: 1px solid var(--color-primary);
  border-radius: var(--radius-1);
  outline: none;
  box-shadow: var(--ring-primary);
}

/* ── 底栏：合价永远可见 + 主/次 CTA ─────────────────────────────────────── */
.zj2-wb-foot {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex: 0 0 auto;
  padding: var(--space-3) var(--space-5);
  border-top: 1px solid var(--color-border);
  background: var(--color-card);
}
.zj2-wb-foot__l { font-size: var(--fs-12-5); color: var(--color-text-2); }
.zj2-wb-foot__v {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-23);
  font-weight: 600;
  color: var(--color-primary);
}
.zj2-wb-foot__meta { font-size: var(--fs-12); color: var(--color-text-3); }
.zj2-wb-foot__acts { margin-left: auto; display: flex; gap: var(--space-2); }

/* ── 右下角一行键盘提示（不弹窗、不遮挡）───────────────────────────────── */
.zj2-wb-hint {
  flex: 0 0 auto;
  padding: 0 var(--space-5) var(--space-3);
  font-size: var(--fs-12);
  color: var(--color-text-3);
  text-align: right;
}
.zj2-wb-hint.is-warn { color: var(--color-primary); }

/* ── ≤1279：收起中栏（窄屏回到改造前的两栏行为；不挤、不横向溢出）──────── */
@media (max-width: 1279px) {
  .zj2-wb-mid { display: none; }
  .app-layout:has(> .zj2-wb-mid) > .left-panel {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
  }
  .app-layout:has(> .zj2-wb-mid) > .right-panel { width: 560px; }
}

/* ─────────────────────────────────────────────────────────────────────────────
 * 12. 报价记录页台账列（卡 t_f6e67688 · P0-1 台账化 · **补缺类台账**）
 *
 *   只补「现成组件里没有的那几个类」，不外提、不改既有类：
 *     · .zj2-chip--void    状态第 4 态（作废 / 已过期）——既有 chip 只有 默认 / pending / ok 三态
 *     · .zj2-panel--wide   明细抽屉的宽版（快照原宽 700px 起步，460 装不下报价单）
 *     · .qd-acts           行操作单元（`position: relative` 给下拉菜单做定位上下文）
 *     · .zj2-menu / __item 行内「改状态」下拉（只列当前状态允许的去向；服务端仍会复核）
 *     · .qd-head           明细抽屉顶部的台账横幅（单号 / 状态 / 有效期 / 版本 / 创建人）
 *   配色一律走 tokens（本文件零裸色值纪律不变）。
 * ────────────────────────────────────────────────────────────────────────── */
.zj2-chip--void { background: var(--tint-error-8); color: var(--color-error); }
.zj2-chip--void::before { background: var(--color-error); }

.zj2-panel--wide { width: min(760px, 94vw); }

.qd-acts {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-1);
  flex-wrap: wrap;
}

.zj2-menu {
  position: absolute;
  top: calc(100% + var(--space-1));
  right: 0;
  z-index: var(--z-panel);
  min-width: 132px;
  padding: var(--space-1);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-3);
  background: var(--color-card);
  box-shadow: var(--shadow-2);
}
.zj2-menu__item {
  display: block;
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 0;
  border-radius: var(--radius-1);
  background: transparent;
  color: var(--color-text);
  font-family: inherit;
  font-size: var(--fs-12-5);
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}
.zj2-menu__item:hover { background: var(--color-hover); }
.zj2-menu__item.zj2-muted { cursor: default; }

.qd-head {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin-bottom: var(--space-5);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--color-border);
  font-size: var(--fs-12-5);
  color: var(--color-text-2);
}

/* ============================================================
   报价单「双版导出」按钮（卡 t_a5c2088b）—— 挂在 .rpt-acts 里，
   由 views/quotes.js#ensureActionsBar 注入（两枚：对外版 / 内部版）。
   基础版式沿用线上既有 .rpt-acts button；这里只补「两版可区分」的配色与留档行排版。
   ============================================================ */
.rpt-acts .btk {
  background: var(--color-card);
  color: var(--color-primary);
  border-color: var(--color-primary);
}

.rpt-acts .btk[data-exportkind="external"] {
  color: #1D7A46;
  border-color: #1D7A46;
}

.rpt-acts .btk:hover {
  background: var(--c-surface-brand-soft);
}

/* 抽屉底部「最近导出」那一行（留档表 quote_export_log 的只读投影） */
.qd-explog {
  display: block;
  margin-bottom: var(--space-1);
  font-size: var(--fs-12);
  word-break: break-all;
}

/* ─────────────────────────────────────────────────────────────────────────────
 * 13. 客户档案抽屉（卡 t_c1158dce：报价·P0-3 客户闭环）
 *    只补**缺的类**：基本信息的键值栅格 / 卡片段落间距 / 「上次同条件价」条件条与结果块。
 *    零裸色值、零裸字号、零裸间距 —— 全部走 tokens；既有类一行未改。
 *    结构骨架沿用 §8 抽屉（.zj2-panel/.zj2-panel__hd/__bd/__ft）与 §4/§5 表格/卡片。
 * ────────────────────────────────────────────────────────────────────────── */
.zj2-cust-sec { margin-bottom: var(--space-8); }
.zj2-cust-sec:last-child { margin-bottom: 0; }

/* 基本信息：两列键值（label 上、值下；窄屏收成一列） */
.zj2-kv-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-5) var(--space-7);
  margin: 0;
  font-size: var(--fs-13-5);
}
.zj2-kv-grid dt {
  color: var(--color-text-3);
  font-size: var(--fs-12-5);
  line-height: var(--lh-tight);
}
.zj2-kv-grid dd {
  margin: 0;
  color: var(--color-text);
  word-break: break-word;
}

/* 「上次同条件价」的条件条：商标 / 国家 / 类别 + 查询按钮一行排开，窄屏换行 */
.zj2-combo-cond {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-5);
  margin-bottom: var(--space-6);
}
.zj2-combo-cond .zj2-field { min-width: 140px; }

/* 查询结果块：浅底 + 圆角，与卡片区分（只用既有 token 的 8% 主色底） */
.zj2-cust-result {
  padding: var(--space-6) var(--space-7);
  border-radius: var(--radius-5);
  background: var(--tint-primary-8);
  font-size: var(--fs-13-5);
  line-height: var(--lh-normal);
}
.zj2-cust-result__main {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
  margin-bottom: var(--space-2);
  font-size: var(--fs-14);
}

/* 客户档案抽屉底栏（卡 t_c1158dce）：只读说明靠左、复购主按钮靠右。
   只新增一个类，不改 .zj2-panel__ft 既有规则（其余面板底栏逐字节不变）。 */
.zj2-panel__ft .zj2-cust-ftnote { margin-right: auto; }

/* ─────────────────────────────────────────────────────────────────────────────
 * 13. 出单体检卡（卡 t_7a64765b · P0-4 · **补缺类**）
 *
 *   抽屉里「导出前」常驻的三项体检查（汇率时效 / 规则缺口 / 毛利 + 服务端复算状态）。
 *   只新增类，不改任何既有类；配色一律走 tokens：
 *     · 通过 / 成功       → --color-success + --tint-success-8
 *     · 提示 / 黄         → --color-secondary（金，辅助强调）+ --tint-secondary-8
 *     · 阻断 / 红         → --color-error + --tint-error-8
 *     · 未判 / 灰         → --color-text-3 + --tint-text-8
 *   本文件零裸色值纪律不变（全部 var(--…)）。
 * ────────────────────────────────────────────────────────────────────────── */
.zj2-precheck {
  border-top: 1px solid var(--color-border);
  padding: var(--space-5) var(--space-7);
  background: var(--color-hover);
  max-height: 38vh;
  overflow: auto;
}
.zj2-precheck:empty { display: none; }

.zj2-pc { font-size: var(--fs-12-5); line-height: var(--lh-normal); }
.zj2-pc__hd {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin-bottom: var(--space-3);
}
.zj2-pc__list { list-style: none; margin: 0; padding: 0; }
.zj2-pc__item {
  display: grid;
  grid-template-columns: 76px 56px 1fr;
  gap: var(--space-2);
  align-items: start;
  padding: var(--space-1) 0;
  border-bottom: 1px dashed var(--color-border-light);
}
.zj2-pc__item:last-child { border-bottom: 0; }
.zj2-pc__k { color: var(--color-text-2); font-weight: 600; }
.zj2-pc__lv {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-1);
  padding: 0 var(--space-2);
  font-size: var(--fs-12);
  white-space: nowrap;
}
.zj2-pc__d { color: var(--color-text-2); word-break: break-word; }
.zj2-pc__item--red .zj2-pc__lv { background: var(--tint-error-8); color: var(--color-error); }
.zj2-pc__item--yellow .zj2-pc__lv { background: var(--tint-secondary-8); color: var(--color-secondary); }
.zj2-pc__item--ok .zj2-pc__lv { background: var(--tint-success-8); color: var(--color-success); }
.zj2-pc__item--unknown .zj2-pc__lv { background: var(--tint-text-8); color: var(--color-text-3); }
.zj2-pc--red { border-left: 3px solid var(--color-error); padding-left: var(--space-4); }
.zj2-pc--yellow { border-left: 3px solid var(--color-secondary); padding-left: var(--space-4); }
.zj2-pc--err { color: var(--color-error); }
.zj2-pc__re { margin-top: var(--space-3); color: var(--color-text-3); }
.zj2-pc__force {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border-light);
}
.zj2-pc__ck { display: inline-flex; align-items: center; gap: var(--space-1); color: var(--color-text-2); }
.zj2-pc__reason {
  flex: 1 1 220px;
  min-width: 160px;
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-3);
  font-size: var(--fs-12-5);
  background: var(--color-card);
  color: var(--color-text);
}
.zj2-pc__reason:disabled { background: var(--color-hover); color: var(--color-text-3); }

/* ═══════════════════════════════════════════════════════════════════════════════
 * 14. 经营看板（卡 t_9db9d1b1 · P1-2 · **补缺类台账**）
 *
 * 只包含既有组件表达不了的形状：6 列 KPI 栅格、图表卡、下钻条、口径脚注。
 * 颜色一律走 tokens（--color-* / --tint-*）；不新增色值、不改既有类的任何规则
 * （多色序列最多 5 色由 JS 侧的 token 取值顺序保证，CSS 不参与配色）。
 * ═══════════════════════════════════════════════════════════════════════════════ */

/* ── 14.1 6 列 KPI 栅格（概览「经营看板」用；窄屏逐级退到 3 / 2 / 1 列）── */
.zj2-kpis--6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
@media (max-width: 1500px) {
  .zj2-kpis--6 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 900px) {
  .zj2-kpis--6 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .zj2-kpis--6 { grid-template-columns: minmax(0, 1fr); }
}

/* ── 14.2 顶部控件条（标题 + 分段 + 含测试数据开关 + 自定义区间）── */
.zj2-dash__hd {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  flex-wrap: wrap;
  margin-bottom: var(--space-5);
}
.zj2-dash__title {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  font-size: var(--fs-20);
  font-weight: 600;
  color: var(--color-text);
}
.zj2-dash__title small { font-size: var(--fs-12); font-weight: 400; color: var(--color-text-3); }
.zj2-dash__custom { display: inline-flex; align-items: center; gap: var(--space-2); }
.zj2-check {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--fs-12-5);
  color: var(--color-text-2);
  cursor: pointer;
}

/* ── 14.3 区间说明行 / 提示条 / 脚注 ── */
.zj2-dash__range-line {
  margin: var(--space-4) 0 0;
  font-size: var(--fs-12-5);
  color: var(--color-text-2);
}
.zj2-dash__note {
  display: inline-block;
  margin-left: var(--space-2);
  padding: 0 var(--space-2);
  border-radius: var(--radius-1);
  background: var(--tint-secondary-8);
  color: var(--color-secondary);
}
.zj2-dash__low {
  margin-top: var(--space-4);
  padding: var(--space-3) var(--space-5);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-secondary);
  border-radius: var(--radius-2);
  background: var(--tint-secondary-8);
  color: var(--color-text-2);
  font-size: var(--fs-12-5);
}
.zj2-dash__foot {
  margin-top: var(--space-8);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border-light);
  color: var(--color-text-3);
  font-size: var(--fs-12);
  line-height: 1.7;
}
.zj2-dash__footline { white-space: normal; }

/* ── 14.4 三张图表卡（趋势 / 国别 / 业务线）：宽屏并排，窄屏单列 ── */
.zj2-dash__charts {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-6);
  margin-top: var(--space-6);
}
@media (max-width: 1280px) {
  .zj2-dash__charts { grid-template-columns: minmax(0, 1fr); }
}
.zj2-dash__chart .zj2-card__bd { padding-top: var(--space-4); }
.zj2-dash__canvas { position: relative; height: 260px; }
.zj2-dash__canvas canvas { max-width: 100%; }

/* ── 14.5 下钻条（报价记录页顶部：来自看板的条件可见、可清除）── */
.zj2-drillbar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin: var(--space-3) 0;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-primary);
  border-radius: var(--radius-2);
  background: var(--tint-primary-8);
}
.zj2-drillbar__t { font-size: var(--fs-12-5); color: var(--color-primary); font-weight: 600; }
