/* ==========================================================
 * 客户端专属样式：步骤条、定额栏、报价单列表、拖拽区、
 * 对比矩阵容器（Univer）、全屏、子工作表、合计栏、导出菜单、进度条
 * 设计语言：Windows 11 Fluent
 * ========================================================== */

.wrap { width: 100%; max-width: none; margin: 0 auto; padding: 24px 20px 60px; }

/* ========== 顶栏：Win11 卡片式标题栏 ========== */
header {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 18px 22px 20px; margin-bottom: 20px; box-shadow: var(--shadow-1);
  position: relative; overflow: hidden;
}
header::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--brand); }
header h1 { font-size: 22px; font-weight: 600; letter-spacing: -0.015em; color: var(--text); }
header p { color: var(--muted); margin-top: 6px; font-size: 13px; }
.header-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.header-actions { display: flex; align-items: center; gap: 10px; }

/* ========== 步骤条 ========== */
.steps { display: flex; gap: 10px; margin-bottom: 20px; flex-wrap: wrap; }
.step { flex: 1; min-width: 180px; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px; display: flex; gap: 12px; align-items: flex-start; box-shadow: var(--shadow-1); }
.step .num { width: 26px; height: 26px; border-radius: 50%; background: var(--brand); color: var(--on-brand); display: flex; align-items: center; justify-content: center; font-weight: 600; flex: none; font-size: 13px; }
.step b { display: block; font-size: 13px; }
.step span { color: var(--muted); font-size: 12px; }

/* ========== 对比矩阵容器 ========== */
.table-wrap { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); position: relative; overflow: hidden; box-shadow: var(--shadow-1); }
#resultWrap.fake-fullscreen { position: fixed; inset: 0; z-index: 500; background: var(--card); border: none; border-radius: 0; margin: 0 !important; display: flex; flex-direction: column; }
/* 全屏按钮：2026-10-17 已迁到标题行（导出之后、与导出同款 .btn .btn-primary，见 index.html + C34）；
   原右下角浮动圆形按钮样式（.fullscreen-btn）随迁移移除，勿恢复 */
footer { text-align: center; color: var(--muted); font-size: 12px; margin-top: 24px; }
.tab-panel { display: block; }

/* ========== 定额栏 ========== */
/* 定额模板 / 报价基准（2026-11-04 用户定：从独占一行并入底部动作行，原 .quota-bar 已删）
 * 左侧选「按什么比」，右侧是「存哪里 / 开始比」；空间不足时先让 meta 换行，再让整组换行。 */
.action-fields { display: flex; align-items: center; gap: 10px; flex: 1 1 520px; min-width: 0; flex-wrap: wrap; }
.action-fields label { font-weight: 600; font-size: 13px; color: var(--muted); white-space: nowrap; }
.action-fields select { min-width: 190px; max-width: 300px; padding: 8px 11px; border: 1px solid transparent; border-radius: var(--radius-sm); font-size: 13px; background: var(--sunken-bg); color: var(--text); box-shadow: var(--sunken-1); }
.action-fields select:focus { outline: none; border-color: transparent; box-shadow: var(--sunken-focus); }
/* 提示紧跟「定额模板」下拉：不撑开（flex: 0），最多 260px，过长由 JS 的 title 兜底 */
.action-fields .meta { flex: 0 1 auto; min-width: 0; max-width: 260px; text-align: left; font-size: 12px; line-height: 1.45; color: var(--muted); margin-right: 4px; }

/* ========== 报价单列表 ========== */
.qlist { display: flex; flex-direction: column; gap: 12px; margin-bottom: 14px; }
.qitem { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 12px 14px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; box-shadow: 2px 2px 4px #b8bcc2, -2px -2px 4px #ffffff; transition: box-shadow .3s ease-in-out, background .3s ease-in-out; }
/* hover 阴影继续缩小到贴平（手指靠近遮光），不放大、不位移 */
.qitem:hover { background: var(--card-hover); box-shadow: none; }
body.dark .qitem { box-shadow: 2px 2px 4px #212429, -2px -2px 4px #3a3f47; }
body.dark .qitem:hover { box-shadow: none; }
.qitem .qname { flex: 1 1 200px; min-width: 150px; display: flex; }   /* 文件名普遍较长：占满剩余空间，避免被截成「C06-智能化…版-材」 */
.qitem .qname input { font-weight: 600; font-size: 14px; border: 1px solid transparent; border-radius: var(--radius-sm); padding: 5px 8px; width: 100%; max-width: 360px; background: transparent; color: var(--text); text-overflow: ellipsis; box-shadow: none !important; }
.qitem .qname input:hover, .qitem .qname input:focus { border-color: transparent; outline: none; background: var(--sunken-bg); box-shadow: var(--sunken-focus) !important; }
.qitem .drop-inline { border: 1px solid transparent; border-radius: 10px; padding: 6px 14px; cursor: pointer; color: var(--brand); font-size: 12px; font-weight: 600; box-shadow: var(--raised-1); transition: box-shadow .3s ease-in-out; }
.qitem .drop-inline:hover { background: transparent; box-shadow: 2px 2px 4px #b8bcc2, -2px -2px 4px #ffffff; }
.qitem .drop-inline:active { box-shadow: var(--press-1); }
.qitem .qmeta { margin-left: auto; font-size: 12px; color: var(--muted); }
/* 缺失匹配字段徽标（2026-10-24）：只在缺「参与匹配判等」的字段时出现。
   刻意不抢眼（与错误同色的浅底小胶囊）—— 它是提示，不是错误；点/悬停看缺了哪几项。
   2026-11-04（BUG-007）：可点击打开解析报告，光标改 pointer。 */
.qitem .qmiss {
  display: inline-block; margin-left: 8px; padding: 2px 8px;
  font-size: 11px; font-weight: 600; line-height: 1.5; border-radius: 10px; white-space: nowrap;
  background: rgba(219,0,0, .12); color: var(--up); border: 1px solid rgba(219,0,0, .22); cursor: pointer;
}
body.dark .qitem .qmiss { background: rgba(255,122,122, .16); color: var(--up); border-color: rgba(255,122,122, .30); }
.qitem .del { border: none; background: none; color: var(--muted); cursor: pointer; font-size: 18px; line-height: 1; padding: 4px 8px; border-radius: var(--radius-sm); }
.qitem .del:hover { color: var(--up); background: var(--fill-hover); }
.qitem .qreport { font-size: 12px; color: var(--brand); cursor: pointer; border-bottom: 1px dashed currentColor; padding-bottom: 1px; }
.qitem .qreport:hover { color: var(--brand-dark); }

/* ===== 报价单种类（2026-10-29）=====
 * 上传区上方的一行：分段控件（复用 .seg 的凹槽 + 凸起材质）+ 右侧一句口径说明。
 * 窄屏时说明换行到下一行（flex-wrap），不挤压分段控件。 */
.qkind-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 12px; }
.qkind-label { font-size: 13px; color: var(--muted); flex: none; }
.qkind-tip { font-size: 12px; color: var(--muted); }
/* 卡片上的「价格画像」徽标（人工 / 材料 / 人工+材料+单价…）：描述这份文件实际有哪些价格列，
 * 与上方口径无关 —— 口径切到某档而该单没有那一档时，用户一眼能看出为什么会是空列。
 * ⚠️ 用 ::before + attr() 渲染，**不进 DOM 文本** —— 卡片行内顺序与 .qmeta 文本口径都不能变
 *    （10-27 用户定的顺序 + _verify-qroworder 的断言都依赖它）。 */
.qitem .qmeta[data-price]::before {
  content: attr(data-price-label);
  display: inline-block; margin-right: 7px; padding: 0 7px; border-radius: 5px;
  font-size: 12px; line-height: 17px; vertical-align: 1px;
  color: var(--brand); background: rgba(36, 139, 200, .10); border: 1px solid rgba(36, 139, 200, .22);
}
body.dark .qitem .qmeta[data-price]::before { color: #75bce6; background: rgba(36, 139, 200, .18); border-color: rgba(36, 139, 200, .38); }

/* 上传校验提示（C42）：被拒绝的文件逐条列原因，不静默跳过 */
.import-notice { position: relative; margin-top: 12px; padding: 11px 40px 11px 14px; background: rgba(219,0,0,0.08); border: 1px solid rgba(219,0,0,0.26); border-radius: var(--radius-sm); font-size: 12px; line-height: 1.7; color: var(--text); }
.import-notice-head { font-weight: 600; color: var(--up); margin-bottom: 2px; }
.import-notice ul { margin: 0; padding-left: 18px; }
.import-notice li { word-break: break-all; }
.import-notice-close { position: absolute; top: 6px; right: 8px; }

/* 解析报告（C42） */
#parseReportBody { max-height: 62vh; overflow: auto; }
.pr-summary { font-size: 13px; color: var(--text); background: var(--fill-hover); border-radius: var(--radius-sm); padding: 9px 12px; margin-bottom: 12px; line-height: 1.6; }
.pr-summary b { color: var(--brand); }
.pr-wrap { border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: auto; }
.pr-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.pr-table th, .pr-table td { padding: 8px 10px; border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; }
.pr-table thead th { background: var(--fill-hover); font-weight: 600; color: var(--muted); position: sticky; top: 0; z-index: 1; white-space: nowrap; }
.pr-table td.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.pr-table tr.skip td { color: var(--muted); }
.pr-name { max-width: 190px; word-break: break-all; font-weight: 500; }
.pr-unmapped { max-width: 230px; color: var(--muted); word-break: break-all; }
.pr-reason { max-width: 210px; color: var(--muted); word-break: break-all; }
.pr-tip { margin-top: 10px; font-size: 12px; line-height: 1.6; color: var(--muted); }


/* ========== 拖拽上传区 ========== */
.drop-multi { border: 1px dashed var(--border-strong); border-radius: var(--radius); padding: 24px; text-align: center; cursor: pointer; transition: box-shadow .3s ease-in-out, border-color .3s ease-in-out; color: var(--muted); background: var(--sunken-bg); }
.drop-multi:hover, .drop-multi.over { background: var(--sunken-bg); border-color: var(--brand); }
.drop-multi .ic { font-size: 26px; }
.drop-multi b { color: var(--text); }

/* ========== 合计栏 ========== */
.total-bar { display: flex; gap: 16px; flex-wrap: wrap; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 18px; margin-top: 14px; box-shadow: var(--shadow-1); }
.total-item { font-size: 13px; color: var(--muted); }
.total-item b { font-size: 16px; font-variant-numeric: tabular-nums; color: var(--text); margin-left: 4px; }

/* ========== 导出菜单 ========== */
.export-dropdown { position: relative; }
.sort-select { padding: 9px 12px; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); font-size: 13px; background: var(--card); color: var(--text); cursor: pointer; outline: none; }
.sort-select:focus { outline: 2px solid var(--brand); outline-offset: -1px; }
.export-menu { position: absolute; top: calc(100% + 4px); right: 0; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-2); z-index: 60; min-width: 180px; padding: 5px; }
.export-menu button { display: block; width: 100%; text-align: left; border: none; background: none; padding: 9px 14px; font-size: 13px; cursor: pointer; border-radius: var(--radius-sm); color: var(--text); }
.export-menu button:hover { background: var(--fill-hover); }
.custom-tip { position: fixed; background: #1f2937; color: #fff; padding: 10px 14px; border-radius: var(--radius); font-size: 15px; line-height: 1.6; max-width: 520px; z-index: 300; pointer-events: none; word-break: break-all; white-space: pre-line; box-shadow: var(--shadow-2); }

/* ========== 子工作表切换 ========== */
.sheet-bar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 14px; padding: 10px 14px; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-1); }
/* 行内态（2026-10-17 用户定稿）：子工作表按钮组并入矩阵标题行，替换原「对比矩阵（价格可直接修改后导出）」标题。
   去掉独立卡片的背景/边框/圆角/阴影/外边距（外观由 .result-head 承担），仅保留 flex 排列。
   ⚠️ 只有 1 个子表时 renderSheetBar 会加 .hidden（display:none !important）→ 右侧操作组靠 margin-left:auto 保持右对齐 */
.sheet-bar-inline { margin-top: 0; padding: 0; background: none; border: none; border-radius: 0; box-shadow: none; flex: 0 1 auto; min-width: 0; }
.sheet-label { font-size: 13px; color: var(--muted); }
.sheet-tab { border: 1px solid var(--border-strong); background: var(--card); padding: 6px 16px; font-size: 13px; border-radius: var(--radius-sm); cursor: pointer; color: var(--text); font-weight: 500; }
.sheet-tab:hover { background: var(--fill-hover); }
.sheet-tab.active { background: var(--brand); color: var(--on-brand); border-color: var(--brand); font-weight: 600; }
/* 切换中：给出明确的视觉反馈（未命中缓存时要等云端匹配数秒，无反馈会让用户以为"点了没反应"） */
.sheet-tab.switching { opacity: 0.7; cursor: progress; pointer-events: none; }
.sheet-tab.switching::after { content: ''; display: inline-block; width: 9px; height: 9px; margin-left: 6px; vertical-align: -1px; border: 2px solid currentColor; border-top-color: transparent; border-radius: 50%; animation: sheetTabSpin 0.7s linear infinite; }
@keyframes sheetTabSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .sheet-tab.switching::after { animation: none; } }
/* 子表按钮的预匹配进度条（2026-10-19 用户要求：「在子表按钮上显示出进度条」）
 * 按钮底部 3px 细条，宽度 = 该子表云端批次进度；absolute 定位 → **不改变按钮尺寸/布局** */
.sheet-tab { position: relative; overflow: hidden; }
.sheet-tab-prog { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; display: none; background: var(--line); }
.sheet-tab-prog > i { display: block; height: 100%; width: 0; background: var(--brand); transition: width .25s ease; }
.sheet-tab.matching { border-color: var(--brand); color: var(--brand); }
.sheet-tab.matching .sheet-tab-prog { display: block; }
.sheet-tab.matched .sheet-tab-prog { display: block; background: transparent; }
.sheet-tab.matched .sheet-tab-prog > i { background: #227771; opacity: .55; }
.sheet-tab.match-failed .sheet-tab-prog { display: block; background: transparent; }
.sheet-tab.match-failed .sheet-tab-prog > i { background: #db0000; opacity: .6; }
.sheet-tab.switching .sheet-tab-prog { display: block; }
/* 当前选中的子表不显示进度条（深蓝底上细条会被误读成选中态装饰；它本来也已完成匹配） */
.sheet-tab.active .sheet-tab-prog { display: none; }
/* 子表预取进度提示（首次比对后后台预匹配其余子表） */
.prefetch-status { margin-left: 10px; font-size: 12px; color: var(--muted); align-self: center; white-space: nowrap; }
.prefetch-status::before { content: ''; display: inline-block; width: 8px; height: 8px; margin-right: 6px; vertical-align: 1px; border: 2px solid currentColor; border-top-color: transparent; border-radius: 50%; animation: sheetTabSpin 0.7s linear infinite; }
@media (prefers-reduced-motion: reduce) { .prefetch-status::before { animation: none; } }

/* 结果区在切换中整体变暗，明确"正在更新" */
.matrix-switching #matrixContainer { opacity: 0.5; transition: opacity 0.15s; }

/* ========== 进度条 ========== */
.progress-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.45); display: flex; align-items: center; justify-content: center; z-index: 400; }
.progress-box { background: var(--card); border-radius: var(--radius); padding: 28px 32px; width: 360px; max-width: 90vw; text-align: center; box-shadow: var(--shadow-2); }
.progress-box .p-text { font-size: 14px; color: var(--text); margin-bottom: 16px; }
.progress-track { height: 8px; background: var(--line); border-radius: 999px; overflow: hidden; }
.progress-fill { height: 100%; width: 0; background: var(--brand); border-radius: 999px; transition: width .3s ease; }
.progress-sub { font-size: 12px; color: var(--muted); margin-top: 10px; }

/* ========== 响应式 ========== */
@media (max-width: 860px) {
  .step { min-width: 140px; }
  .action-fields { flex: 1 1 100%; }
  .action-fields select { min-width: 160px; }
  /* 860 仍放得下：提示跟着「定额模板」走，不独占整行（实测独占会把行高从 117 抬到 160） */
  .action-fields .meta { flex: 0 1 auto; max-width: 220px; text-align: left; margin-right: 0; }
}
@media (max-width: 560px) {
  .step { min-width: 100%; }
  .action-fields select { flex: 1 1 100%; max-width: none; }
  .action-btns { width: 100%; }
  /* 2026-11-04：两个按钮平分一行时，「我的数据库」会被挤成两行（实测"我的数据/库"）——
     缩字号与内边距、并禁止换行；开始比对的 148 最小宽度在窄屏取消，否则总宽超出。 */
  .action-btns .btn { flex: 1 1 0; white-space: nowrap; padding: 10px 10px; font-size: 13px; }
  .action-btns #compareBtn { min-width: 0; }
}

/* ========== 对比矩阵容器（Univer） ==========
 * 2026-10-17 用户定稿：**非全屏显示高度 = 屏幕（视口）高度的 75%**（`75vh`，随窗口 resize 自动重算；
 *   窗口尺寸变化由 univerFitContainer 的 ResizeObserver 跟随 → Univer 根节点高度与画布视口同步）。
 * 全屏（#resultWrap.fake-fullscreen）：由 flex 填满视口剩余空间（height:auto + flex:1 接管）。
 * ⚠️ height 必须是具体值：Univer 根节点高度由 univerFitContainer 按容器 clientHeight 设置，
 *    容器无显式高度时此前只能靠 min-height 兜底（恒 520px，不随窗口变化）。
 * 兜底：视口极矮（< 533px）时以 min-height 400px 保证表格可用。 */
/* 表格画布：白 → 浅灰（2026-10-25 用户要求与整体风格统一）。
   Univer 单元格由 canvas 绘制、吃它自己的 JS 主题，这里只能改容器与 --univer-gray-0
   （表头 / 工具栏 / 空白区跟随）；画布主色已由 canvas 透明让出，实测可透出本底色。 */
.matrix-container {
  flex: 1; height: 75vh; min-height: 400px;
  background: #e9edf4; border-radius: var(--radius-sm);
  position: relative; overflow: hidden; box-shadow: var(--sunken-1);
  --univer-gray-0: #e9edf4;
}
/* 深色：Univer 画布是引擎的浅色主题（只认自己的 JS 主题，CSS 改不动），
   这里把它压暗一档，避免深色页面里整片刺眼白光；单元格文字仍是深色，对比不变。 */
body.dark .matrix-container {
  background: #dfe4ea;
  --univer-gray-0: #dfe4ea;
}
#resultWrap.fake-fullscreen .matrix-container { height: auto; }

/* 大模型语义匹配不可用时的提示横幅 */
.ai-hint { margin: 0 16px 12px; padding: 10px 14px; border: 1px solid rgba(255,230,109,0.55); background: rgba(255,230,109,0.16); color: var(--warn); border-radius: var(--radius); font-size: 13px; line-height: 1.6; }
body.dark .ai-hint { background: rgba(255,230,109,0.16); border-color: rgba(255,230,109,0.45); color: var(--warn); }

/* 对比矩阵右键菜单（确认匹配/不匹配） */
.matrix-ctx-menu { position: fixed; z-index: 900; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-2); padding: 5px; min-width: 140px; }
.matrix-ctx-item { padding: 8px 14px; font-size: 13px; border-radius: var(--radius-sm); cursor: pointer; color: var(--text); }
.matrix-ctx-item:hover { background: var(--fill-hover); }
.matrix-ctx-item.ok:hover { background: rgba(78,205,196,0.12); }
.matrix-ctx-item.no:hover { background: rgba(219,0,0,0.12); }

/* ---- 云端异常横幅（系统异常状态的统一反馈出口，不自动消失） ---- */
.cloud-alert {
  margin: 6px 0 0;
  padding: 12px 16px;
  border-radius: var(--radius);
  background: rgba(219,0,0, 0.08);
  border: 1px solid var(--up);
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
}
body.dark .cloud-alert { background: rgba(255,122,122, 0.12); }
.cloud-alert-title { display: flex; align-items: center; gap: 8px; color: var(--up); font-weight: 600; font-size: 14px; }
.cloud-alert-detail { margin-top: 4px; color: var(--text-dim); font-size: 12px; }
.cloud-alert .btn { flex: none; }

/* ---- 单元格内容溢出提示（列宽不足时，悬停显示完整内容） ---- */
.cell-overflow-tip {
  position: fixed;
  z-index: 950;
  max-width: 560px;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  background: var(--card);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-2);
  color: var(--text);
  font-size: 13px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-all;
  pointer-events: none;   /* 不遮挡鼠标，避免浮层自身触发交互 */
}
.cell-overflow-tip.hidden { display: none; }

/* ============================================================
 * Univer 暗色模式对比度修复（用户 2026-10-16 要求：WCAG AA）
 * ------------------------------------------------------------
 * 背景：Univer 深色皮肤的「禁用态」前景 = gray-600 (#31363F)、
 *   部分图标 = gray-700 (#272A2F)，它们落在深色面板（#2B2B2B / #1F2124）上
 *   对比度仅约 1.2:1（不可辨识），违背可访问性要求（实测审计，2026-10-16）。
 * 修复：仅 body.dark 下，把「过暗前景」提升为可读中灰 #8A93A1——
 *   · 对 #2B2B2B ≈ 4.5:1，对 #1F2124 ≈ 5.2:1（均达 AA 级）；
 *   · 禁用态仍明显弱于可用态（白色 #FFF ≈ 13:1），交互层级保留。
 * ⚠️ 选择器写法：用「属性包含」匹配 Univer 的 Tailwind 风格类名
 *   （类名含 `dark:disabled:!` 等特殊字符，直接写类选择器需转义、易错）；
 *   配合 !important + 更高特异性覆盖 Univer 自身的 !important 规则。
 * ⚠️ 修改此段后必须重跑对比度审计脚本（.workbuddy/_verify-phase2-*.js 内嵌）确认全部 ≥3:1。
 * ============================================================ */
/* ⚠️ 状态作用域（2026-10-16 实测踩坑）：`[class*=...]` 匹配的是「类名子串」，
   而 `dark:disabled:!univer-text-gray-600` 这个类总是挂在按钮的 class 列表里
   （只在 :disabled 时才生效）——因此覆盖规则**必须自己带 `:disabled` 限定**，
   否则会把「可用态」按钮也涂成灰色（暗色下可用态应为白色 #FFF）。 */
body.dark [class*="dark:disabled:!univer-text-gray-600"]:disabled,
body.dark [class*="dark:disabled:!univer-text-gray-600"][disabled],
body.dark [class*="dark:disabled:!univer-text-gray-600"][aria-disabled="true"] { color: #8a93a1 !important; }
/* 常驻「不可交互」元素（如禁用选择器的下拉箭头：pointer-events-none，不带 :disabled）——
   Univer 自身就用 `dark:!univer-text-gray-600` 表达其常驻禁用态 → 直接提亮 */
body.dark [class*="dark:!univer-text-gray-600"]:not([class*="dark:disabled:!"]) { color: #8a93a1 !important; }
body.dark [class*="dark:!univer-text-gray-700"] { color: #8a93a1 !important; }
/* 禁用按钮带「深灰底」的组合（如处于按下态又被禁用的切换钮）：把底压暗，
   使提亮后的前景达标（#8A93A1 on #4f5763 ≈ 2.4:1 → 压暗后 ≈ 4.5:1）；可用态不受影响（白字 7.5:1）。 */
body.dark [class*="dark:!univer-bg-gray-500"]:disabled { background-color: #272a2f !important; }
body.dark :is(button, [role="button"], input, select, textarea):disabled { --univer-gray-600: #8a93a1; }
/* 兼容：部分控件用「父级禁用 + 子级继承」表达禁用态（如字体/格式选择器内的文字） */
body.dark :is([aria-disabled="true"], .univer-toolbar-selector-root[disabled]) { --univer-gray-600: #8a93a1; }

/* ============================================================
 * Univer 工具栏紧凑化（用户 2026-10-16 要求；三处版本演化后的最终形态）
 * ------------------------------------------------------------
 * 结构（实测）：matrixContainer 顶部两大块——
 *   ① 工具栏 header（白底、上下 1px 分割线）：内含两层——
 *      标签行（开始/公式/视图）容器 .univer-h-9；工具行（图标）容器 .univer-h-10；
 *   ② 公式栏容器 header（空类名；内为 A1 名字框/×/√/fx/输入行，28px）。
 * 约定 A（工具栏内部两层）：标签行 36 → 32；工具行 40 → 32（按钮净距 ≈5.5px）；
 *   工具栏 header 内边距 10 / 22 / 0（上/左右/下）。
 * 约定 B（**合并为统一工具栏区域**，用户 2026-10-16 定稿；2026-10-17 升级为「三行完全融合」）：
 *   工具栏 header 下边距 0 + 下外边距 0，并隐藏其下边框；
 *   **三行无内部分界线**：工具行底边框（原 rgb(227,229,234) 实线）与公式栏容器顶边框
 *   （原 rgba(0,0,0,0.08)）均置透明 → 标签行 / 工具行 / 公式行视觉上连成一整块；
 *   公式栏容器上边距 8（贴紧工具行）、下边距 12（原 20）、下外边距 12（原 20）。
 *   → 图标行 → 公式行净距 ≈ 9px；整块（标签/工具/公式三行）≈ 76+8+28+12。
 *   公式行到表格区间距 40 → 24。
 * 保持：按钮点击区域（标签 28px / 图标 24px）不变；justify-center、分组竖线、
 *   各工具项命令绑定全部原样；两框左右内边距同为 22px（对齐不变）。
 * 选择器：均为「结构定位」，不依赖状态类（:has 定位工具栏 header；空类名 header
 *   经实测全容器唯一 = 公式栏容器）。
 * 验证：.workbuddy/_verify-toolbar.js（26 项：布局断言 + 三行无分界线 + 工具栏点击 +
 *   公式栏/名字框真实操作）；改动后必须看截图。
 * ⚠️ 本段是以上间距/合并约定的唯一事实源，禁止在别处再改这些高度/边距（防两处打架）。
 * ============================================================ */
.matrix-container header [class~="univer-select-none"][class~="univer-h-9"] { height: 32px !important; }
.matrix-container header [class~="univer-h-10"][class~="univer-grid-flow-col"] {
  height: 32px !important;
  /* 2026-10-17 用户定稿「三行合并」：去掉工具行底边框（原 rgb(227,229,234) 实线，是二、三行之间的分界线） */
  border-bottom-color: transparent !important;
}
/* 约定 A + B（工具栏 header：与公式栏相接、隐藏块边缘线） */
.matrix-container header:has(> [class~="univer-select-none"][class~="univer-h-9"]) {
  padding-top: 10px !important;
  padding-bottom: 0 !important;            /* 6 → 0（与公式栏直接相接） */
  margin-bottom: 0 !important;             /* 6 → 0（两框合并为同一区块） */
  border-bottom-color: transparent !important;   /* 隐藏块边缘线（2026-10-17 起三行完全融合，无内部分界线） */
}
/* 约定 B（公式栏容器：并入统一区块后的内边距） */
.matrix-container section[class*="grid-rows"] > header:not([class]) {
  padding-top: 8px !important;             /* 18 → 8（贴紧分割线） */
  padding-bottom: 12px !important;         /* 20 → 12（并入区块后收紧底部） */
  margin-bottom: 12px !important;          /* 20 → 12（到表格区的间距） */
  /* 2026-10-17 用户定稿「三行合并」：去掉公式栏容器顶边框（原 rgba(0,0,0,0.08)，与工具行底边框叠加成 2px 分界线） */
  border-top-color: transparent !important;
}

/* ==========================================================
 * OCR 强制校对面板（C43）：同意 → 识别中 → 校对 三态同一弹窗
 * 置信度着色：红=低于 OCR_CONF.low、黄=低于 warn、灰=未知、绿=人工改过
 * ========================================================== */
.pf-consent, .pf-error, .pf-loading { font-size: 13px; line-height: 1.7; }
.pf-file { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; word-break: break-all; }
.pf-badge { font-size: 11px; font-weight: 700; color: var(--on-brand); background: var(--brand); border-radius: 4px; padding: 2px 6px; letter-spacing: .5px; }
.pf-dim { color: var(--muted); font-size: 12px; }
.pf-notes { margin: 0 0 12px; padding-left: 18px; color: var(--text); }
.pf-notes li { margin: 4px 0; }
.pf-hint { font-size: 12px; color: var(--muted); background: var(--fill-hover); border-radius: var(--radius-sm); padding: 8px 10px; }
.pf-loading { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 34px 0; }
.pf-spin { width: 30px; height: 30px; border-radius: 50%; border: 3px solid var(--line); border-top-color: var(--brand); animation: pfspin .8s linear infinite; }
@keyframes pfspin { to { transform: rotate(360deg); } }
.pf-load-text { font-weight: 600; font-size: 14px; }
.pf-error-title { font-weight: 700; color: var(--up); margin-bottom: 6px; }
.pf-error-msg { background: rgba(219,0,0,0.10); border: 1px solid rgba(219,0,0,0.26); border-radius: var(--radius-sm); padding: 9px 12px; margin-bottom: 10px; word-break: break-all; }
.pf-foot { display: flex; justify-content: flex-end; gap: 10px; margin-top: 14px; }
.pf-sum { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; font-size: 12px; color: var(--muted); background: var(--fill-hover); border-radius: var(--radius-sm); padding: 9px 12px; margin-bottom: 10px; }
.pf-sum b { color: var(--text); font-variant-numeric: tabular-nums; }
.pf-sum .pf-bad b { color: var(--up); }
.pf-kv.pf-bad b { color: var(--up); }
.pf-note { font-size: 12px; color: var(--text); background: var(--sunken-bg); box-shadow: var(--sunken-1); border-radius: var(--radius-sm); padding: 8px 10px; margin-bottom: 10px; word-break: break-all; }
.pf-tip { font-size: 12px; color: var(--muted); line-height: 1.7; margin-bottom: 10px; }
.pf-table-wrap { max-height: 52vh; overflow: auto; border: 1px solid var(--line); border-radius: var(--radius-sm); }
.pf-table { border-collapse: separate; border-spacing: 0; width: 100%; font-size: 12px; }
.pf-table thead th { position: sticky; top: 0; z-index: 2; background: var(--fill-hover); color: var(--muted); font-weight: 600; text-align: left; padding: 7px 8px; border-bottom: 1px solid var(--line); white-space: nowrap; }
.pf-cell { padding: 0; border-bottom: 1px solid var(--line); border-right: 1px solid var(--line); }
.pf-cell input { width: 100%; box-sizing: border-box; border: 0; background: transparent; color: var(--text); font: inherit; padding: 6px 8px; outline: none; }
.pf-cell input:focus { box-shadow: inset 0 0 0 2px var(--brand); border-radius: 3px; }
.pf-cell.low { background: rgba(219,0,0, .14); }
.pf-cell.warn { background: rgba(235, 194, 0, .16); }
.pf-cell.unknown { background: rgba(110, 110, 110, .10); }
.pf-cell.edited { background: rgba(78,205,196, .10); }
body.dark .pf-cell.low { background: rgba(255,122,122, .18); }
body.dark .pf-cell.warn { background: rgba(255, 229, 102, .16); }
body.dark .pf-cell.unknown { background: rgba(255, 255, 255, .06); }
body.dark .pf-cell.edited { background: rgba(121,217,210, .14); }

/* 解析报告：自由文本补全统计（C44） */
.pr-derived { font-size: 12px; line-height: 1.65; color: var(--text); background: var(--sunken-bg); box-shadow: var(--sunken-1); border-radius: var(--radius-sm); padding: 9px 12px; margin-bottom: 10px; }
.pr-derived b { color: var(--brand); font-variant-numeric: tabular-nums; }
body.dark .pr-derived { background: var(--sunken-bg); }

/* 解析报告：C67 三项对账（合并回填 / 行数 / 金额 / 跳过明细）
   与 .pr-derived 同款凹底；is-warn 只在「对不上」时用警告色，正常时保持中性，
   不要用成功色（青）做「一致」—— 一致性是默认状态，不需要额外颜色抢注意力。 */
.pr-audit { font-size: 12px; line-height: 1.7; color: var(--text); background: var(--sunken-bg); box-shadow: var(--sunken-1); border-radius: var(--radius-sm); padding: 9px 12px; margin-bottom: 10px; }
.pr-audit b { color: var(--brand); font-variant-numeric: tabular-nums; }
.pr-audit.is-warn { border-left: 3px solid var(--warn); }
.pr-audit.is-warn b { color: var(--warn); }

/* ==========================================================
 * 运行日志与反馈弹窗（C45）
 * ========================================================== */
.fb-link { color: var(--brand); text-decoration: none; border-bottom: 1px dashed currentColor; }
.fb-link:hover { color: var(--brand-dark); }
.fb-stats { font-size: 12px; color: var(--muted); background: var(--fill-hover); border-radius: var(--radius-sm); padding: 9px 12px; margin-bottom: 14px; line-height: 1.6; }
.fb-stats b { color: var(--text); font-variant-numeric: tabular-nums; }
.fb-label { display: block; font-size: 12px; font-weight: 600; color: var(--text); margin: 12px 0 6px; }
.fb-req { color: var(--up); font-weight: 400; font-size: 11px; margin-left: 4px; }
.fb-opt { color: var(--muted); font-weight: 400; font-size: 11px; margin-left: 4px; }
.fb-textarea, .fb-input { width: 100%; box-sizing: border-box; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: var(--card); color: var(--text); font: inherit; font-size: 13px; padding: 9px 11px; outline: none; }
.fb-textarea { min-height: 92px; resize: vertical; line-height: 1.65; }
.fb-textarea:focus, .fb-input:focus { border-color: var(--brand); }
.fb-opts { display: flex; flex-wrap: wrap; gap: 16px; margin: 12px 0 4px; }
.fb-check { font-size: 12px; color: var(--text); display: flex; align-items: center; gap: 6px; cursor: pointer; }
.fb-privacy { font-size: 12px; line-height: 1.75; color: var(--muted); background: var(--sunken-bg); box-shadow: var(--sunken-1); border-radius: var(--radius-sm); padding: 9px 12px; margin-top: 12px; }
.fb-privacy b { color: var(--text); }
.fb-result { font-size: 12px; line-height: 1.7; border-radius: var(--radius-sm); padding: 10px 12px; margin-top: 14px; word-break: break-all; }
/* 状态条：整圈极淡描边 + 状态底（不用左侧 3px 强调条） */
.fb-ok { background: rgba(78,205,196,0.10); border: 1px solid rgba(78,205,196,0.28); color: var(--text); }
.fb-bad { background: rgba(219,0,0,0.10); border: 1px solid rgba(219,0,0,0.28); color: var(--text); }
.fb-info { background: rgba(36,139,200,0.08); border: 1px solid rgba(36,139,200,0.24); color: var(--text); }
.fb-tip { margin-top: 8px; color: var(--muted); }
.fb-dim { color: var(--muted); }
.fb-raw { width: 100%; box-sizing: border-box; min-height: 160px; margin-top: 10px; font-size: 11px; font-family: ui-monospace, Consolas, monospace; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--card); color: var(--text); padding: 8px; }
.fb-foot { display: flex; align-items: center; gap: 10px; margin-top: 16px; }
.fb-spacer { flex: 1 1 auto; }
body.dark .fb-ok { background: rgba(121,217,210,0.14); }
body.dark .fb-bad { background: rgba(255,122,122,0.14); }

/* 进度层「取消匹配」（C46）：只在中止可达时才出现，不干扰常规等待 */
.progress-cancel { margin-top: 14px; font-size: 12px; padding: 6px 18px; }
.progress-cancel.hidden { display: none; }
.progress-box .progress-cancel:disabled { opacity: .6; cursor: default; transform: none; }

/* ========== 个人定额弹窗（2026-10-19） ==========
 * 与官方定额下拉同权；弹窗三态：从报价单合成 / 手工新建 / 编辑已有
 * ⚠️ 进度条等表格内元素不要写内联 display（会盖掉状态类），见 matrix.js 的同名约定 */
.pq-box { width: 980px; max-width: 96vw; height: 82vh; max-height: 88vh; display: flex; flex-direction: column; padding: 0; overflow: hidden; }
.pq-box .modal-head { padding: 18px 20px 0; margin-bottom: 12px; }
.pq-step-info { margin-left: auto; margin-right: 12px; font-size: 12px; color: var(--muted); }
.pq-tabs { display: flex; gap: 6px; padding: 0 20px 10px; border-bottom: 1px solid var(--line); }
.pq-tab { border: 1px solid var(--border-strong); background: var(--card); color: var(--text); border-radius: 8px; padding: 6px 14px; font-size: 13px; cursor: pointer; }
.pq-tab:hover { background: var(--fill-hover); }
.pq-tab.active { background: var(--brand); border-color: var(--brand); color: var(--on-brand); font-weight: 600; }
.pq-tab:disabled { opacity: .5; cursor: default; }
.pq-body { flex: 1; overflow: auto; padding: 14px 20px; }
.pq-title { font-size: 13px; font-weight: 600; margin: 4px 0 10px; }
.pq-stat { font-weight: 400; font-size: 12px; color: var(--muted); margin-left: 6px; }

.pq-sources { display: flex; flex-direction: column; gap: 10px; }
.pq-quote { border: 1px solid var(--line); border-radius: 8px; padding: 8px 12px; }
.pq-quote-head { display: flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer; }
.pq-quote-head span { color: var(--muted); font-size: 12px; }
.pq-sheets { display: flex; flex-wrap: wrap; gap: 6px 14px; margin: 8px 0 2px 22px; }
.pq-sheet { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text); cursor: pointer; }
.pq-summary { margin-top: 10px; font-size: 12px; color: var(--muted); }
.pq-empty { color: var(--muted); font-size: 13px; padding: 18px 0; text-align: center; }

.pq-conflict-ops { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
.pq-conflicts { display: flex; flex-direction: column; gap: 10px; }
.pq-conflict { border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; }
.pq-conflict-head { display: flex; align-items: baseline; gap: 8px; font-size: 13px; margin-bottom: 8px; flex-wrap: wrap; }
.pq-conflict-head span { color: var(--muted); font-size: 12px; }
.pq-cand { display: flex; align-items: center; gap: 10px; padding: 6px 8px; border-radius: 6px; font-size: 12px; cursor: pointer; }
.pq-cand.picked { background: var(--fill-hover); }
.pq-cand-src { min-width: 220px; }
.pq-cand-price { font-weight: 600; min-width: 70px; text-align: right; }
.pq-cand-raw, .pq-cand-info { color: var(--muted); }

.pq-editor { border: 1px solid var(--line); border-radius: 8px; overflow: auto; max-height: 46vh; }
.pq-table { border-collapse: collapse; width: 100%; font-size: 12px; }
.pq-table th { position: sticky; top: 0; background: var(--card); border-bottom: 1px solid var(--line); padding: 6px 4px; white-space: nowrap; z-index: 1; }
.pq-table td { border-bottom: 1px solid var(--line); padding: 2px 3px; }
.pq-table input { width: 100%; border: 1px solid transparent; background: transparent; color: var(--text); font-size: 12px; padding: 3px 4px; border-radius: 4px; }
.pq-table input:focus { border-color: var(--brand); outline: none; background: var(--card); }
.pq-del { border: none; background: transparent; color: var(--muted); cursor: pointer; font-size: 15px; line-height: 1; }
.pq-del:hover { color: #db0000; }
.pq-more { font-size: 12px; color: var(--muted); padding: 8px; }
.pq-editor-ops { display: flex; align-items: center; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.pq-export { margin-left: auto; font-size: 12px; color: var(--muted); display: inline-flex; align-items: center; gap: 6px; }
.pq-danger { color: #db0000; border-color: rgba(219,0,0,.4); }
/* 2026-11-05 用户定：这一行拆成两半 —— 危险操作（删除定额）单独靠左，
   常规操作（添加一行 / 从 Excel 粘贴）整体靠右。
   不用右上角：那里紧挨关闭 ×，关窗口时容易误点。
   删除按钮沿用 .pq-danger 的红字+红边（底部行空间够，比轻量文字更明确"这是危险项"）。 */
.pq-editor-ops .pq-ops-right { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
#pqPasteArea { width: 100%; height: 90px; margin: 8px 0; border: 1px solid var(--border-strong); border-radius: 6px; padding: 8px; font-size: 12px; background: var(--card); color: var(--text); font-family: inherit; }

.pq-foot { border-top: 1px solid var(--line); padding: 12px 20px; display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.pq-name-wrap { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 260px; }
.pq-name-wrap label { font-size: 13px; font-weight: 600; }
.pq-name-wrap input { flex: 1; min-width: 180px; padding: 8px 10px; border: 1px solid var(--border-strong); border-radius: 6px; background: var(--card); color: var(--text); font-size: 13px; }
.pq-name-wrap input:focus { border-color: var(--brand); outline: none; }
.pq-msg { font-size: 12px; color: var(--muted); }
.pq-msg.err { color: #db0000; }
.pq-actions { display: flex; gap: 8px; }

/* ========== 调试直通徽标（C49，未上线期间；上线关闭 debug-bypass.js 后自动消失） ========== */
.debug-badge { position: fixed; right: 14px; bottom: 14px; z-index: 900; background: rgba(219,0,0,0.10); color: var(--up); border: 1px solid rgba(219,0,0,0.42); border-radius: 8px; padding: 6px 10px; font-size: 12px; box-shadow: 0 2px 8px rgba(0,0,0,.12); cursor: help; user-select: none; }
body.dark .debug-badge { background: rgba(255,122,122,0.16); color: var(--up); border-color: rgba(255,122,122,0.42); }

/* 个人定额：保存方式（新建 / 追加到已有）+ 导出禁用说明 + 已有条目高亮（2026-10-19） */
.pq-save-mode { display: inline-flex; align-items: center; gap: 12px; font-size: 12px; color: var(--muted); flex-wrap: wrap; }
.pq-save-mode label { display: inline-flex; align-items: center; gap: 5px; cursor: pointer; color: var(--text); }
.pq-save-mode input[type="radio"]:disabled + span { opacity: .5; }
.pq-save-mode select { padding: 6px 8px; border: 1px solid var(--border-strong); border-radius: 6px; background: var(--card); color: var(--text); font-size: 12px; max-width: 240px; }
.pq-note { margin-left: auto; font-size: 12px; color: var(--muted); }
.pq-cand.is-existing .pq-cand-src { color: var(--brand); font-weight: 600; }
.pq-export { display: none !important; }

/* ==========================================================
 * 凸凹材质补丁（2026-10-21 用户定稿：按钮/卡片凸，输入框凹）
 * ------------------------------------------------------------
 * 通用规则已在 base.css 末尾兜底；这里只补客户端专有组件。
 * ⚠️ 新增组件请引用 --raised-* / --sunken-*，勿手写 box-shadow。
 * ========================================================== */

/* 拖放区：凹槽 */
.drop-multi { background: var(--sunken-bg); box-shadow: var(--sunken-1); }
.drop-multi:hover, .drop-multi.over { background: var(--sunken-bg); box-shadow: var(--sunken-focus); }

/* 下拉：凹面 */
.action-fields select, .sort-select { background: var(--sunken-bg); box-shadow: var(--sunken-1); }
.action-fields select:focus, .sort-select:focus { box-shadow: var(--sunken-focus); }

/* 子工作表页签 / 个人定额页签：凹槽为底，选中项凸起（按下去 = 当前） */
.sheet-tab { box-shadow: var(--sunken-1); background: var(--sunken-bg); }
.sheet-tab:hover { box-shadow: var(--sunken-focus); }
.sheet-tab:active { box-shadow: var(--press-1); }
.sheet-tab.active { box-shadow: var(--raised-1); background: var(--card); color: var(--brand); }
.pq-tab { box-shadow: var(--sunken-1); background: var(--sunken-bg); }
.pq-tab:hover { box-shadow: var(--sunken-focus); }
.pq-tab.active { box-shadow: var(--raised-1); background: var(--card); color: var(--brand); }

/* 步骤序号：小圆片凸起 */
.step .num { box-shadow: var(--raised-1); }

/* 行内可编辑文件名：默认读起来是「文字」不是「输入框」——悬停/聚焦才下沉 */
.qitem .qname input { box-shadow: none; }
.qitem .qname input:hover { box-shadow: var(--sunken-1); }
.qitem .qname input:focus { box-shadow: var(--sunken-focus); }

/* 个人定额表格：整张表不套凹面，聚焦单格才显形 */
.pq-table input { box-shadow: none; }
.pq-table input:focus { box-shadow: var(--sunken-focus); }
.pq-name-wrap input, .pq-save-mode select { background: var(--sunken-bg); box-shadow: var(--sunken-1); }
.pq-name-wrap input:focus, .pq-save-mode select:focus { box-shadow: var(--sunken-focus); }
.pq-editor { box-shadow: var(--sunken-1); }

/* 进度轨道做成凹槽，填充条浮在上面 */
.progress-track { box-shadow: var(--sunken-1); }

/* ==========================================================
 * P0 改版（2026-10-21）：状态条 / 右对齐主操作 / 结果区工具栏主次
 * ------------------------------------------------------------
 * ① .steps 三张装饰卡 → .status-strip 状态条（数据由 updateStatusStrip 驱动）
 * ② 「开始比对」满宽 1221px → 右下角 148×40 单主操作
 * ③ 结果区一行三个主按钮 → 1 主（导出）+ 3 次（排序/详细比对/云端存档）+ 1 图标（全屏）
 * ========================================================== */

/* ---------- ① 状态条：40px，三段实时状态 ---------- */
.status-strip {
  display: flex; align-items: center; gap: 0;
  background: var(--sunken-bg); border: 1px solid transparent;
  border-radius: var(--radius-sm); box-shadow: var(--sunken-1);
  padding: 0 16px; height: 40px; margin-bottom: 16px;
}
.ss-item { display: flex; align-items: center; gap: 8px; flex: 1 1 0; min-width: 0; }
.ss-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; background: var(--border-strong); box-sizing: border-box; }
.ss-item.is-done .ss-dot { background: var(--down); }
.ss-item.is-active .ss-dot { background: var(--brand); box-shadow: 0 0 0 3px rgba(36,139,200,0.16); }
.ss-item.is-idle .ss-dot { background: transparent; border: 1.5px solid var(--border-strong); }
.ss-label { font-size: 11px; color: var(--muted); flex: none; }
.ss-val { font-size: 12px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ss-item.is-idle .ss-val { color: var(--muted); font-weight: 400; }
.ss-sep { width: 1px; height: 14px; background: var(--line); flex: none; margin: 0 16px; }

/* ---------- ② 主操作：右对齐一组 ---------- */
/* 2026-11-04：左侧「定额模板 / 报价基准」，右侧「我的数据库 / 开始比对」 */
.action-row { display: flex; align-items: center; justify-content: space-between; gap: 12px 18px; margin-top: 16px; flex-wrap: wrap; }
.action-btns { display: flex; align-items: center; gap: 10px; margin-left: auto; flex: none; }
.action-row .btn { padding: 10px 20px; font-size: 14px; }
.action-row #compareBtn { min-width: 148px; justify-content: center; }

/* ---------- ③ 结果区标题行：左信息 / 右两组操作 ---------- */
.result-head { padding: 12px 16px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
/* 左侧操作组（2026-11-01 用户定）：种类 / 排序 / 只看需处理 / 详细比对 靠左；云端存档+导出+全屏仍靠右 */
.head-left { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.head-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; flex-wrap: wrap; }
.head-group { display: flex; align-items: center; gap: 8px; }
.head-sep { width: 1px; height: 16px; background: var(--line); flex: none; margin: 0 2px; }

/* 全屏：平时只显示图标（省 40px 宽、不与导出抢），进入全屏后才显示「退出全屏」文案 */
.fs-icon { padding: 9px 10px; }
.fs-icon #fullscreenBtnText { display: none; }
#resultWrap.fake-fullscreen .fs-icon #fullscreenBtnText { display: inline; }
#resultWrap.fake-fullscreen .fs-icon { padding: 9px 16px; }

/* ==========================================================
 * 合计栏·匹配情况徽标（2026-10-21）
 * ------------------------------------------------------------
 * 放在合计栏最右侧：金额回答「多少钱」，这块回答「比得怎么样」。
 * 颜色与名称格底色同源（红=未匹配 / 蓝=未报价 / 黄=相似），
 * 但这里用「10% 底 + 实色字」的小胶囊，避免整栏出现大色块。
 * ========================================================== */
.total-stat {
  display: flex; align-items: center; gap: 8px;
  margin-left: auto; padding-left: 18px;
  border-left: 1px solid var(--line);
}
.ts-label { font-size: 12px; color: var(--muted); white-space: nowrap; }
.ts-rate { font-size: 17px; font-variant-numeric: tabular-nums; line-height: 1; }
.ts-rate.is-ok   { color: #227771; }
.ts-rate.is-warn { color: #806a00; }
.ts-rate.is-bad  { color: #db0000; }
.ts-sub { font-size: 11px; color: var(--muted); white-space: nowrap; }
.ts-chip { font-size: 11px; padding: 2px 8px; border-radius: 999px; white-space: nowrap; font-weight: 500; }
.ts-chip.ts-ok  { color: #227771; background: rgba(78,205,196,0.10); }
.ts-chip.ts-bad { color: #db0000; background: rgba(219,0,0,0.10); }
.ts-chip.ts-np  { color: #248bc8; background: rgba(36,139,200,0.10); }
.ts-chip.ts-fz  { color: #1e72a4; background: rgba(36,139,200,0.10); }
.ts-chip.ts-und { color: var(--muted); background: rgba(0,0,0,0.06); }
/* 2026-10-27 A+B+C：落选（同一清单项被多行报价指向，未被采用）—— 可点，打开候选面板 */
.ts-chip.ts-lost { color: var(--warn); background: rgba(255,230,109,0.35); cursor: pointer; }
.ts-chip.ts-lost:hover { background: rgba(255,230,109,0.55); }
.ts-chip.ts-lost:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* ========== 候选报价面板（2026-10-27 A+B+C） ==========
 * 列表项是「卡片」→ 凸；选中态用主色描边（不换底色，保持四色语义）。
 * 面板里只有展示与单选，不改判定口径（口径见 match-local.js / C57）。 */
.cand-box { width: 620px; max-width: 94vw; max-height: 86vh; display: flex; flex-direction: column; padding: 20px 22px 16px; }
.cand-body { flex: 1; min-height: 0; overflow: auto; margin: 0 -4px; padding: 0 4px; }
.cand-sub { font-size: 13px; color: var(--text); margin-bottom: 6px; line-height: 1.5; }
.cand-note { font-size: 12px; color: var(--muted); line-height: 1.6; margin-bottom: 12px; }
.cand-list { display: flex; flex-direction: column; gap: 8px; }
.cand-item {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--card); box-shadow: var(--raised-1); cursor: pointer;
}
.cand-item:hover { border-color: var(--border-strong); }
.cand-item.is-on { border-color: var(--brand); box-shadow: inset 0 0 0 1px var(--brand), var(--raised-1); }
.cand-item.is-lost { cursor: default; }
.cand-radio { flex: none; width: 14px; height: 14px; border-radius: 50%; border: 1px solid var(--border-strong); background: var(--bg); }
.cand-item.is-on .cand-radio { border-color: var(--brand); box-shadow: inset 0 0 0 4px var(--brand); }
.cand-main { flex: 1; min-width: 0; }
.cand-line { font-size: 13px; color: var(--text); display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.cand-no { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.cand-meta { font-size: 12px; color: var(--muted); }
.cand-tags { display: flex; gap: 6px; margin-top: 5px; flex-wrap: wrap; }
.cand-tag { font-size: 11px; padding: 1px 7px; border-radius: 999px; }
.cand-tag.is-ok { color: var(--down); background: rgba(78,205,196,0.14); }
.cand-tag.is-fz { color: var(--fuzzy); background: rgba(36,139,200,0.12); }
.cand-tag.is-dim { color: var(--muted); background: rgba(0,0,0,0.05); }
.cand-tag.is-dup { color: var(--warn); background: rgba(255,230,109,0.35); }
.cand-tag.is-warn { color: var(--up); background: rgba(255,107,107,0.14); }
.cand-money { flex: none; text-align: right; }
.cand-money b { display: block; font-size: 14px; color: var(--text); }
.cand-money span { font-size: 11px; color: var(--muted); }
.cand-alts { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); }
.cand-alts-title { font-size: 12px; color: var(--muted); margin-bottom: 8px; }
.cand-alt { display: flex; align-items: center; gap: 8px; padding: 6px 0; font-size: 13px; }
.cand-alt-txt { flex: 1; min-width: 0; color: var(--text); }
.cand-alt-score { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.cand-alt-go { padding: 4px 10px; font-size: 12px; }
.cand-foot { display: flex; align-items: center; gap: 10px; padding-top: 14px; }
.cand-hint { flex: 1; font-size: 12px; color: var(--muted); }
.cand-lost-go { flex: none; padding: 4px 10px; font-size: 12px; }
.matrix-ctx-item.cand { color: var(--brand); }

body.dark .ts-rate.is-ok   { color: #79d9d2; }
body.dark .ts-rate.is-warn { color: #ff7a7a; }
body.dark .ts-rate.is-bad  { color: #ff7a7a; }
body.dark .ts-chip.ts-ok  { color: #79d9d2; background: rgba(121,217,210,0.14); }
body.dark .ts-chip.ts-bad { color: #ff7a7a; background: rgba(255,122,122,0.14); }
body.dark .ts-chip.ts-np  { color: #75bce6; background: rgba(90,174,224,0.14); }
body.dark .ts-chip.ts-fz  { color: #75bce6; background: rgba(117,188,230,0.14); }
body.dark .ts-chip.ts-und { color: #b8b8b8; background: rgba(255,255,255,0.08); }
body.dark .ts-chip.ts-lost { color: #ffe66d; background: rgba(255,230,109,0.16); }
body.dark .ts-chip.ts-lost:hover { background: rgba(255,230,109,0.26); }
body.dark .cand-tag.is-ok { color: #7fd6d0; background: rgba(78,205,196,0.16); }
body.dark .cand-tag.is-fz { color: #75bce6; background: rgba(90,174,224,0.16); }
body.dark .cand-tag.is-dim { color: #b8b8b8; background: rgba(255,255,255,0.08); }
body.dark .cand-tag.is-dup { color: #ffe66d; background: rgba(255,230,109,0.16); }
body.dark .cand-tag.is-warn { color: #ff7a7a; background: rgba(255,107,107,0.16); }
body.dark .cand-radio { background: var(--bg); }

/* ==========================================================
 * 「只看需处理」筛选（2026-10-21）
 * ------------------------------------------------------------
 * 触发器放在结果区左组首位（排序 / 详细比对 / 云端存档之前）：
 * 它是「看哪些行」的开关，属于视图层，不是数据处理。
 * 形态遵循凸凹材质：默认凸面 ghost，开启后按下去（--press-1）+ 品牌色。
 * ========================================================== */
.oi-btn { gap: 6px; }
.oi-btn .oi-count {
  min-width: 19px; height: 18px; padding: 0 5px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 999px;
  background: rgba(219,0,0,0.12); color: #db0000;
  font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums;
  box-shadow: var(--raised-1);
}
.oi-btn.is-on {
  background: var(--brand); border-color: var(--brand); color: var(--on-brand);
  box-shadow: var(--press-1);
}
/* 开启态：按钮变成品牌实心，计数改成「白底深蓝字」——
   原来是半透明白底 + 白字，11px 下压不住品牌蓝（实测对比度只有 ~3.4:1）。 */
.oi-btn.is-on .oi-count {
  background: #f0f0f3; color: #248bc8; box-shadow: none;
}
body.dark .oi-btn .oi-count { background: rgba(255,122,122,0.16); color: #ff7a7a; }
/* 深色开启态仍需单独声明：idle 的深色规则 `body.dark .oi-btn .oi-count` 特异性(0,3,1)
   高于 `.oi-btn.is-on .oi-count`(0,3,0)，不覆盖就会变成「浅粉底 + 浅粉字」压在亮蓝按钮上。
   这里统一成白底深蓝字（与浅色一致），实测对比度 7:1。 */
body.dark .oi-btn.is-on .oi-count { background: #f0f0f3; color: #248bc8; }

/* 筛选后一行不剩：给一张明确的空态，而不是只剩表头的空表 */
.matrix-empty-hint {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 12px; padding: 14px 16px;
  background: var(--sunken-bg); box-shadow: var(--sunken-1);
  border-radius: var(--radius); color: var(--muted); font-size: 12px;
}
.matrix-empty-hint svg { flex: none; color: var(--brand); }
.matrix-empty-hint span { flex: 1 1 auto; }
.matrix-empty-hint .btn { flex: none; padding: 6px 12px; font-size: 12px; }

/* 导出菜单里的「只导当前行」提示 */
.export-hint {
  padding: 8px 12px 9px; margin-bottom: 4px;
  border-bottom: 1px solid var(--line);
  font-size: 11px; line-height: 1.5; color: var(--muted);
}
.export-hint b { color: var(--text); font-variant-numeric: tabular-nums; }

/* ========== 图标化后的局部对齐（2026-10-21） ========== */
/* 矩阵右键菜单：图标 + 文字一行 */
.matrix-ctx-item { display: flex; align-items: center; gap: 7px; }
.matrix-ctx-item .mc-ico { display: inline-flex; }
.matrix-ctx-item.ok .mc-ico { color: #227771; }
.matrix-ctx-item.no .mc-ico { color: #db0000; }

/* 报价单行「删除」：点击区 26×26 → 32×32（低于 32px 在触摸/手抖时很容易点错，
   而删掉一份报价单是不可撤销的）。❌ 不要再改回 padding:4px 8px 的窄按钮。 */
.qitem .del {
  width: 32px; height: 32px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 18px; line-height: 1;
}

/* 规则弹窗统计：0 条时用弱化的 0 + 一句说明，别让一横「–」孤零零悬着像加载失败 */
.rules-stats .rstat.is-zero .v { color: var(--muted); }
.rules-stats-hint { margin: -2px 0 12px; font-size: 11px; color: var(--muted); }

/* ========== 另存为弹层（2026-10-25） ==========
 * 形态由用户定稿：只用应用内弹层（不调系统 showSaveFilePicker），
 * 文件名 / 类型 / 浮动系数都在这一层填，保存后直接落浏览器默认下载目录。
 * 材质沿用 base.css：输入与分段轨道=凹、弹层与主按钮=凸，不手写 box-shadow。 */
.modal-box.save-box { width: 480px; display: flex; flex-direction: column; max-height: 92vh; }
/* 内容变长（C71 加了抬头四项）后：正文自己滚，底部按钮始终可见 */
.save-body { display: flex; flex-direction: column; gap: 14px; overflow-y: auto; min-height: 0; padding-right: 2px; }
.save-name-field { margin-bottom: 0; }
.save-name-field > label,
.save-block > label { display: block; margin-bottom: 6px; font-size: 12px; font-weight: 600; color: var(--text); }
.save-name-row { display: flex; align-items: stretch; }
.save-name-row input {
  flex: 1 1 auto; min-width: 0; width: auto;
  border-top-right-radius: 0; border-bottom-right-radius: 0;
}
/* 2026-11-05 用户定：文件类型不再是单独一排按钮，改成文件名后面的后缀下拉。
   风格与左边的文件名输入框拼成一整条：左边方角、右边圆角。 */
.save-ext-select {
  flex: none; width: 100px; height: auto; min-height: 40px;
  padding: 0 8px; font-size: 13px; cursor: pointer;
  border-top-left-radius: 0; border-bottom-left-radius: 0;
  border-left: none;
}

/* 税率行：勾选框 + 百分比下拉 + 说明 */
.save-tax-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.save-check-inline { align-items: center; font-size: 12px; }
.save-check-inline input { margin: 0; }
.save-tax-select { width: 96px; min-width: 96px; height: 34px; padding: 0 10px; font-size: 13px; cursor: pointer; }

.save-ext {
  display: inline-flex; align-items: center; flex: none; padding: 0 12px;
  font-size: 13px; color: var(--muted);
  background: var(--sunken-bg); border: 1px solid var(--border-strong); border-left: none;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  box-shadow: var(--sunken-1);
  font-variant-numeric: tabular-nums;
}
.save-hint { margin-top: 6px; font-size: 11px; line-height: 1.5; color: var(--muted); }
.save-hint b { color: var(--text); font-variant-numeric: tabular-nums; }
.save-seg { width: 100%; }
.save-seg .seg-item { flex: 1; padding: 8px 6px; text-align: center; }
/* C72：报价单选项挪到弹层最上面（参照单打头），分隔线/上内边距随之去掉 */
.save-quote { display: flex; flex-direction: column; gap: 14px; }
.save-select { width: 100%; }
.save-coef-row { display: flex; align-items: center; gap: 8px; }
.save-coef {
  width: 96px; padding: 9px 11px; font-size: 13px; font-family: inherit;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--sunken-bg); color: var(--text); box-shadow: var(--sunken-1);
  font-variant-numeric: tabular-nums;
}
.save-coef:focus { outline: none; border-color: var(--brand); box-shadow: var(--sunken-focus); }
.save-pct { font-size: 13px; color: var(--muted); }
.save-calc { margin-left: auto; font-size: 12px; color: var(--muted); text-align: right; font-variant-numeric: tabular-nums; }
.save-calc b { color: var(--text); }
.save-check { display: flex; align-items: flex-start; gap: 8px; font-size: 12px; color: var(--text); cursor: pointer; user-select: none; }
/* C72：非 xlsx 时「带公式」整行变灰不可点（PDF/CSV 没有公式） */
.save-check.is-disabled { opacity: .5; cursor: not-allowed; }
.save-check-tip { margin-left: 4px; font-size: 11px; color: var(--muted); }
.save-check input { margin: 2px 0 0; accent-color: var(--brand); }
.save-note {
  padding: 10px 12px; border-radius: var(--radius-sm);
  background: var(--sunken-bg); box-shadow: var(--sunken-1);
  font-size: 12px; line-height: 1.6; color: var(--muted);
}
.save-note b { color: var(--text); }
.save-note.is-warn { color: var(--warn); background: rgba(255,230,109,0.18); box-shadow: none; }
body.dark .save-note.is-warn { color: var(--warn); background: rgba(255,230,109,0.18); }
.save-foot { display: flex; justify-content: flex-end; gap: 10px; margin-top: 18px; }

/* 报价单抬头四项（C71）：2×2 栅格，跟 .field 共用凹面输入框，只压高度 */
.save-meta { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 12px; }
.save-meta-f { margin-bottom: 0; }
.save-meta-f > label {
  display: block; margin-bottom: 5px;
  font-size: 12px; font-weight: 600; color: var(--muted);
}
.save-meta-f input { height: 36px; padding: 0 10px; font-size: 13px; }
/* 2026-11-05：报价有效期紧跟「日期」下方（右列），所以强制占第 2 列；
   窄屏改单列时恢复自动排布，否则会空出左边一格。 */
.save-meta-valid { grid-column: 2; }
.save-valid-row { display: flex; align-items: center; gap: 6px; }
.save-valid-row input { flex: 1; min-width: 0; }
.save-valid-unit { flex: none; font-size: 12px; color: var(--muted); }
@media (max-width: 520px) { .save-meta { grid-template-columns: 1fr; } .save-meta-valid { grid-column: auto; } }

/* ==========================================================
 * 保存结果确认浮层（2026-11-02 用户定，C70）
 *   原来用 alert()：位置由浏览器决定、落在窗口顶部，离「保存」按钮很远，
 *   用户要跨半个屏幕去点确定。改成贴着按钮的浮层。
 *   材质按 C58：浮层 = 凸（--raised-2），颜色只用变量，深色自动跟随。
 * ========================================================== */
.save-pop {
  position: fixed; z-index: 110;                 /* 高于 .modal(100)，低于提示层(1200) */
  width: min(330px, calc(100vw - 24px));
  padding: 14px 16px 12px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--raised-2);
  display: flex; flex-direction: column; gap: 8px;
}
.save-pop.hidden { display: none; }
.save-pop-body { font-size: 13px; line-height: 1.7; color: var(--text); }
.save-pop-body .sp-t { font-weight: 600; margin-bottom: 4px; word-break: break-all; }
.save-pop-body b { font-weight: 600; }
.save-pop-body .sp-diff { color: var(--warn); font-weight: 700; }
.save-pop-foot { display: flex; justify-content: flex-end; margin-top: 2px; }
.save-pop-foot .btn { min-width: 78px; height: 32px; padding: 0 16px; }
/* 箭头：与浮层同底色，只画朝外的两条边（四边都画会出现双线） */
.save-pop-arrow { position: absolute; width: 10px; height: 10px; background: var(--card); transform: rotate(45deg); }
.save-pop-arrow.is-bottom { bottom: -6px; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.save-pop-arrow.is-top { top: -6px; border-left: 1px solid var(--line); border-top: 1px solid var(--line); }

/* ==========================================================
 * 排版层（2026-10-25）：长说明收进「?」
 * ------------------------------------------------------------
 * 原「报价单」卡片说明约 150 字、单行排到 1100px，12px 灰字根本读不完。
 * 现在默认一行摘要 + 一个 16px 圆点，详情用原生 <details> 弹出（零 JS、键盘可达）。
 * 字号阶梯同时收敛为 11 / 12 / 13 / 14 / 15 / 22 六档。
 * ========================================================== */
.card .hint { position: relative; }
.hint-more { display: inline-block; vertical-align: middle; margin-left: 6px; }
.hint-more > summary {
  list-style: none; width: 16px; height: 16px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; line-height: 1; color: var(--muted);
  background: var(--bg); box-shadow: var(--raised-1); cursor: pointer;
  transition: box-shadow .3s ease-in-out, color .3s ease-in-out;
}
.hint-more > summary::-webkit-details-marker { display: none; }
.hint-more > summary:hover { color: var(--brand); }
.hint-more > summary:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
/* 展开 = 按进表面，与全站「选中即凹」一致 */
.hint-more[open] > summary { color: var(--brand); box-shadow: var(--press-1); }
.hint-pop {
  position: absolute; left: 0; top: calc(100% + 10px); z-index: 40;
  width: 620px; max-width: min(620px, calc(100vw - 120px));
  background: var(--card); border-radius: var(--radius-sm); box-shadow: var(--raised-3);
  padding: 12px 14px; font-size: 12px; line-height: 1.8; color: var(--muted); font-weight: 400;
}
.hint-pop b { color: var(--text); font-weight: 600; }

/* ==========================================================
 * 设置 → 个人资料（C68，2026-11-01）
 *   节流：pane 内本身可纵向滚动（.set-pane 已有 overflow），这里只做分节与两列栅格。
 *   .rg-upload / .rg-status / .rg-tpl 复用 css/register.css，别在这里重复定义。
 * ========================================================== */
.pf-body { display: flex; flex-direction: column; gap: 9px; padding: 0; }
.pf-sec { display: flex; flex-direction: column; gap: 8px; }
.pf-sec-h {
  display: flex; align-items: center; gap: 8px;
  font-size: 13px; font-weight: 700; color: var(--text);
  padding-bottom: 8px; border-bottom: 1px solid var(--line);
}
.pf-kv { display: grid; grid-template-columns: 84px 1fr; gap: 8px 12px; font-size: 13px; }
.pf-kv span { color: var(--muted); }
.pf-kv b { font-weight: 600; word-break: break-all; }
.pf-tip { font-size: 12px; line-height: 1.65; color: var(--muted); }
.pf-hint { font-size: 12px; line-height: 1.6; border-radius: var(--radius-sm); padding: 7px 11px; }
.pf-hint:empty { display: none; }
.pf-hint.ok { color: var(--down); background: rgba(78,205,196,0.10); }
.pf-hint.warn { color: var(--warn); background: rgba(255,230,109,0.14); }
.pf-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.pf-row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.pf-uploads { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.pf-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 2px; }
.pf-actions .btn { min-width: 132px; }
.mk-tip.ok { color: var(--down); }
.mk-tip.bad { color: var(--up); }
@media (max-width: 720px) {
  .pf-grid, .pf-uploads, .pf-row2 { grid-template-columns: 1fr; }
}

/* 个人资料里的表单控件（C68）
 * ⚠️ 不要复用 .mk-field/.mk-tip：它们定义在 css/market.css，而 index.html 不加载那个文件，
 *    直接套用会「类名在、样式不在」——表现为输入框塌成一条细线（2026-11-01 实测）。
 *    这里自建 .pf-field，与 C58「输入=凹」的材质规范保持一致。 */
.pf-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.pf-field > label {
  display: flex; align-items: center; gap: 5px;
  font-size: 12px; font-weight: 600; color: var(--muted);
}
.pf-field input[type=text],
.pf-field select {
  width: 100%; height: 38px; padding: 0 12px; box-sizing: border-box;
  font: inherit; font-size: 13px; color: var(--text);
  border: none; border-radius: var(--radius-sm);
  background: var(--sunken-bg); box-shadow: var(--sunken-1);
  outline: none;
}
.pf-field input[type=text]:focus,
.pf-field select:focus { box-shadow: var(--sunken-1), 0 0 0 2px var(--brand); }
.pf-field input::placeholder { color: var(--muted); }
.pf-tip.ok { color: var(--down); }
.pf-tip.bad { color: var(--up); font-weight: 600; }

/* 账号区单行排布（C68）：三组「标签 + 值」横向摊开，省下的高度留给单位信息与提交按钮 */
.pf-kv-row {
  grid-template-columns: auto minmax(72px, 1fr) auto minmax(72px, 1fr) auto minmax(56px, 1fr);
  align-items: center; gap: 6px 10px;
}

/* C69：「② 实名认证」标题右侧的状态说明（需先填信息 / 已通过 / 审核中）
 * 2026-11-03：标题行改成「左标题 + 中间说明（自动撑开、右对齐）+ 右按钮」三件套，
 *   ② 的「提交实名认证」也挪到这里，与 ① 的「保存信息」同款同位置。 */
.pf-sec-tip { flex: 1 1 auto; text-align: right; font-weight: 400; font-size: 12px; color: var(--muted); }
/* ① 没有 tip，用徽标的 margin-right 把按钮顶到最右，保证两节按钮右端对齐 */
.pf-sec-h .rg-status { margin-right: auto; }
/* ① 单位信息标题右侧的「保存信息」小按钮（C69）：高度压到 26px，避免挤掉 ② 的提交按钮 */
.pf-sec-h .pf-h-btn {
  margin-left: 0; height: 26px; min-width: 0; padding: 0 12px;
  font-size: 12px; line-height: 1; flex: none;
}

/* ==========================================================
 * 账号绑定行（2026-11-03，2026-11-03 重排）
 *   绑定手机/微信决定「能否发布需求与报价」，比单位信息更靠前，放在账号区正下方。
 *   2026-11-03：原来 6 个元素挤一行，输入框被压到 96-118px。改成三行：
 *     ① 手机绑定 + 状态 + 主按钮（常驻，收起时是「更换手机」）
 *     ② 手机号输入（吃满）+ 获取验证码
 *     ③ 验证码输入（吃满）+ 提示
 *   输入框沿用 C58 的「输入=凹」材质（--sunken-*），不要写死阴影。
 * ========================================================== */
.pf-bind { display: flex; flex-direction: column; gap: 8px; font-size: 12px; }
.pf-bind-head { display: flex; align-items: center; gap: 8px; min-height: 30px; }
.pf-bind-k { color: var(--muted); }
.pf-bind b { font-weight: 600; }
.pf-bind .pf-h-btn { height: 30px; padding: 0 12px; font-size: 12px; }
.pf-bind-head .pf-h-btn { margin-left: auto; }
.pf-bind-row { display: flex; align-items: center; gap: 8px; }
.pf-bind-row input {
  /* 手机号 300px 足够（11 位数字），不撑满整行 —— 980 宽的分栏面板里吃满会显得空 */
  flex: 0 1 300px; min-width: 0; height: 32px; padding: 0 10px; box-sizing: border-box;
  font: inherit; font-size: 12px; color: var(--text); width: auto;
  border: none; border-radius: var(--radius-sm);
  background: var(--sunken-bg); box-shadow: var(--sunken-1); outline: none;
}
.pf-bind-row input:focus { box-shadow: var(--sunken-1), 0 0 0 2px var(--brand); }
.pf-bind-row input::placeholder { color: var(--muted); }
/* 按钮始终贴行右端，与标题行的「绑定手机 / 更换手机」对齐 */
.pf-bind-row .pf-h-btn { flex: none; margin-left: auto; }
.pf-bind-row .pf-h-btn[disabled] { opacity: .55; cursor: default; }
/* 验证码 6 位，窄一点；右侧用一句轻提示补足视觉重量（贴右，与上行按钮同列） */
.pf-bind-row #pfBindCode { flex: 0 1 200px; letter-spacing: 1px; }
.pf-bind-hint { flex: 1 1 auto; color: var(--muted); font-size: 11px; text-align: right; }

/* ==========================================================
 * 窄屏（≤560px，含 390px 手机）：报价单卡片与状态条不再互相挤压
 * 2026-11-03 修 BUG-009：390px 下删除按钮掉到第三行单独一行、
 *   状态条「比对 未…」被省略号截断、"未选择定额模板"被挤成细长条。
 * 只加媒体查询，桌面端样式一行未改。
 * ========================================================== */
@media (max-width: 560px) {
  /* 卡片：第一行「文件名 + 删除」，第二行「元信息 + 解析报告」。
     删除按钮必须留在右上角行内（QA 明确要求），不能再被长元信息挤到下一行。 */
  .qitem { padding: 10px 12px; gap: 6px 8px; }
  .qitem .qname { flex: 1 1 auto; order: 1; min-width: 0; }
  .qitem .qname input { max-width: none; }
  .qitem .del { order: 2; margin-left: auto; flex: none; }
  .qitem .qmeta { order: 3; margin-left: 0; flex: 1 1 auto; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; line-height: 1.6; }
  .qitem .qmiss { margin-left: 0; }
  .qitem .qreport { order: 4; flex: none; }
  .qitem .drop-inline { order: 4; flex: none; }

  /* 状态条：三段各占一行，允许换行，不再用省略号截断 */
  .status-strip { height: auto; min-height: 40px; padding: 8px 12px; flex-wrap: wrap; gap: 4px 0; }
  .ss-item { flex: 1 1 100%; }
  .ss-item .ss-val { white-space: normal; overflow: visible; text-overflow: clip; }
  .ss-sep { display: none; }

  /* 定额 / 基准（已并入动作行）：窄屏时标签与下拉各占一行，说明不会被挤成竖排窄条 */
  .action-fields { gap: 8px; }
  .action-fields label { flex: 1 1 100%; }
  .action-fields select { flex: 1 1 100%; min-width: 0; max-width: none; }
  .action-fields .meta { flex: 1 1 100%; max-width: none; text-align: left; margin-right: 0; }
}
