:root {
  --bg: #f1f5f9;
  --panel: #ffffff;
  --border: #dbe3ec;
  --border-strong: #c3cedb;
  --text: #1e293b;
  --muted: #64748b;
  --primary: #1d4ed8;
  --primary-dark: #1e40af;
  --ok: #15803d;
  --ok-bg: #dcfce7;
  --warn: #b45309;
  --warn-bg: #fef3c7;
  --danger: #b91c1c;
  --danger-bg: #fee2e2;
  --info-bg: #e0f2fe;
  --info: #0369a1;
  --shadow: 0 1px 3px rgba(15, 23, 42, .08), 0 1px 2px rgba(15, 23, 42, .04);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
  font-size: 13px;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

button, input, select, textarea { font-family: inherit; font-size: 13px; color: inherit; }

/* ---------------- 布局 ---------------- */
.app { display: flex; flex-direction: column; height: 100vh; }

header.topbar {
  display: flex; align-items: center; gap: 14px;
  padding: 0 16px; height: 52px;
  background: #0f172a; color: #e2e8f0;
  box-shadow: var(--shadow); z-index: 20;
}
header.topbar .brand { font-size: 15px; font-weight: 600; letter-spacing: .5px; }
header.topbar .brand small { font-weight: 400; color: #94a3b8; margin-left: 8px; font-size: 12px; }
header.topbar .spacer { flex: 1; }
header.topbar .stat { color: #94a3b8; font-size: 12px; }
header.topbar .stat b { color: #e2e8f0; }

nav.tabs { display: flex; gap: 4px; padding: 0 12px; background: #fff; border-bottom: 1px solid var(--border); }
nav.tabs button {
  border: none; background: none; padding: 11px 16px; cursor: pointer;
  color: var(--muted); border-bottom: 2px solid transparent; font-size: 13px;
}
nav.tabs button:hover { color: var(--text); }
nav.tabs button.active { color: var(--primary); border-bottom-color: var(--primary); font-weight: 600; }

main { flex: 1; overflow: hidden; display: flex; }
.view { flex: 1; overflow: auto; padding: 16px; display: none; }
.view.active { display: block; }

/* ---------------- 通用控件 ---------------- */
/* 按钮样式对 <button> 与 <a> 都生效——
   以前只写了 button.btn，界面里 8 处 <a class="btn">（打开原文件、看…）
   完全没有按钮外观，显示成裸链接。 */
button.btn, a.btn {
  display: inline-block; text-decoration: none;
  border: 1px solid var(--border-strong); background: #fff; color: var(--text);
  padding: 6px 13px; border-radius: 6px; cursor: pointer; white-space: nowrap;
  font-size: inherit; font-family: inherit;
}
button.btn:hover, a.btn:hover { background: #f8fafc; border-color: #94a3b8; }
button.btn.primary, a.btn.primary {
  background: var(--primary); border-color: var(--primary); color: #fff; }
button.btn.primary:hover, a.btn.primary:hover { background: var(--primary-dark); }
button.btn.danger, a.btn.danger { color: var(--danger); border-color: #fca5a5; }
button.btn.danger:hover, a.btn.danger:hover { background: var(--danger-bg); }
button.btn.sm, a.btn.sm { padding: 3px 9px; font-size: 12px; border-radius: 5px; }
button.btn:disabled { opacity: .5; cursor: not-allowed; }

input[type=text], input[type=number], input[type=date], input[type=search], select, textarea {
  border: 1px solid var(--border-strong); border-radius: 6px; padding: 6px 9px;
  background: #fff; outline: none; width: 100%;
}
input:focus, select:focus, textarea:focus { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(29,78,216,.12); }

label.fld { display: block; margin-bottom: 10px; }
label.fld span { display: block; font-size: 12px; color: var(--muted); margin-bottom: 4px; }

.toolbar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 12px; }
.toolbar .grow { flex: 1; }

.card { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; box-shadow: var(--shadow); }
.card + .card { margin-top: 14px; }
.card > h3 { margin: 0; padding: 11px 14px; border-bottom: 1px solid var(--border); font-size: 13px; font-weight: 600; }
.card > .body { padding: 14px; }

.muted { color: var(--muted); }
.small { font-size: 12px; }

.badge { display: inline-block; padding: 1px 7px; border-radius: 10px; font-size: 11px; line-height: 17px; white-space: nowrap; }
.badge.ok { background: var(--ok-bg); color: var(--ok); }
.badge.warn { background: var(--warn-bg); color: var(--warn); }
.badge.err { background: var(--danger-bg); color: var(--danger); }
.badge.info { background: var(--info-bg); color: var(--info); }
.badge.gray { background: #eef2f7; color: var(--muted); }

/* ---------------- 送货单 ---------------- */
.notes-wrap { display: flex; gap: 16px; height: 100%; align-items: flex-start; }
.notes-wrap { --notes-w: 330px; }
.notes-list { width: var(--notes-w, 330px); flex: none; position: sticky; top: 0; }
/* 分隔条：左右拖动改宽度，拖到很窄就相当于折叠 */
.notes-resizer { flex: none; width: 6px; align-self: stretch; cursor: col-resize;
  border-radius: 3px; background: transparent; transition: background .15s; }
.notes-resizer:hover, .notes-resizer.dragging { background: var(--primary); opacity: .45; }
/* 折叠态：列表与分隔条都收起，只留一个展开把手 */
.notes-wrap.collapsed .notes-list,
.notes-wrap.collapsed .notes-resizer { display: none; }
.notes-expand { display: none; flex: none; align-self: flex-start;
  width: 22px; padding: 10px 0; cursor: pointer;
  border: 1px solid var(--border); border-radius: 6px; background: #f8fafc;
  color: var(--muted); font-size: 14px; line-height: 1; }
.notes-expand:hover { background: #eef2f7; color: var(--primary); }
.notes-wrap.collapsed .notes-expand { display: block; }
/* 左侧卡片用 flex 撑满可视高度：列表自己滚，小结条永远钉在卡片底部。
   以前用 max-height 硬算像素，加上小结条后就顶出视口、条看不见了。 */
.notes-list.card { display: flex; flex-direction: column; max-height: calc(100vh - 150px); }
.notes-list .items { flex: 1 1 auto; min-height: 0; max-height: none; overflow: auto; }
.note-card { padding: 9px 12px 9px 9px; border-left: 3px solid transparent;
  border-bottom: 1px solid var(--border); cursor: pointer; transition: background .12s; }
.note-card:hover { background: #f8fafc; }
.note-card.active { background: #eff6ff; border-left-color: var(--primary); }
.note-card .l1 { display: flex; justify-content: space-between; gap: 8px; font-weight: 600; }
.note-card .l1 .amt { color: var(--primary); font-variant-numeric: tabular-nums; }
.note-card .l2 { color: var(--muted); font-size: 12px; margin-top: 3px; }
.note-card .l2 .miss { color: var(--danger); }
/* 质检进度条：已匹配 / 待确认 / 未找到 三色按比例铺开 */
.note-card .qcrow { display: flex; align-items: center; gap: 8px; margin-top: 7px; }
.note-card .qcbar { flex: 1; min-width: 0; display: flex; height: 5px; border-radius: 3px;
  overflow: hidden; background: #e6ebf2; }
.note-card .qcbar i { display: block; height: 100%; transition: width .2s; }
.note-card .qcbar .ok { background: #22c55e; }
.note-card .qcbar .ask { background: #f59e0b; }
.note-card .qcbar .miss { background: #ef4444; }
.note-card .ratio { flex: none; font-size: 11px; color: var(--muted);
  font-variant-numeric: tabular-nums; }

.note-main { flex: 1; min-width: 0; }

table.grid { width: 100%; border-collapse: collapse; font-size: 12px; }
table.grid th, table.grid td { border-bottom: 1px solid var(--border); padding: 6px 7px; text-align: left; vertical-align: middle; }
table.grid th { background: #f8fafc; font-weight: 600; color: #334155; position: sticky; top: 0; z-index: 2; }
table.grid tbody tr:hover { background: #f8fafc; }
table.grid td.num, table.grid th.num { text-align: right; font-variant-numeric: tabular-nums; }
table.grid td.ctr, table.grid th.ctr { text-align: center; }
table.grid tr.selected { background: #eff6ff; }
table.grid input[type=text], table.grid input[type=number] { padding: 3px 6px; border-radius: 4px; }
.table-scroll { overflow: auto; max-height: calc(100vh - 400px); }

.summary { display: flex; gap: 22px; flex-wrap: wrap; align-items: baseline; padding: 10px 14px; background: #f8fafc; border-top: 1px solid var(--border); font-size: 12px; }
.summary .big { font-size: 16px; font-weight: 700; color: var(--primary); }
.summary .cn { color: var(--muted); }

.meta-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 10px 16px; padding: 14px; }
.meta-grid .k { font-size: 12px; color: var(--muted); margin-bottom: 3px; }

/* ---------------- 报告库 ---------------- */
.report-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: 12px; }
.report-card { border: 1px solid var(--border); border-radius: 9px; overflow: hidden; background: #fff; cursor: pointer; }
.report-card:hover { border-color: var(--primary); box-shadow: 0 2px 10px rgba(29,78,216,.12); }
/* 卡片顶部状态栏：文件类型 / 页数 / 大小 / 引用数 / 提取状态 */
.report-card .card-bar { display: flex; align-items: center; gap: 6px;
  padding: 5px 8px; background: #f8fafc; border-bottom: 1px solid var(--border);
  font-size: 11px; color: var(--muted); min-height: 26px; }
.report-card .card-bar .type-icon { color: #475569; line-height: 0; flex: none;
  padding: 2px 4px; border-radius: 5px; }
.report-card .card-bar .type-icon svg { width: 15px; height: 15px; }
.report-card .card-bar .bar-meta { white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }
.report-card .thumb { height: 190px; background: #f8fafc; display: flex; align-items: center;
  justify-content: center; overflow: hidden; position: relative; }
/* 状态徽章压在报告图右上角：一眼看到状态，又不占文字区的位置 */
.report-card .thumb-badge { display: flex; align-items: center; line-height: 0; }
/* 状态圆点：绿=已提取 蓝=提取中 红=失败 灰=未提取 */
.report-card .dot { display: block; width: 9px; height: 9px; border-radius: 50%; }
.report-card .dot-ok   { background: #16a34a; }
.report-card .dot-run  { background: #2563eb; animation: dotpulse 1.1s ease-in-out infinite; }
.report-card .dot-err  { background: #dc2626; }
.report-card .dot-gray { background: #94a3b8; }
@keyframes dotpulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }

.report-card .thumb img { max-width: 100%; max-height: 100%; }
.report-card .cap { padding: 7px 9px; font-size: 11.5px; line-height: 1.45; word-break: break-all; }
.report-card .cap .nm { font-weight: 600; }
.report-card .cap .sub { color: var(--muted); margin-top: 3px; }

/* ---------------- 弹窗 ---------------- */
.overlay { position: fixed; inset: 0; background: rgba(15,23,42,.45); display: flex; align-items: center; justify-content: center; z-index: 100; padding: 24px; }
.overlay.hidden { display: none; }
.modal { background: #fff; border-radius: 12px; box-shadow: 0 20px 50px rgba(15,23,42,.3); display: flex; flex-direction: column; max-height: 92vh; width: 900px; max-width: 100%; overflow: hidden; }
.modal.wide { width: 1180px; }
.modal.narrow { width: 520px; }
.modal > header { display: flex; align-items: center; padding: 13px 16px; border-bottom: 1px solid var(--border); }
.modal > header h3 { margin: 0; font-size: 14px; flex: 1; }
.modal > .content { padding: 16px; overflow: auto; flex: 1; }
/* 匹配报告面板用的是 .modal-body —— 之前没给它任何样式，
   于是内容撑破弹窗、变成整页滚动，标题与进度都跟着滚走。 */
.modal > .modal-body { padding: 16px; overflow: auto; flex: 1; min-height: 0; }
/* 状态区吸顶：116 行的列表往下滚时，进度与结果始终看得见 */
.am-sticky { position: sticky; top: -16px; z-index: 3; background: #fff;
  padding: 10px 0 8px; margin: -16px 0 0; border-bottom: 1px solid var(--border); }
.modal > footer { padding: 12px 16px; border-top: 1px solid var(--border); display: flex;
  gap: 8px; row-gap: 8px; justify-content: flex-end; flex-wrap: wrap; background: #f8fafc; }
/* 选择报告弹窗：底栏「以后同名同规格同批次，自动用这份」勾选框 */
.qc-remember { display: inline-flex; align-items: center; gap: 5px; margin: 0;
  font-size: 12.5px; color: var(--fg); cursor: pointer; white-space: nowrap; }
.qc-remember input { width: auto; margin: 0; }
/* 缺规格/日期时勾不了：直接写清原因，不再给一个灰掉的勾选框 */
.qc-remember.off { color: var(--muted); cursor: help;
  border-bottom: 1px dashed var(--border-strong); }
.x-btn { border: none; background: none; font-size: 20px; line-height: 1; cursor: pointer; color: var(--muted); padding: 0 4px; }
.x-btn:hover { color: var(--text); }

/* 选择弹窗：候选列表沿用明细表（table.grid）的样式——
   同样的表头、行线、悬停与选中色，只是列不一样。 */
.pick-table { table-layout: fixed; }
.pick-table col.c-nm { width: auto; }
.pick-table col.c-sp { width: 22%; }
.pick-table col.c-dt { width: 19%; }
.pick-table th { white-space: nowrap; }
.pick-table thead th { background: #fff;
  border-bottom: 1px solid var(--border-strong); }
.pick-table td.kc { font-variant-numeric: tabular-nums; }
.pick-table tbody tr.cand-row { cursor: pointer; }

.pick-table .c-thumb { width: 62px; text-align: center; }
.pick-table .c-thumb img { width: 42px; height: 57px; object-fit: cover; border-radius: 3px;
  background: #f1f5f9; vertical-align: middle;
  box-shadow: 0 1px 3px rgba(15, 23, 42, .16); }
.pick-table .c-thumb .cmeta { color: var(--muted); font-size: 10.5px; margin-top: 3px;
  white-space: nowrap; }
.pick-table .c-thumb .cmeta .score { color: var(--primary); font-weight: 700; }
.pick-table .c-best {
  display: inline-block; margin-left: 3px; padding: 0 4px; border-radius: 3px;
  background: var(--ok-bg); color: var(--ok); font-size: 10px; font-weight: 600;
  vertical-align: 1px;
}
.pick-table .c-act { width: 58px; text-align: right; }
.pick-table .c-act .btn { background: transparent; color: var(--muted);
  border-color: transparent; padding-left: 6px; padding-right: 6px; }
.pick-table .c-act .btn:hover { background: #fff; color: var(--primary);
  border-color: var(--primary); }
.pick-table tbody tr.cand-row:hover .c-act .btn { color: var(--primary); }
.pick-table .c-pick { width: 34px; text-align: center; }
/* 选择用复选框：方框比小圆点好点，也和明细表的勾选列一致（仍然是单选） */
.pick-table .c-pick input.c-check {
  width: 15px; height: 15px; margin: 0; padding: 0; cursor: pointer;
  accent-color: var(--primary); vertical-align: middle;
}
.pick-table .c-foot { text-align: right; padding: 6px 2px 0; border-bottom: 0; }
/* 明细那一行：浅底 + 更重的一条下边线，常驻在候选上方 */
.pick-table tbody tr.pick-item > td {
  background: #f8fafc; font-weight: 600;
  border-bottom: 1px solid var(--border-strong); }
.pick-table tbody tr.pick-item > td:first-child {
  color: var(--muted); font-weight: 400; font-size: 11.5px; }
/* 选中行左侧一条主色竖杠 */
.pick-table tbody tr.cand-row.picked > td:first-child {
  box-shadow: inset 3px 0 0 var(--primary); }
.pick-table thead th { position: sticky; top: 0; z-index: 2; background: #fff; }
.pick-table tr.pick-item { position: sticky; top: 24px; z-index: 1; }
/* 一格：值后面紧跟 ↻（不是顶到格子最右边） */
.pick-table .kc { padding-right: 8px; }
.pick-table .kc .kline { display: flex; align-items: center; gap: 5px; min-width: 0; }
.pick-table .kc .kv { min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.pick-table .kc .cfn { color: var(--muted); font-size: 11px; margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 值下面的一行小标记（最接近的批次 / 疑似抄错之类），不跟值抢横向空间 */
.pick-table .kc .kmark { margin-top: 3px; }
.pick-table .kc .kmark .badge { font-size: 10px; padding: 0 5px; line-height: 16px; }
/* 相符/不符只用文字颜色表达，不再铺底色 */
.pick-table .kc.ok  { color: #15803d; }
.pick-table .kc.bad { color: #b91c1c; }
.pick-table .kc.unk { color: var(--text); }
.pick-table .kc.ok  .kv, .pick-table .kc.bad .kv { font-weight: 600; }
.pick-table .kc .kfix { color: #94a3b8; }
.score { font-variant-numeric: tabular-nums; font-weight: 600; }

.pdf-preview { width: 100%; height: 62vh; border: 1px solid var(--border); border-radius: 8px; background: #eef2f7; }
.page-strip { display: flex; flex-direction: column; gap: 10px; align-items: center; background: #eef2f7; padding: 12px; border-radius: 8px; max-height: 62vh; overflow: auto; }
.page-strip img { max-width: 100%; box-shadow: 0 2px 8px rgba(15,23,42,.18); background: #fff; }

.toast { position: fixed; right: 20px; bottom: 20px; z-index: 500; display: flex; flex-direction: column; gap: 8px; }
.toast .t { padding: 10px 14px; border-radius: 8px; background: #0f172a; color: #fff; box-shadow: var(--shadow); max-width: 460px; font-size: 12.5px; }
.toast .t.err { background: var(--danger); }
.toast .t.ok { background: #166534; }
.toast .t.warn { background: #92400e; }

.spinner { display: inline-block; width: 13px; height: 13px; border: 2px solid rgba(255,255,255,.4); border-top-color: #fff; border-radius: 50%; animation: spin .7s linear infinite; vertical-align: -2px; }
/* 普通（白底）按钮上的转圈：白色看不见，改用主题蓝 */
.btn:not(.primary):not(.danger) .spinner,
.btn.ghost .spinner { border-color: #cbd5e1; border-top-color: var(--primary); }
/* 小按钮里的转圈缩小一点，免得撑变形 */
.btn.sm .spinner { width: 11px; height: 11px; border-width: 2px; }
.fix-one .spinner { width: 10px; height: 10px; border-width: 2px;
  border-color: #cbd5e1; border-top-color: var(--primary); }
@keyframes spin { to { transform: rotate(360deg); } }

.empty { text-align: center; color: var(--muted); padding: 40px 20px; }

.row-actions { display: flex; gap: 4px; }

.split { display: grid; grid-template-columns: 360px 1fr; gap: 16px; }
.checkline { display: flex; align-items: center; gap: 7px; margin-bottom: 8px; }
.checkline input { width: auto; }

/* 「质检报告汇总」页的内容选项：缩进在封面勾选项下面 */
.cover-opts {
  margin: -2px 0 10px 26px; padding-left: 11px;
  border-left: 2px solid var(--border, #dfe4ea);
}
.cover-row { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 12px; margin-bottom: 6px; }
.cover-opts.off .cover-row, .cover-row.off { opacity: .45; }
.cover-lb { color: var(--muted, #6b7280); font-size: 12px; min-width: 42px; }
.cover-row .ck {
  display: inline-flex; align-items: center; gap: 4px; margin: 0;
  font-size: 12.5px; cursor: pointer; white-space: nowrap;
}
.cover-row .ck input { width: auto; margin: 0; }
.cover-row .ck:has(input:disabled) { cursor: default; }
.cover-tip { font-size: 12px; color: var(--muted, #6b7280); min-height: 0; }
.cover-tip:empty { display: none; }

/* 可排序表头：看得出能点，并标出当前升降序 */
table.grid th.sortable { cursor: pointer; user-select: none; white-space: nowrap; }
table.grid th.sortable:hover { background: #eef2f7; color: var(--primary, #1d4ed8); }
table.grid th.sortable .sort-mark { color: var(--primary, #1d4ed8); font-size: 11px; }

/* ---------------- 报告预览浮层 ---------------- */
#rpvOverlay { position: fixed; inset: 0; background: rgba(15,23,42,.55);
  z-index: 300; display: flex; align-items: center; justify-content: center; padding: 24px; }
.rpv-panel { background: #fff; border-radius: 10px; width: min(1100px, 96vw);
  max-height: 92vh; display: flex; flex-direction: column; overflow: hidden;
  box-shadow: 0 20px 50px rgba(0,0,0,.3); }
.rpv-head { display: flex; gap: 8px; align-items: center; padding: 10px 14px;
  border-bottom: 1px solid var(--border); background: #f8fafc; }
.rpv-body { overflow: auto; padding: 12px; background: #eef2f7;
  display: flex; flex-direction: column; gap: 12px; align-items: center; }
.rpv-body img { max-width: 100%; background: #fff; border: 1px solid var(--border);
  border-radius: 4px; }
.cname a.cview { color: inherit; text-decoration: none; }
.cname a.cview:hover { color: var(--primary); text-decoration: underline; }

/* 报告卡片上的三项关键字段：商品名称 / 规格 / 日期 */
.report-card .key3 { margin-top: 6px; font-size: 12px; line-height: 1.55;
  background: #f8fafc; border: 1px solid var(--border); border-radius: 6px; padding: 5px 7px; }
.report-card .key3 > div { display: flex; gap: 5px; }
.report-card .key3 .k { flex: none; color: var(--muted); width: 28px; }

/* 卡片上可点击修改的值：悬停才显出一条淡淡的虚线下划线，保持页面整洁 */
.report-card .kf-edit { cursor: text; border-bottom: 1px dashed transparent; }
.report-card .kf-edit:hover { border-bottom-color: var(--primary); color: var(--primary); }
.report-card .kf-input { width: 100%; font: inherit; padding: 1px 4px;
  border: 1px solid var(--primary); border-radius: 4px; }

/* 报告详情：解析信息默认折叠，页面保持整洁 */
.ex-more { margin: 2px 0 8px; }
.ex-more > summary { cursor: pointer; font-size: 12px; color: var(--muted);
  padding: 3px 0; user-select: none; }
.ex-more > summary:hover { color: var(--primary); }
.ex-more[open] > summary { margin-bottom: 4px; }

/* 详情页的「提取 / 重算」下拉菜单：把三个次要操作收成一个按钮 */
.menu-wrap { position: relative; display: inline-block; }
.menu { position: absolute; right: 0; top: calc(100% + 4px); z-index: 20;
  background: #fff; border: 1px solid var(--border); border-radius: 8px;
  box-shadow: 0 8px 20px rgba(15,23,42,.14); min-width: 168px; padding: 4px; }
.menu a { display: block; padding: 7px 10px; font-size: 13px; color: var(--text);
  text-decoration: none; border-radius: 6px; white-space: nowrap; }
.menu a:hover { background: #eff6ff; color: var(--primary); }

/* 报告全文（HTML 渲染）：表格画成真表格，读起来才像报告 */
.md-view { background: #fff; border: 1px solid var(--border); border-radius: 8px;
  padding: 12px 14px; font-size: 13px; line-height: 1.75; }
.md-view table { border-collapse: collapse; margin: 8px 0; width: 100%; }
.md-view td, .md-view th { border: 1px solid var(--border); padding: 4px 7px;
  vertical-align: top; }
.md-view tr:first-child td { background: #f8fafc; font-weight: 600; }
.md-view h4 { margin: 12px 0 6px; font-size: 14px; }
.md-view img { max-width: 100%; border: 1px solid var(--border); border-radius: 4px; margin: 6px 0; }
.md-view hr { border: none; border-top: 1px solid var(--border); margin: 10px 0; }


/* 报告全文里的原始 MD 视图 */
.md-raw { white-space: pre-wrap; word-break: break-word; background: #f8fafc;
  border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px;
  font-size: 12px; line-height: 1.65; font-family: ui-monospace, monospace; margin: 0; }

/* 报告覆盖多个规格时，用小标签分别列出（匹配时与任一个相符即算对上） */
.report-card .spec-chip { display: inline-block; background: #eef2ff; color: #3730a3;
  border-radius: 4px; padding: 0 5px; margin: 0 3px 2px 0; font-size: 11px; }

/* 人工修正过的报告：四项用蓝色标出，与"机器抽出来的"一眼区分 */
.report-card .key3.manual { background: #f5f3ff; border-color: #ddd6fe; }
.report-card .key3.manual .kf-edit { color: #7c3aed; }

/* 明细的字段筛选：标签 + 复合下拉 */
.flt { display: inline-flex; align-items: center; gap: 4px; }
.flt > label { font-size: 12px; color: var(--muted); }
.flt .flt-in { width: 118px; padding: 5px 7px; }

.report-card .used-n { display: inline-flex; align-items: center; gap: 2px;
  color: var(--primary); font-weight: 600; line-height: 1; }
.report-card .used-n svg { flex: none; }

/* 选择弹窗：候选行里的名称/规格/生产（与报告库同一呈现方式） */
.sm-select { padding: 2px 4px; font-size: 12px; }

/* 筛选框内的清除按钮：贴在输入框右端，有值才出现 */
.flt .flt-box { position: relative; display: inline-flex; align-items: center; }
/* 原生三角形：聚焦时才出现，且跟着 padding 走。全部压掉，自己画一个。 */
.flt .flt-in { -webkit-appearance: none; appearance: none; }
.flt .flt-in::-webkit-calendar-picker-indicator,
.flt .flt-in::-webkit-list-button,
.flt .flt-in::-webkit-inner-spin-button {
  display: none !important; opacity: 0 !important;
  width: 0 !important; margin: 0 !important; padding: 0 !important;
}
/* 三角形平时不显示，聚焦时才出现——和浏览器原生行为一致 */
.flt .flt-box::after {
  content: ''; position: absolute; right: 4px; top: 50%; margin-top: -3px;
  border-left: 5px solid transparent; border-right: 5px solid transparent;
  border-top: 6px solid #64748b; pointer-events: none;
  opacity: 0; transition: opacity .12s ease;
}
.flt .flt-box:focus-within::after { opacity: 1; }
.flt .flt-x { position: absolute; right: 20px; width: 16px; height: 16px;
  line-height: 1; padding: 0; border: none; border-radius: 50%;
  background: #e2e8f0; color: #475569; font-size: 12px; cursor: pointer;
  display: flex; align-items: center; justify-content: center; }
.flt .flt-x:hover { background: #cbd5e1; color: #1e293b; }
.flt .flt-x[hidden] { display: none; }
.flt .flt-in { padding-right: 40px; }     /* 右侧留给：× + 自绘三角形 */

/* 匹配理由：表格里只显示一句话，全文在悬停提示里 */
.qc-why { cursor: help; }

/* 待确认/未找到：报告提取的名称/规格/日期，相符绿、不符红 */
.qc-cmp { margin-top: 3px; display: flex; flex-direction: column; gap: 1px; }
.qc-row { font-size: 11.5px; line-height: 1.45; padding: 0 4px; border-radius: 3px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: help; }
.qc-row .f { display: inline-block; width: 28px; color: var(--muted); }
.qc-row.ok  { background: #dcfce7; color: #15803d; }
.qc-row.ok .f { color: #16a34a; }
.qc-row.bad { background: #fee2e2; color: #b91c1c; }
.qc-row.bad .f { color: #dc2626; }
.qc-row.unk { background: #f1f5f9; color: #64748b; }

/* 送货明细表：固定列宽。
   自动布局下超长内容会把列顶开、撑破页面（规格列表、报告名都可能很长）；
   而 text-overflow:ellipsis 也只有在宽度确定时才生效。 */
.table-scroll table.grid { table-layout: fixed; }
.table-scroll table.grid td { overflow: hidden; }
.table-scroll table.grid td > div { min-width: 0; }

/* 待确认的逐项对照：宽了就截断，绝不撑破单元格 */
.qc-cmp { max-width: 100%; min-width: 0; }
.qc-row { max-width: 100%; }

/* 报告库卡片里的长值截断 */
.report-card .key3 > div > span:last-child {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
/* 每格右侧的「只重抽这一项」小按钮 */
.pick-table .kfix {
  width: 22px; height: 22px; padding: 0; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid transparent; border-radius: 5px; background: transparent;
  color: #64748b; font-size: 16px; font-weight: 600; line-height: 1; cursor: pointer;
  opacity: .85; transition: opacity .12s, background .12s, border-color .12s, color .12s;
}
.pick-table .kfix:hover {
  opacity: 1; background: #fff; border-color: var(--border); color: var(--primary);
}
.pick-table .kfix:disabled { opacity: 1; cursor: default; }

/* 规格片段后面的"共 N 种"小字 */
.qc-row .muted { font-size: 10.5px; opacity: .75; }

/* 报告库：分段按钮（卡片/列表） */
.seg { display: inline-flex; border: 1px solid var(--border); border-radius: 6px;
  overflow: hidden; }
.seg-b { border: none; background: #fff; padding: 5px 10px; font-size: 12px;
  cursor: pointer; color: var(--text); }
.seg-b + .seg-b { border-left: 1px solid var(--border); }
.seg-b.on { background: var(--primary); color: #fff; }
/* 报告库列表视图 */
.rep-table { width: 100%; }
.rep-table tbody tr { cursor: pointer; }
.rep-table tbody tr:hover { background: #eff6ff; }
.rep-table tbody tr.warn-row { background: #fffbeb; }
.rep-table td.ell { max-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }

/* 列表视图：容器退出 CSS 网格。
   .report-grid 是 minmax(168px,1fr) 的网格，表格放进去会被挤进 168px 的格子。 */
.report-grid.list-mode { display: block; }
.rep-table { table-layout: fixed; }   /* max-width:0 截断技巧需要固定布局 */
.rep-table th, .rep-table td { vertical-align: middle; }

/* 列表里的文件类型图标：紧贴文件名，颜色淡一些 */
.rep-table .type-icon { display: inline-flex; vertical-align: -2px;
  margin-right: 5px; color: #64748b; }
.rep-table .type-icon svg { width: 13px; height: 13px; }

/* 列表：文件名列在最后，给宽一些（文件名通常较长） */
.rep-table th:last-child, .rep-table td:last-child { width: 32%; }

/* 匹配报告面板的标题栏：之前没有样式，标题与「关闭」上下堆叠。
   与 .modal > header 对齐：标题靠左、关闭靠右，同一行。 */
.modal > .modal-head, .modal-head {
  display: flex; align-items: center; gap: 10px;
  padding: 13px 16px; border-bottom: 1px solid var(--border);
}
.modal-head h3 { margin: 0; font-size: 14px; flex: 1; }
.modal-head .btn { flex: none; }

/* 匹配按钮里的图标：与文字对齐，比文字略大一点 */
#btnAiMatch svg { vertical-align: -2px; margin-right: 3px; }
#btnAiMatch { display: inline-flex; align-items: center; }

/* AI 提取弹窗：四个关键数字做成大方块，重点一眼可见 */
.ai-stats { display: flex; gap: 8px; margin-bottom: 12px; }
.ai-stat { flex: 1; background: #f8fafc; border: 1px solid var(--border);
  border-radius: 8px; padding: 8px 10px; text-align: center; }
.ai-stat b { display: block; font-size: 20px; line-height: 1.2; }
.ai-stat span { font-size: 11px; color: var(--muted); }
.ai-stat.hot { background: #eff6ff; border-color: #bfdbfe; }
.ai-stat.hot b { color: var(--primary); }
.ai-stat.bad b { color: var(--danger); }
.ai-warn { background: #fffbeb; border: 1px solid #fde68a; border-radius: 8px;
  padding: 8px 10px; font-size: 12px; margin-bottom: 12px; color: #92400e; }
.ai-adv { margin-top: 10px; border-top: 1px solid var(--border); padding-top: 8px; }
.ai-adv summary { cursor: pointer; font-size: 12px; color: var(--muted); }

/* ---------------- 使用日志 ---------------- */
.usage-bar { gap: 10px; }
.usage-bar #usageSearch { flex: 0 1 280px; min-width: 180px; }
.usage-bar #usageHint { white-space: nowrap; }
.usage-user { flex: 0 0 auto; height: 30px; max-width: 190px; padding: 0 8px;
  border: 1px solid var(--border); border-radius: 8px; background: var(--panel);
  color: var(--text); font-size: 12.5px; }
.usage-users { display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  padding: 9px 14px; border-bottom: 1px solid var(--border); background: #fafcff; }
.usage-users .chip { display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--border); background: var(--panel); color: var(--text);
  border-radius: 999px; padding: 3px 10px; font-size: 12px; line-height: 1.6;
  font-family: inherit; }
.usage-users button.chip { cursor: pointer; }
.usage-users button.chip:hover { border-color: var(--primary); color: var(--primary); }
.usage-users .chip.on { border-color: var(--primary); color: var(--primary);
  background: #eff6ff; }
.usage-users .chip .n { color: var(--muted); font-variant-numeric: tabular-nums; }
.usage-users .chip.on .n { color: var(--primary); }

.usage-kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px; margin-bottom: 14px; }
.usage-kpi { min-width: 0; background: var(--panel); border: 1px solid var(--border);
  border-radius: 10px; box-shadow: var(--shadow); padding: 10px 14px 11px; }
.usage-kpi-h { font-size: 12px; color: var(--muted); }
.usage-kpi-v { font-size: 23px; font-weight: 650; line-height: 1.3;
  font-variant-numeric: tabular-nums; letter-spacing: .2px; }
.usage-kpi-s { font-size: 11.5px; color: var(--muted); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.usage-kpi.bad { border-color: #fecaca; background: #fffafa; }
.usage-kpi.bad .usage-kpi-v { color: var(--danger); }

.usage-cols { display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(290px, .75fr);
  gap: 14px; align-items: stretch; margin-bottom: 14px; }
@media (max-width: 1100px) { .usage-cols { grid-template-columns: 1fr; } }

.usage-card { display: flex; flex-direction: column; min-width: 0;
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: var(--shadow); }
.usage-card-h { display: flex; align-items: center; gap: 8px; flex: none;
  padding: 9px 14px; border-bottom: 1px solid var(--border); }
.usage-card-h h3 { margin: 0; font-size: 13px; font-weight: 600; }
.usage-card-h .sub { font-size: 11.5px; color: var(--muted); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.usage-card-h .grow { flex: 1; }
.usage-side { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.usage-side .usage-card { flex: 1; }

/* 每日柱状图 */
.usage-chart-body { display: flex; flex-direction: column; flex: 1;
  padding: 14px 14px 10px; min-height: 190px; }
.usage-bars { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(3px, 1fr);
  gap: 3px; align-items: end; flex: 1; min-height: 130px;
  border-bottom: 1px solid var(--border); padding-bottom: 3px; }
.usage-col { display: flex; flex-direction: column; justify-content: flex-end;
  align-items: center; height: 100%; cursor: default; }
.usage-col i { display: block; width: 100%; max-width: 44px; min-height: 2px;
  border-radius: 3px 3px 0 0; background: linear-gradient(180deg, #60a5fa, #2563eb);
  transition: background .12s; }
.usage-col:hover i { background: #1d4ed8; }
.usage-col.zero i { background: #dbe3ec; }
.usage-axis { display: flex; justify-content: space-between; gap: 8px;
  margin-top: 6px; font-size: 11px; color: var(--muted);
  font-variant-numeric: tabular-nums; }
.usage-chart-empty { display: flex; align-items: center; justify-content: center;
  flex: 1; min-height: 130px; font-size: 12px; color: var(--muted); }

/* 按用途 / 按模型 */
.usage-split { display: flex; flex-direction: column; gap: 11px; padding: 11px 14px 13px; }
.usage-split-row { display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: 2px 10px; width: 100%; padding: 0; border: 0; background: none;
  font: inherit; color: inherit; text-align: left; cursor: pointer; }
.usage-split-row .k { font-size: 12.5px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.usage-split-row .v { font-size: 11.5px; color: var(--muted);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.usage-split-row .tk { grid-column: 1 / -1; font-size: 11px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-variant-numeric: tabular-nums; }
.usage-split-row .bar { grid-column: 1 / -1; height: 5px; border-radius: 3px;
  background: #eef2f7; overflow: hidden; }
.usage-split-row .bar i { display: block; height: 100%; border-radius: 3px;
  background: var(--primary); opacity: .7; transition: opacity .12s; }
.usage-split-row:hover .k, .usage-split-row.on .k { color: var(--primary); }
.usage-split-row:hover .bar i, .usage-split-row.on .bar i { opacity: 1; }
.usage-split-row.on .k { font-weight: 600; }
.usage-empty-sm { padding: 10px 14px 13px; font-size: 12px; color: var(--muted); }

/* 调用明细 / 操作记录 */
.usage-tabs { display: flex; gap: 2px; }
.usage-tabs button { display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 9px; border: 0; border-radius: 6px; background: none;
  color: var(--muted); font-size: 12.5px; cursor: pointer; }
.usage-tabs button:hover { background: #f1f5f9; color: var(--text); }
.usage-tabs button.on { background: #eff6ff; color: var(--primary); font-weight: 600; }
.usage-tabs .cnt { font-size: 11px; font-weight: 400; opacity: .8;
  font-variant-numeric: tabular-nums; }

.usage-filters { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 6px 14px; border-bottom: 1px solid var(--border);
  background: #f8fafc; font-size: 12px; }
.usage-filters .grow { flex: 1; }
.usage-filters .fchip { display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px; border: 1px solid #bfdbfe; border-radius: 999px;
  background: #eff6ff; color: var(--primary); font-size: 11.5px; cursor: pointer; }
.usage-filters .fchip b { font-weight: 400; opacity: .75; }
.usage-filters .fchip:hover { background: #dbeafe; }
.usage-filters .usage-fail { display: inline-flex; align-items: center; gap: 4px;
  white-space: nowrap; }

.usage-scroll { overflow: auto; max-height: 520px; }
.usage-table { table-layout: fixed; }
.usage-table th { position: sticky; top: 0; z-index: 2; white-space: nowrap; }
.usage-table td { vertical-align: middle; }
.usage-table td.ell, .usage-table .nm { overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.usage-table .nm { font-size: 12px; }
.usage-table .sub { font-size: 11px; color: var(--muted); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.usage-table .usage-time { color: var(--muted); white-space: nowrap;
  font-variant-numeric: tabular-nums; }
.usage-table .usage-tk { white-space: nowrap; font-variant-numeric: tabular-nums; }
.usage-table tr.fail td { background: #fff5f5; }
.usage-table tr.usage-fail-note td { padding-top: 2px; padding-bottom: 7px;
  background: #fff5f5; color: var(--danger); font-size: 11.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.usage-table tr.usage-fail-note .badge { margin-right: 5px; }
.usage-empty-row { padding: 28px 10px !important; text-align: center;
  color: var(--muted); }
.usage-table .usage-view { margin-left: 5px; padding: 0; border: 0; background: none;
  color: var(--primary); font-size: 11px; cursor: pointer; }
.usage-table .usage-view:hover { text-decoration: underline; }
.usage-table .usage-view:disabled { color: var(--muted); cursor: default;
  text-decoration: none; }

/* 模型输出弹窗 */
.usage-res-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px;
  margin-bottom: 10px; font-size: 12px; color: var(--muted); }
.usage-res-meta b { color: var(--text); font-weight: 600; }
.usage-res-meta .sep { color: var(--border-strong); }
.usage-res-note { margin-bottom: 10px; padding: 7px 10px; border-radius: 6px;
  background: var(--warn-bg); color: var(--warn); font-size: 12px; }
.usage-result { margin: 0; max-height: 55vh; overflow: auto; padding: 10px 12px;
  background: #f8fafc; border: 1px solid var(--border); border-radius: 8px;
  font: 12px/1.55 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  white-space: pre-wrap; word-break: break-word; }

@media (max-width: 900px) { .usage-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 760px) { .usage-table { min-width: 720px; } }

/* 报告库列表的状态列：图标（形状区分状态，颜色辅助） */
.rep-table .rep-st { display: inline-flex; align-items: center;
  justify-content: center; vertical-align: -3px; }
.rep-table .rep-st.ok { color: #15803d; }
.rep-table .rep-st.err { color: #b91c1c; }
.rep-table .rep-st.run { color: var(--primary); }
.rep-table .rep-st.gray { color: var(--muted); }
/* 文件名列在首位，给足宽度 */
.rep-table th:first-child, .rep-table td:first-child { width: 30%; }
.rep-table th:last-child, .rep-table td:last-child { width: auto; }

/* 卡片状态栏里的状态图标：沿用列表那套形状与配色 */
.card-bar .rep-st { display: inline-flex; align-items: center; vertical-align: -2px; }
.card-bar .rep-st.ok { color: #15803d; }
.card-bar .rep-st.err { color: #b91c1c; }
.card-bar .rep-st.run { color: var(--primary); }
.card-bar .rep-st.gray { color: var(--muted); }

/* 文件类型图标：带颜色，一眼分辨 PDF 与图片（原来是清一色灰） */
/* 注意特异性：卡片里有一条 `.report-card .card-bar .type-icon { color:#475569 }`
   （3 个类），会盖住只有 2 个类的 `.type-icon.t-pdf`，导致卡片上是灰的、列表里却是彩色。
   这里把卡片上下文一并写上，让两处一致。 */
.type-icon.t-pdf, .report-card .card-bar .type-icon.t-pdf { color: #dc2626; background: #fee2e2; }
.type-icon.t-img, .report-card .card-bar .type-icon.t-img { color: #0891b2; background: #cffafe; }
/* 两处共用的底色药丸：让图标本身更醒目 */
.type-icon { display: inline-flex; align-items: center; justify-content: center;
  border-radius: 4px; padding: 1px 3px; }
/* 列表里紧贴文件名，缩小一点内边距免得占宽 */
.rep-table .type-icon { margin-right: 5px; padding: 1px 2px; }

/* 报告详情：预览缩放工具条 */
.zoom-bar { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; }
.zoom-bar .zoom-val { font-size: 12px; color: var(--muted); min-width: 42px;
  text-align: center; font-variant-numeric: tabular-nums; }
/* 用 --z 控制图片宽度：容器自带滚动，缩放不破坏布局 */
#exPreview img { width: calc(100% * var(--z, 1)); max-width: none; }

/* 报告全文：切换按钮与正文同在一个框里，按钮像框内的小工具条 */
.md-box { border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.md-box .md-tools { display: flex; align-items: center; gap: 6px;
  padding: 6px 8px; background: #f8fafc; border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 1; }
.md-box #mdPane { border: none; border-radius: 0; }

/* 结构化字段：修正控件 */
.fix-bar { display: flex; align-items: center; gap: 10px; margin-bottom: 10px;
  padding: 6px 8px; background: #f8fafc; border: 1px solid var(--border);
  border-radius: 8px; }
.fix-bar .chk { display: inline-flex; align-items: center; gap: 3px; cursor: pointer; }
.fix-wrap { position: relative; display: block; }
/* 单个字段的修正按钮：贴在输入框右端 */
.fix-one { position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  width: 20px; height: 20px; border: 1px solid var(--border); border-radius: 5px;
  background: #fff; color: var(--primary); cursor: pointer; font-size: 12px;
  line-height: 1; display: flex; align-items: center; justify-content: center; }
.fix-one:hover { background: #eff6ff; border-color: var(--primary); }
.fix-wrap input { padding-right: 28px; }
/* 破坏性操作（会重构解析数据）用红色 */
.menu .menu-danger { color: var(--danger); }
.menu .menu-danger:hover { background: #fef2f2; }

/* 应用内确认框：替代浏览器原生 confirm */
.ask-body { padding: 4px 0; }
.ask-line { font-size: 13px; line-height: 1.8; color: var(--text); }
.ask-line + .ask-line { margin-top: 4px; color: var(--muted); }

/* 导入：文件选择行 */
.pick-row { display: flex; align-items: center; gap: 10px; }
.pick-row label.btn { margin: 0; }
.pick-name { font-size: 12.5px; color: var(--text); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }

/* 报告库：批量上传 —— 拖放区 + 待传清单 */
.up-drop { display: flex; align-items: center; justify-content: center; gap: 10px;
  padding: 18px 14px; border: 1.5px dashed var(--border, #cbd5e1); border-radius: 8px;
  background: #f8fafc; transition: border-color .12s, background .12s; }
.up-drop.hot { border-color: var(--primary, #1d4ed8); background: #eff6ff; }
.up-drop-hint { font-size: 12.5px; color: var(--muted, #6b7280); }
.up-list { margin-top: 10px; max-height: 220px; overflow: auto;
  border: 1px solid var(--border, #e2e8f0); border-radius: 6px; }
.up-row { display: flex; align-items: center; gap: 8px; padding: 5px 9px;
  font-size: 12.5px; border-bottom: 1px solid #f1f5f9; }
.up-row:last-child { border-bottom: 0; }
.up-name { flex: 1 1 auto; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.up-size { flex: 0 0 auto; color: var(--muted, #6b7280); font-variant-numeric: tabular-nums; }
.up-msg { flex: 0 0 auto; max-width: 45%; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; color: var(--muted, #6b7280); }
.up-ok { flex: 0 0 auto; color: var(--ok, #15803d); font-weight: 700; }
.up-err { flex: 0 0 auto; color: var(--danger, #b91c1c); font-weight: 700; }
.up-busy { flex: 0 0 auto; color: var(--primary, #1d4ed8); font-weight: 700; }
.up-del { flex: 0 0 auto; width: 20px; height: 20px; line-height: 1; padding: 0;
  border: 0; border-radius: 4px; background: transparent; cursor: pointer;
  color: var(--muted, #94a3b8); font-size: 15px; }
.up-del:hover { background: #f1f5f9; color: var(--danger, #b91c1c); }

/* 导入弹窗：内容不多，宽度收到约 2/3（900 → 600） */
.modal.import { width: 600px; }

/* 「选择质检报告」弹窗：1180 → 790（约减 1/3）。候选卡片不需要那么宽。 */
/* 高度固定：切上一条/下一条时候选数量不同，弹窗不该跟着忽高忽低 */
.modal.picker { width: 790px; height: min(86vh, 760px); }
.modal.picker > .content { min-height: 0; }
/* 标题：动作在前，商品名做副标题，别让长名称把标题挤成两行 */
.modal.picker > header h3 { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.modal.picker .qc-sub { font-weight: 400; color: var(--muted); font-size: 12.5px;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 送货上下文（学校/数量）：表格里没有的信息才放这儿 */
.qc-meta { display: flex; gap: 16px; align-items: center; flex-wrap: wrap;
  font-size: 12px; color: var(--muted); margin-bottom: 8px; }
.qc-meta b { color: var(--text); font-weight: 600; }
/* 搜索框和常用词同一行，把高度让给列表 */
.qc-tools { display: flex; gap: 10px; align-items: center; margin-bottom: 2px; }
.qc-tools #qcSearch { flex: 0 0 240px; width: 240px; }   /* 原来是撑满整行，收到一半 */
.qc-tools .chip-row { flex: 0 0 auto; }
.qc-tools .chip-row { flex: 0 1 auto; margin: 0; overflow: hidden; flex-wrap: nowrap; }
.qc-tools .chip { flex: 0 0 auto; white-space: nowrap;   /* 挤窄了也别把「250克」拆成两行 */
  padding: 2px 8px; }
.qc-tools .chip-tip { display: none; }           /* 挤了就省掉这几个字 */
@media (max-width: 860px) {
  .qc-tools { flex-wrap: wrap; }
  .qc-tools .chip-row { flex-wrap: wrap; }
}

/* 选择弹窗：名称/规格/生产 是否相符（对绿错红） */

/* 质检报告列的图标按钮：图标+文字，窄屏只留图标 */
.qc-act { display: inline-flex; align-items: center; gap: 4px; padding: 3px 8px; }
.qc-act svg { flex: none; }

/* 设置页：智能匹配提示词 —— 独立区块，默认展开，一眼能看到 */
.prompt-box {
  margin-top: 16px; padding: 12px 14px; border-radius: 9px;
  background: #f8fafc; border: 1px solid var(--border);
}
.prompt-box .prompt-head {
  display: flex; align-items: baseline; gap: 8px;
  padding-bottom: 6px; border-bottom: 1px solid var(--border); margin-bottom: 4px;
}
.prompt-box .prompt-head b { font-size: 13.5px; }
.prompt-box textarea { background: #fff; }
.prompt-box code {
  background: #e2e8f0; border-radius: 3px; padding: 0 4px; font-size: 11.5px;
}

/* 设置页：分组小节 */
.set-sec { border: 1px solid var(--border); border-radius: 9px; padding: 12px 14px; margin-bottom: 12px; background: #fff; }
.set-sec-h { font-size: 13px; font-weight: 600; color: var(--text); margin-bottom: 10px;
  padding-bottom: 7px; border-bottom: 1px solid var(--border); }
.set-sec details.adv { margin-top: 10px; }
.set-sec details.adv > summary { font-size: 12px; color: var(--primary); cursor: pointer; padding: 3px 0; }
.set-sec details.adv[open] > summary { margin-bottom: 8px; color: var(--text); font-weight: 600; }

/* 设置页：单列，限宽，读起来不散 */
.settings-wrap { max-width: 880px; }
.settings-wrap > .card { margin-bottom: 14px; }
.settings-wrap details.env-card > summary {
  font-size: 13px; font-weight: 600; cursor: pointer; padding: 13px 16px; color: var(--text);
}
.settings-wrap details.env-card[open] > summary { border-bottom: 1px solid var(--border); }
.settings-wrap details.env-card > .body { padding: 12px 16px; }

/* 解析引擎：固定展示，不做可选 */
.fixed-way { background: #f8fafc; border: 1px solid var(--border); border-radius: 8px;
  padding: 10px 12px; margin-bottom: 10px; font-size: 13px; }
.fixed-way b { color: var(--text); }
.fixed-way .muted { margin-left: 8px; }

/* 解析引擎：兜底降级 */
.fallback-way { margin-top: 10px; padding: 10px 12px; border-radius: 8px;
  background: #fffbeb; border: 1px solid #fcd34d; }
.fallback-way-h { font-size: 12.5px; font-weight: 600; color: #b45309; margin-bottom: 6px; }
.fallback-way .fld { margin-bottom: 0; }

/* 打印弹窗：内容不多，宽度收到 1180 → 790（约 1/3） */
.modal.print { width: 790px; }

/* 打印弹窗：送货单与质检报告两个页签，共用范围/打印机/份数 */
.print-tabs { display: flex; gap: 4px; margin: -16px -16px 12px;
  padding: 0 16px; background: #f8fafc; border-bottom: 1px solid var(--border); }
.print-tabs .ptab { border: none; background: none; padding: 9px 14px; cursor: pointer;
  color: var(--muted); border-bottom: 2px solid transparent; font-size: 13px; }
.print-tabs .ptab:hover { color: var(--text); }
.print-tabs .ptab.on { color: var(--primary); border-bottom-color: var(--primary);
  font-weight: 600; background: #fff; }
.print-scope { margin-bottom: 12px; }
.print-shared { display: flex; gap: 10px; align-items: flex-end; margin-top: 14px;
  padding-top: 12px; border-top: 1px dashed var(--border); }
.print-result { margin-top: 14px; }
.print-result:empty { display: none; }

/* 质检报告列：按钮三色对应三种状态（状态文字已去掉） */
.qc-act.ok      { color: #15803d; border-color: #86efac; background: #f0fdf4; }
.qc-act.ok:hover { background: #dcfce7; border-color: #4ade80; }
.qc-act.ask     { color: #b45309; border-color: #fcd34d; background: #fffbeb; }
.qc-act.ask:hover { background: #fef3c7; border-color: #f59e0b; }
.qc-act.miss    { color: #b91c1c; border-color: #fca5a5; background: #fef2f2; }
.qc-act.miss:hover { background: #fee2e2; border-color: #ef4444; }
.qc-act.exempt  { color: var(--muted); border-color: var(--border-strong); background: #f8fafc; }

/* 导入弹窗：下载模板 */
.tmpl-link { color: var(--primary); text-decoration: none; border-bottom: 1px dashed currentColor; }
.tmpl-link:hover { color: var(--primary-dark); }

/* 选择报告弹窗：常用词块，点一下即搜 */
.chip-row { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 10px; min-height: 0; }
.chip-tip { color: var(--muted); font-size: 12px; align-self: center; }
.chip { border: 1px solid var(--border); background: #f8fafc; color: var(--fg);
        border-radius: 999px; padding: 2px 10px; font-size: 12px; cursor: pointer; }
.chip:hover { background: #eef2ff; border-color: #c7d2fe; color: var(--primary); }

/* 菜单栏最右侧：本系统开发方信息（电话悬停才滑出） */
.tabs-brand {
  margin-left: auto; display: flex; align-items: center;
  padding-right: 4px; font-size: 11px; color: var(--muted);
  letter-spacing: .3px; white-space: nowrap;
}
.tabs-brand .dev { cursor: default; }
.tabs-brand .dot, .tabs-brand .tel {
  max-width: 0; opacity: 0; overflow: hidden; margin-left: 0;
  transition: max-width .18s ease, opacity .18s ease, margin-left .18s ease;
}
.tabs-brand .tel { color: var(--muted); text-decoration: none; }
.tabs-brand .tel:hover { color: var(--primary); }
.tabs-brand:hover .dot { max-width: 12px; opacity: .5; margin-left: 4px; }
.tabs-brand:hover .tel { max-width: 110px; opacity: 1; margin-left: 4px; }

/* 剩余质保天数 */
.left-days { font-variant-numeric: tabular-nums; }
.left-days.bad  { color: #b91c1c; font-weight: 600; }
.left-days.soon { color: #b45309; font-weight: 600; }

/* 按学校分开的清单：学校名不折行 */
.nowrap { white-space: nowrap; }

/* ---------- 顶部 AI 进度胶囊 ---------- */
.top-ai {
  display: inline-flex; align-items: center; gap: 8px;
  margin-left: 10px; padding: 2px 10px 2px 8px; border-radius: 999px;
  background: rgba(56, 189, 248, .16); color: #bae6fd; font-size: 12px;
}
.top-ai .bar { width: 64px; height: 5px; border-radius: 3px;
  background: rgba(255,255,255,.22); overflow: hidden; }
.top-ai .bar i { display: block; height: 100%; border-radius: 3px;
  background: linear-gradient(90deg, #38bdf8, #818cf8);
  background-size: 200% 100%; animation: ai-flow 1.2s linear infinite; }
@keyframes ai-flow { from { background-position: 0 0; } to { background-position: 200% 0; } }

/* ---------- 报告解析按钮：进度填充 + 流动条纹 ---------- */
.ai-run { display: inline-flex; align-items: center; gap: 6px; }
.ai-run-btn { position: relative; overflow: hidden; min-width: 132px; }
.ai-run-fill {
  position: absolute; left: 0; top: 0; bottom: 0; width: 0;
  background: rgba(255,255,255,.25); transition: width .4s ease;
}
.ai-run-btn.running .ai-run-fill {
  background-image: repeating-linear-gradient(45deg,
    rgba(255,255,255,.42) 0 7px, rgba(255,255,255,.12) 7px 14px);
  background-size: 20px 20px; animation: ai-stripe .7s linear infinite;
}
@keyframes ai-stripe { from { background-position: 0 0; } to { background-position: 20px 0; } }
.ai-run-label { position: relative; z-index: 1; }
.ai-run-btn.running { animation: ai-pulse 1.6s ease-in-out infinite; }
@keyframes ai-pulse { 0%,100% { box-shadow: 0 0 0 0 rgba(59,130,246,.45); }
                      50% { box-shadow: 0 0 0 4px rgba(59,130,246,0); } }

/* ---------- 底部状态栏 ---------- */
.statusbar {
  position: sticky; bottom: 0; z-index: 4;
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  margin-top: 12px; padding: 7px 14px;
  background: #f8fafc; border-top: 1px solid var(--border);
  font-size: 12px; color: var(--muted);
}
.statusbar b { color: var(--text); font-weight: 600; }
.statusbar .dot { opacity: .4; }
.note-statusbar { margin-top: 0; }
#view-reports .toolbar { position: sticky; top: 0; z-index: 6; background: #fff; }

/* hidden 属性要被 display 规则尊重：.btn{display:inline-flex} 会盖掉 [hidden] */
.btn[hidden], button[hidden] { display: none !important; }
/* 报告库筛选条：别把「状态」「引用」挤成竖排 */
#view-reports .toolbar { flex-wrap: wrap; row-gap: 6px; }
#view-reports .flt { white-space: nowrap; }
#view-reports .flt .sm-select { min-width: 92px; }

/* 送货单主区：内容可滚动，状态栏钉在底部 */
.note-col { flex: 1; min-width: 0; display: flex; flex-direction: column; height: 100%; }
.note-col .note-main { flex: 1; min-height: 0; overflow: auto; }
.note-col .statusbar { flex: none; margin-top: 8px; border-radius: 8px; border: 1px solid var(--border); }

/* 提取弹窗「高级」里的一行 */
.ai-adv-row { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; margin-top: 8px; }
.ai-adv-row .fld { max-width: 150px; margin: 0; }

/* ---------- 质检报告库：两行工具栏 ---------- */
.rep-bar { position: sticky; top: 0; z-index: 6; background: #fff;
  border-bottom: 1px solid var(--border); margin: -4px -4px 10px; padding: 8px 10px 6px; }
.rep-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.rep-row .grow { flex: 1 1 auto; }
.rep-row-main { margin-bottom: 6px; }
.rep-row-main #reportSearch { flex: 1 1 260px; max-width: 420px; min-width: 180px; }
.rep-row-flt { gap: 10px; }
.rep-row-flt .flt { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.rep-row-flt .flt label { font-size: 12px; color: var(--muted); }
.rep-row-flt .sm-select { height: 28px; font-size: 12px; }
.rep-chk { display: inline-flex; align-items: center; gap: 5px; }
.btn.ghost { background: transparent; border-color: transparent; color: var(--muted); }
.btn.ghost:hover { background: #f1f5f9; color: var(--text); }

/* 底部状态栏：左中右三段 */
#repStatusBar { display: flex; align-items: center; gap: 10px; }
#repStatusBar .sb-left { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
#repStatusBar .sb-right { margin-left: auto; display: flex; align-items: center; gap: 8px; }

/* 报告库状态栏里的操作结果（扫描 / 上传 / 智能分析 / 暂停…），8 秒后自动消失 */
#repStatusBar .sb-note {
  max-width: 56vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  padding: 2px 9px; border-radius: 6px; font-size: 12px;
}
#repStatusBar .sb-note.ok  { color: #15803d; background: #f0fdf4; border: 1px solid #bbf7d0; }
#repStatusBar .sb-note.err { color: var(--danger); background: #fef2f2; border: 1px solid #fecaca; }

/* 中间：卡片等高、列表头吸顶 */
.report-grid { display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); }
#view-reports .card > .body { padding: 10px 12px; }
#view-reports table.grid thead th { position: sticky; top: 0; background: #fff; z-index: 2; }

/* ---------- 报告卡片：等高、信息行截断 ---------- */
.report-card { display: flex; flex-direction: column; }
.report-card .thumb { height: 168px; flex: none; }
.report-card .cap { flex: 1; display: flex; flex-direction: column; gap: 2px; }
.report-card .cap .sub { margin-top: 0; }
/* 规格可能很长（多规格列表），压成一行省略号，避免卡片被撑高 */
.report-card .cap .sub, .report-card .cap .nm {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.report-card .cap .nm { max-width: 100%; }

/* ---------- 报告库：滚动时不漏内容 ----------
   .view 有 16px 内边距，吸顶/吸底的元素贴在 padding 以内，
   内容会从它们上下那 16px 的缝隙里露出来。这里把内边距挪到
   内部元素上，让工具栏与状态栏紧贴视口边缘。 */
#view-reports { padding: 0; }
#view-reports .rep-bar { margin: 0; border-bottom: 1px solid var(--border); }
/* 只让卡片/列表切换贴到页面最右边，其他工具栏控件仍保留内边距 */
#view-reports .rep-row-main .seg { margin-right: -10px; }
#view-reports .rep-body { padding: 10px 16px 0; }
#view-reports .rep-foot {
  position: sticky; bottom: 0; z-index: 5;
  background: #fff; border-top: 1px solid var(--border);
  padding: 0 16px;
}

/* ---------- 送货单：日期区间自适应 ----------
   侧栏宽度可拖动（最窄约 200px），两个 date 控件原来固定最小宽度会溢出。 */
.note-dates { display: flex; gap: 6px; margin-top: 8px; }
.note-dates input[type="date"] {
  flex: 1 1 0; min-width: 0; width: auto;          /* 允许压缩 */
  padding: 4px 6px; font-size: 12px;
}
/* WebKit 的日期输入内部是 fixed 宽的分段，给一个上限避免撑破 */
.note-dates input[type="date"]::-webkit-datetime-edit { overflow: hidden; }
.note-dates .btn { flex: none; }
.notes-wrap.collapsed ~ * .note-dates { display: none; }

/* WebKit 的 date 控件内部编辑器有固定最小宽度（约 110px），压不下去——
   侧栏拖窄时只能让它换行，而不是溢出被裁掉。用容器查询按**侧栏自身宽度**判断。 */
.notes-list { container-type: inline-size; }
@container (max-width: 320px) {
  .note-dates { flex-wrap: wrap; }
  .note-dates .btn { flex: 1 1 100%; }        /* 清空独占一行，靠左 */
}
@container (max-width: 258px) {
  .note-dates input[type="date"] { flex: 1 1 100%; }   /* 两个日期各占一行 */
}

/* 侧栏很窄时，标题不要被挤成竖排；按钮整体换行 */
.notes-list h3 { white-space: nowrap; flex-wrap: wrap; row-gap: 6px; }
@container (max-width: 240px) {
  .notes-list h3 { gap: 6px; }
  .notes-list h3 .btn { padding-left: 8px; padding-right: 8px; }
}

/* 送货单筛选：搜索框占主要宽度，其余控件紧凑 */
/* 三个筛选框各自独立，宽度够放一个词就行 */
#noteMain .flt-sm { flex: 0 1 128px; min-width: 96px; }
#noteMain .flt-sm .flt-box { width: 100%; }
#noteMain .flt-sm .flt-in { width: 100%; }

/* ---------- 送货单明细表：列多，横向滚动时表头和操作列留在视野里 ---------- */
#noteMain table.grid th, #noteMain table.grid td {
  white-space: nowrap;
  padding: 5px 6px;
}
#noteMain table.grid thead th {
  position: sticky; top: 0; z-index: 2; background: #fff;
  border-bottom: 1px solid var(--border-strong);
}
/* 最后一列（改/删）贴在右侧，横向滚动也够得着 */
#noteMain table.grid th:last-child, #noteMain table.grid td:last-child {
  position: sticky; right: 0; background: #fff; z-index: 1;
  box-shadow: -6px 0 8px -6px rgba(15,23,42,.18);
}
#noteMain table.grid tbody tr.selected td:last-child { background: #eff6ff; }


/* 质检报告列与操作列一起钉在右侧：横向滚动时"选择报告"始终可点 */
#noteMain table.grid th:nth-last-child(2), #noteMain table.grid td:nth-last-child(2) {
  position: sticky; right: 68px; background: #fff; z-index: 1;
}
#noteMain table.grid tbody tr.selected td:nth-last-child(2) { background: #eff6ff; }
#noteMain table.grid th:last-child, #noteMain table.grid td:last-child { width: 68px; }

/* ---------- 明细表列宽收紧 ---------- */
/* 规格最多 100 克/袋 这种，给 92px 足够，超长省略 */
#noteMain table.grid th:nth-child(5), #noteMain table.grid td:nth-child(5) {
  max-width: 92px; overflow: hidden; text-overflow: ellipsis;
}
/* 质检报告列为图标按钮（文字收进悬停提示），省出约 60px */
#noteMain table.grid .qc-act-t { display: none; }
#noteMain table.grid .qc-act { padding: 3px 6px; }
/* 学校、单位也不用太宽 */
/* 学校名较长：列宽由列定义给足，超长仍省略 */
#noteMain table.grid th:nth-child(3), #noteMain table.grid td:nth-child(3) {
  overflow: hidden; text-overflow: ellipsis;
}

/* 字段选择弹层 */
#noteMain [style*="padding:0 14px 10px"] { position: relative; }
/* 固定在页面上（挂到 body），否则会被卡片的 overflow:hidden 裁掉 */
.cols-pop {
  position: fixed; z-index: 200;
  background: #fff; border: 1px solid var(--border-strong); border-radius: 10px;
  box-shadow: 0 10px 24px rgba(15,23,42,.16); padding: 12px 16px;
  display: grid; grid-template-columns: 1fr;      /* 单列，一行一个字段 */
  gap: 2px; min-width: 190px; max-height: 60vh; overflow: auto;
}
.cols-pop[hidden] { display: none; }
.cols-pop label { display: flex; align-items: center; gap: 7px; font-size: 12.5px;
  white-space: nowrap; padding: 2px 0; cursor: pointer; }
.cols-pop label input { margin: 0; flex: none; }
.cols-pop label[title] { color: var(--muted); }
.cols-acts { grid-column: 1 / -1; display: flex; gap: 8px; padding-top: 10px;
  margin-top: 2px; border-top: 1px dashed var(--border); }

/* 明细表：按声明的列宽渲染（否则浏览器会按内容把列撑开，宽度设了也白设） */
#noteMain table.grid { table-layout: fixed; }
/* 首尾列留出内边距，别贴着卡片边缘 */
#noteMain table.grid th:first-child, #noteMain table.grid td:first-child { padding-left: 12px; }
#noteMain table.grid th:last-child, #noteMain table.grid td:last-child { padding-right: 12px; }
/* 行高再压一点：按钮本身 26px，加上下内边距正好 */
#noteMain table.grid td { padding-top: 4px; padding-bottom: 4px; }
#noteMain table.grid .row-actions { display: flex; gap: 4px; }
#noteMain table.grid .row-actions .btn { padding: 2px 7px; }

/* 学校与商品名称：单行显示，超长省略（悬停可看全文）。
   不换行——行高一乱，整张表就不好扫读了。 */
#noteMain table.grid td.col-school,
#noteMain table.grid td.col-product_name {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 其余文本列仍然单行，避免表格跳高 */
#noteMain table.grid td.col-spec,
#noteMain table.grid td.col-prod_date,
#noteMain table.grid td.col-shelf_life,
#noteMain table.grid td.col-days_left { white-space: nowrap; }

/* 送货单状态栏：左侧状态筛选、中间异常提示、右侧字段 */
#noteStatusBar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
#noteStatusBar .sb-chips { display: flex; gap: 6px; align-items: center; flex-wrap: wrap;
  margin-left: auto; }
.note-statusbar .sb-chip {
  border: 1px solid var(--border); background: #fff; border-radius: 999px;
  padding: 3px 10px; font-size: 12px; color: var(--text); cursor: pointer;
  display: inline-flex; align-items: center; gap: 4px;
}
.note-statusbar .sb-chip:hover { border-color: var(--primary); }
.note-statusbar .sb-chip b { font-weight: 600; }
.note-statusbar .sb-chip.ok b { color: var(--ok); }
.note-statusbar .sb-chip.warn b { color: var(--warn); }
.note-statusbar .sb-chip.bad b { color: var(--danger); }
.note-statusbar .sb-chip.on {
  background: var(--primary); border-color: var(--primary); color: #fff;
}
.note-statusbar .sb-chip.on b { color: #fff; }
#noteStatusBar .sb-mid { flex: 1; min-width: 0; }
#noteStatusBar .grow { flex: 1; }
/* 鼠标停在明细行上时这里显示 商品/规格/生产日期；空着时充当撑开左右的占位 */
#noteStatusBar .sb-hover {
  flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 6px;
  overflow: hidden; white-space: nowrap;
}
#noteStatusBar .sb-hv { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
#noteStatusBar .sb-hv b { font-weight: 600; }
#noteStatusBar .sb-warn { max-width: 46%; }
#noteStatusBar .sb-warn {
  display: inline-block; font-size: 12px; color: #92400e; cursor: pointer;
  background: #fffbeb; border: 1px solid #fde68a; border-radius: 6px;
  padding: 3px 8px; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; max-width: 100%;
}
#noteStatusBar .sb-warn:hover { background: #fef3c7; border-color: #fbbf24; }
/* 定位后闪一下，方便在长表里找到 */
#noteMain tr.flash td { animation: rowflash 1.6s ease-out; }
@keyframes rowflash { 0%,40% { background: #fef9c3; } 100% { background: transparent; } }
#modal tr[data-goto] { cursor: pointer; }
#modal tr[data-goto]:hover { background: #f8fafc; }

/* 状态栏里的匹配进度 */
.note-statusbar .sb-run {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--primary);
}
.note-statusbar .sb-run .sb-bar {
  display: inline-block; width: 120px; height: 6px; border-radius: 3px;
  background: #e2e8f0; overflow: hidden;
}
.note-statusbar .sb-run .sb-bar i {
  display: block; height: 100%; background: var(--primary);
  background-image: linear-gradient(45deg, rgba(255,255,255,.5) 25%, transparent 25%,
    transparent 50%, rgba(255,255,255,.5) 50%, rgba(255,255,255,.5) 75%,
    transparent 75%, transparent);
  background-size: 14px 14px; animation: sb-stripe .7s linear infinite;
  transition: width .3s;
}
@keyframes sb-stripe { from { background-position: 0 0; } to { background-position: 14px 0; } }

/* 状态栏：匹配完成的结果 */
.note-statusbar .sb-done {
  font-size: 12px; color: #15803d; background: #f0fdf4;
  border: 1px solid #bbf7d0; border-radius: 6px; padding: 3px 9px;
}
.note-statusbar .sb-done b { color: #15803d; }

/* 状态栏里的「剩余质保」下拉 */
#noteStatusBar .sb-days {
  width: auto; flex: 0 0 auto;      /* 全局 select 是 100% 宽，这里要收回来 */
  height: 26px; padding: 0 6px; font-size: 12px; border-radius: 999px;
}

/* 表头恒在固定列之上：滚动时右侧"报告/改/删"的单元格不能盖住列名。
   固定列那条规则同时命中了 th，且写在后面，所以这里必须 !important。 */
#noteMain table.grid thead th { z-index: 3 !important; background: #fff; }
#noteMain table.grid thead th:nth-last-child(2),
#noteMain table.grid thead th:last-child { z-index: 4 !important; }
#noteMain table.grid tbody td:nth-last-child(2),
#noteMain table.grid tbody td:last-child { z-index: 1 !important; }

/* 送货单状态栏：胶囊形改成 5px 圆角 */
.note-statusbar .sb-chip { border-radius: 5px; }
#noteStatusBar .sb-days { border-radius: 5px; }
#noteStatusBar .sb-warn { border-radius: 5px; }
#noteStatusBar .sb-run .sb-bar { border-radius: 3px; }
#noteStatusBar .btn { border-radius: 5px; }

/* 送货单列表底部的小结：条数 / 行数 / 合计，筛选后即时跟着变 */
.notes-statusbar {
  flex: none; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 6px 10px; border-top: 1px solid var(--border); background: #f8fafc;
  border-radius: 0 0 var(--r-card, 10px) var(--r-card, 10px);
  font-size: 11.5px; color: var(--muted); min-height: 30px;
}
.notes-statusbar b { color: var(--text); font-weight: 600; }
.notes-statusbar .gap { flex: 1; }
.notes-statusbar .warn { color: var(--warn); }
.notes-statusbar .miss { color: var(--danger); }
.notes-statusbar .amt { color: var(--text); font-variant-numeric: tabular-nums; }

/* 单项重抽：↻ 淡出，原地换成一个细圆环转圈。
   直接转那个箭头字会显得歪（字形本身不在正中，转起来一抖一抖），
   圆环是画出来的、正好居中，看着自然。 */
@keyframes kfix-spin { to { transform: rotate(360deg); } }
.pick-table .kfix.spin { color: transparent; opacity: 1; position: relative; }
.pick-table .kfix .kring {
  position: absolute; inset: 4px; border-radius: 50%;
  border: 2px solid rgba(15, 23, 42, .16);
  border-top-color: var(--primary);
  animation: kfix-spin .7s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .pick-table .kfix .kring { animation-duration: 2.4s; }  /* 关动效的机器上放慢 */
}

/* 选择弹窗头部：标题 + 上/下一条 */
.modal.picker > header { gap: 8px; }
.modal.picker > header .btn { flex: none; }
.modal.picker > header .qc-sub { flex: 1 1 auto; }
.qc-tools #qcAnalyzeAll { flex: none; white-space: nowrap; }

/* 报告库分页（前端渲染上限） */
.rep-more { display: flex; justify-content: center; padding: 14px 0 4px; }

/* ---------- 智能匹配弹窗：结果摘要 ---------- */
.am-result-head {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: 8px 0 10px;
}
.am-stats { display: flex; gap: 8px; flex-wrap: wrap; }
.am-stat {
  min-width: 76px; padding: 7px 10px; border: 1px solid var(--border);
  border-radius: 8px; background: #f8fafc;
}
.am-stat b { display: block; font-size: 19px; line-height: 1.15; font-variant-numeric: tabular-nums; }
.am-stat span { font-size: 12px; color: var(--muted); }
.am-stat.ok b { color: var(--ok); }
.am-stat.warn b { color: var(--warn); }
.am-actions { display: flex; gap: 8px; flex-wrap: wrap; }

.am-rows { margin-top: 4px; }
.am-rows > summary {
  cursor: pointer; color: var(--primary); font-size: 12px; width: fit-content;
  padding: 4px 0;
}
.am-rows > table { margin-top: 6px; }

/* ---------- 智能匹配：方式选择与右侧开始按钮 ---------- */
.am-run-row { display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap; margin-bottom: 8px; }
.am-modes { display: flex; gap: 8px; flex-wrap: wrap; flex: 1 1 420px; }
.am-mode {
  display: flex; align-items: flex-start; gap: 7px; padding: 7px 10px;
  border: 1px solid var(--border); border-radius: 8px; background: #fff;
  cursor: pointer; min-width: 150px;
}
.am-mode:has(input:checked) { border-color: var(--primary); background: #eff6ff; }
.am-mode input { margin-top: 2px; }
.am-mode span { display: flex; flex-direction: column; gap: 2px; }
.am-mode b { font-size: 12.5px; font-weight: 600; }
.am-mode small { color: var(--muted); font-size: 11.5px; line-height: 1.35; }
.am-run-box {
  margin-left: auto; display: flex; flex-direction: column;
  align-items: flex-end; gap: 4px; text-align: right;
}
.am-run-box > .btn { min-width: 108px; }

/* 智能匹配：固定高度，展开明细时只在弹窗内部滚动，不把窗口撑大 */
.modal.match { height: min(88vh, 860px); }
.modal.match > .modal-body { min-height: 0; overflow: auto; }

/* ---------- 单行匹配过程 ---------- */
.proc-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.proc-block {
  border: 1px solid var(--border); border-radius: 8px; background: #f8fafc;
  padding: 9px 10px; font-size: 12px;
}
.proc-block > b { display: block; margin-bottom: 5px; font-size: 12.5px; }
.proc-checks { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.proc-check {
  display: inline-flex; align-items: center; gap: 3px; padding: 3px 7px;
  border: 1px solid var(--border); border-radius: 999px; background: #fff;
  font-size: 11.5px;
}
.proc-check.ok { color: #15803d; border-color: #bbf7d0; background: #f0fdf4; }
.proc-check.bad { color: #b91c1c; border-color: #fecaca; background: #fef2f2; }
.proc-check.na { color: var(--muted); }
.proc-check small { display: none; }
@media (max-width: 600px) {
  .proc-grid { grid-template-columns: 1fr; }
}

/* 左侧送货单卡片：快捷操作 */
.note-card-actions {
  display: flex; gap: 3px; flex-wrap: wrap; margin-top: 7px;
  padding-top: 6px; border-top: 1px dashed var(--border);
}
.note-card-actions button {
  border: 0; background: transparent; color: var(--muted);
  font-size: 11px; padding: 2px 4px; border-radius: 4px; cursor: pointer;
  font-family: inherit;
}
.note-card-actions button:hover { background: #eef2f7; color: var(--primary); }

/* 报告库顶部：字段健康摘要 */
.report-health { margin-bottom: 10px; }
.report-health-box {
  background: #f8fafc; border: 1px solid var(--border); border-radius: 8px;
  padding: 9px 10px;
}

/* 送货单底部状态栏：匹配状态 */
#noteStatusBar .sb-match {
  font-size: 11.5px; color: var(--muted); white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* 报告共用提醒：放在筛选行右侧 */
#noteMain .note-conflict {
  display: inline-block; max-width: 100%; font-size: 12px; color: #92400e;
  cursor: pointer; background: #fffbeb; border: 1px solid #fde68a;
  border-radius: 6px; padding: 3px 8px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; font-family: inherit;
}
#noteMain .note-conflict:hover { background: #fef3c7; border-color: #fbbf24; }

/* 送货单底部状态栏：强制单行；报告信息过长时省略，不换行撑高 */
#noteStatusBar {
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  gap: 8px;
}
#noteStatusBar .sb-hover {
  flex: 1 1 180px;
  min-width: 0;
  overflow: hidden;
}
#noteStatusBar .sb-hv {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#noteStatusBar .sb-chips {
  flex: 0 0 auto;
  flex-wrap: nowrap;
  margin-left: auto;
}
#noteStatusBar .sb-match,
#noteStatusBar .sb-days,
#noteStatusBar #btnColsBar {
  flex: 0 0 auto;
}

/* 送货单底部状态栏：两行布局（上行报告信息，下行筛选与匹配状态） */
#noteStatusBar {
  flex-wrap: wrap;
  min-height: 58px;
  align-content: center;
  row-gap: 3px;
  overflow: visible;
}
#noteStatusBar .sb-hover {
  flex: 1 1 100%;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
}
#noteStatusBar .sb-hv {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#noteStatusBar .sb-chips {
  flex: 0 1 auto;
  flex-wrap: nowrap;
  margin-left: 0;
}
#noteStatusBar .sb-match { margin-left: auto; }

/* 筛选行里的剩余质保/状态胶囊：沿用状态栏样式，但不整行铺开 */
#noteMain .sb-days {
  width: auto;
  flex: 0 0 auto;
  height: 26px;
  padding: 0 6px;
  font-size: 12px;
  border-radius: 5px;
}
#noteMain .sb-chips {
  display: flex;
  gap: 6px;
  align-items: center;
  flex-wrap: wrap;
}
#noteMain .sb-chip {
  border: 1px solid var(--border);
  background: #fff;
  border-radius: 5px;
  padding: 3px 10px;
  font-size: 12px;
  color: var(--text);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
}
#noteMain .sb-chip:hover { border-color: var(--primary); }
#noteMain .sb-chip b { font-weight: 600; }
#noteMain .sb-chip.ok b { color: var(--ok); }
#noteMain .sb-chip.warn b { color: var(--warn); }
#noteMain .sb-chip.bad b { color: var(--danger); }
#noteMain .sb-chip.on {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}
#noteMain .sb-chip.on b { color: #fff; }

/* 打印弹窗：固定高度，展开/收起选项时不改变窗口大小 */
.modal.print {
  height: min(88vh, 860px);
}
.modal.print > .content {
  min-height: 0;
  overflow: auto;
}

/* 打印弹窗：客户端模式隐藏打印机；汇总子项不占空白 */
.modal.print .print-shared[hidden] { display: none !important; }
.modal.print .cover-opts[hidden] { display: none !important; }
.modal.print .print-opts {
  display: grid; grid-template-columns: 1fr 1fr; gap: 2px 16px;
}
.modal.print .checkline { margin-bottom: 6px; }
.modal.print .content { padding-bottom: 8px; }

/* 打印弹窗：比之前矮一些，保持固定高度，内容区内部滚动 */
.modal.print {
  height: min(72vh, 660px);
}

/* 送货单标题后的匹配状态 */
.note-match-state {
  display: inline-block; margin-left: 8px; padding: 2px 7px;
  font-size: 11.5px; color: var(--muted); white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* 送货单标题后的匹配状态：状态色气泡 */
.note-match-state {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--muted);
  background: #f1f5f9;
  border: 1px solid var(--border);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.note-match-state.is-running {
  color: var(--primary);
  background: #eff6ff;
  border-color: #bfdbfe;
}
.note-match-state.is-done {
  color: #15803d;
  background: #f0fdf4;
  border-color: #bbf7d0;
}
.note-match-state.is-cancelled,
.note-match-state.is-interrupted {
  color: #b45309;
  background: #fffbeb;
  border-color: #fde68a;
}
.note-match-state.is-failed,
.note-match-state.is-error {
  color: var(--danger);
  background: #fef2f2;
  border-color: #fecaca;
}

/* 送货单底部状态栏恢复单行 */
#noteStatusBar {
  flex-wrap: nowrap;
  min-height: 0;
  align-content: normal;
  row-gap: 0;
  overflow-x: auto;
  overflow-y: hidden;
}
#noteStatusBar .sb-hover {
  flex: 1 1 auto;
  white-space: nowrap;
}

/* 送货单底部状态栏：固定单行高度 */
#noteStatusBar {
  height: 32px;
  min-height: 32px;
  max-height: 32px;
  padding: 0 14px;
  box-sizing: border-box;
  line-height: 32px;
}
#noteStatusBar .sb-hover { line-height: 32px; }

/* 明细导航：匹配过程 / 编辑明细弹窗共用 */
.item-nav {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-bottom: 10px; padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}
.item-nav span {
  font-size: 12px; color: var(--muted); margin-right: auto;
  font-variant-numeric: tabular-nums;
}

/* 匹配过程弹窗：宽度约为原来 2/3，固定高度 */
.modal.proc {
  width: 790px;
  height: min(56vh, 460px);
}
.modal.proc > .content {
  min-height: 0;
  overflow: auto;
}

/* 报告库：字段健康摘要并入底部状态栏 */
#repStatusBar { flex-wrap: wrap; row-gap: 4px; }
#repStatusBar #reportHealth { flex: 1 1 100%; }
#reportHealth .report-health-box {
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: 0 0 3px;
}

/* 报告库状态栏：可点击的字段筛选项 */
.rep-field-chips { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin-top: 7px; }
.rep-chip {
  border: 1px solid var(--border); background: #fff; color: var(--text);
  border-radius: 999px; padding: 3px 9px; font-size: 11.5px; cursor: pointer;
  font-family: inherit; white-space: nowrap;
}
.rep-chip:hover { border-color: var(--primary); }
.rep-chip b { font-weight: 600; margin-left: 3px; }
.rep-chip.on {
  background: #eff6ff; border-color: var(--primary); color: var(--primary);
}

/* 报告筛选行：缺名称/规格/日期，可组合 */
.rep-field-filters { display: inline-flex; gap: 5px; flex-wrap: wrap; align-items: center; }

/* 报告字段筛选：复选框样式 */
.rep-field-filters { display: inline-flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.rep-field-check {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 12px; color: var(--text); cursor: pointer; white-space: nowrap;
}
.rep-field-check input { margin: 0; accent-color: var(--primary); }
.rep-field-check b { font-weight: 600; color: var(--muted); }

/* 报告字段筛选：复选框做成紧凑的小标签 */
.rep-field-filters {
  display: inline-flex;
  gap: 6px;
  flex-wrap: wrap;
  align-items: center;
}
.rep-field-check {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: #fff;
  font-size: 12px;
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
  line-height: 1.4;
}
.rep-field-check:hover { border-color: var(--primary); }
.rep-field-check input {
  margin: 0;
  accent-color: var(--primary);
  flex: none;
}
.rep-field-check b {
  font-weight: 600;
  color: var(--muted);
  margin-left: 1px;
}
.rep-field-check:has(input:checked) {
  background: #eff6ff;
  border-color: var(--primary);
  color: var(--primary);
}
.rep-field-check:has(input:checked) b { color: var(--primary); }

/* 登录 / 注册 */
.auth-gate {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(160deg, #eef4ff 0%, #f8fafc 55%, #eef7f2 100%);
}
.auth-gate.hidden { display: none; }
.auth-card {
  width: min(92vw, 390px); background: #fff; border: 1px solid var(--border);
  border-radius: 14px; padding: 22px 22px 18px;
  box-shadow: 0 18px 50px rgba(15, 23, 42, .14);
}
.auth-brand {
  font-size: 17px; font-weight: 700; text-align: center; margin-bottom: 16px;
  color: var(--text);
}
.auth-tabs { display: flex; gap: 4px; margin-bottom: 14px; border-bottom: 1px solid var(--border); }
.auth-tab {
  flex: 1; border: 0; background: none; padding: 9px 0; cursor: pointer;
  color: var(--muted); font-size: 13px; border-bottom: 2px solid transparent;
  font-family: inherit;
}
.auth-tab.on { color: var(--primary); border-bottom-color: var(--primary); font-weight: 600; }
.auth-card .fld { margin-bottom: 10px; }
.auth-submit { width: 100%; margin-top: 6px; justify-content: center; }
.auth-msg { min-height: 18px; font-size: 12px; color: var(--danger); margin: 2px 0 4px; }
.auth-note { margin-top: 12px; font-size: 11.5px; color: var(--muted); text-align: center; }
.top-user {
  font-size: 12px; color: var(--muted); white-space: nowrap;
  padding: 3px 8px; border: 1px solid var(--border); border-radius: 999px;
  background: #f8fafc;
}

/* 用户管理 */
.user-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.user-table th, .user-table td {
  border-bottom: 1px solid var(--border); padding: 6px 8px; text-align: left;
}
.user-table th { color: var(--muted); font-weight: 500; }
.user-actions { display: flex; gap: 5px; flex-wrap: wrap; }
.user-create {
  margin-top: 12px; padding-top: 12px; border-top: 1px dashed var(--border);
}
.user-create .btn { margin-top: 8px; }

/* 登录页：企业工作台布局 */
.auth-gate {
  padding: 24px;
  background:
    radial-gradient(1200px 600px at 8% 10%, #dbeafe 0%, transparent 55%),
    radial-gradient(900px 500px at 100% 100%, #dcfce7 0%, transparent 50%),
    #f3f6fb;
}
.auth-shell {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 430px;
  width: min(1060px, 94vw);
  min-height: 560px;
  border-radius: 22px;
  overflow: hidden;
  box-shadow: 0 28px 80px rgba(15, 23, 42, .18);
  background: #fff;
}
.auth-hero {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 46px 48px;
  color: #e2ecff;
  background:
    radial-gradient(700px 400px at 100% 0%, rgba(59,130,246,.38), transparent 60%),
    linear-gradient(145deg, #0b1f38 0%, #12345a 55%, #0e2b4c 100%);
}
.auth-kicker {
  font-size: 11px; letter-spacing: .18em; color: #93c5fd;
  font-weight: 600; margin-bottom: 18px;
}
.auth-hero h1 {
  font-size: clamp(30px, 3.3vw, 42px); line-height: 1.18;
  color: #fff; margin: 0 0 16px; letter-spacing: .02em;
}
.auth-hero p {
  max-width: 380px; margin: 0 0 22px; font-size: 13.5px;
  line-height: 1.8; color: #c7d7ee;
}
.auth-hero ul {
  list-style: none; padding: 0; margin: 0 0 34px;
  display: grid; gap: 10px; font-size: 13px; color: #dbeafe;
}
.auth-hero li::before {
  content: "✓"; display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; margin-right: 8px;
  border-radius: 50%; background: rgba(147,197,253,.16);
  color: #93c5fd; font-size: 11px;
}
.auth-hero-foot {
  font-size: 11.5px; color: #7f9bc0; letter-spacing: .04em;
}
.auth-card {
  width: auto; border: 0; border-radius: 0; box-shadow: none;
  padding: 46px 40px 30px; display: flex; flex-direction: column;
  justify-content: center; background: #fff;
}
.auth-card-title {
  font-size: 22px; font-weight: 700; color: var(--text);
  margin-bottom: 22px; letter-spacing: .01em;
}
.auth-tabs { margin-bottom: 20px; }
.auth-tab { padding: 11px 0; font-size: 13.5px; }
.auth-card .fld { margin-bottom: 14px; }
.auth-card .fld span { font-size: 12px; color: var(--muted); margin-bottom: 5px; }
.auth-card .fld input {
  height: 42px; font-size: 14px; border-radius: 8px; padding: 0 12px;
}
.auth-submit {
  height: 44px; margin-top: 10px; border-radius: 8px;
  font-size: 14px; font-weight: 600;
}
.auth-msg { min-height: 20px; margin: 4px 0 2px; }
.auth-note { margin-top: 16px; font-size: 12px; }

@media (max-width: 820px) {
  .auth-shell { grid-template-columns: 1fr; width: min(480px, 94vw); min-height: 0; }
  .auth-hero { display: none; }
  .auth-card { padding: 34px 26px 24px; }
  .auth-gate { padding: 16px; }
}

/* 登录表单：没有显式 type 的输入框也要占满卡片宽度 */
.auth-card input { width: 100%; }

/* 用户管理：邀请码 */
.user-section-title {
  font-size: 12px; font-weight: 600; color: var(--muted);
  margin-bottom: 8px; letter-spacing: .02em;
}
.reg-code-list { margin-top: 10px; }
.reg-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px; letter-spacing: .04em; color: var(--primary);
  background: #eff6ff; border: 1px solid #bfdbfe; border-radius: 4px;
  padding: 2px 6px;
}
.reg-code-table td { vertical-align: middle; }

/* 设置页：左侧分类导航 + 右侧单面板 */
.settings-wrap {
  max-width: 1080px;
  display: grid;
  grid-template-columns: 176px minmax(0, 1fr);
  gap: 18px;
  align-items: start;
}
.settings-nav {
  position: sticky;
  top: 12px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 8px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow);
}
.settings-nav-b {
  border: 0;
  background: transparent;
  text-align: left;
  padding: 9px 11px;
  border-radius: 6px;
  font-size: 12.5px;
  color: var(--muted);
  cursor: pointer;
  font-family: inherit;
  white-space: nowrap;
}
.settings-nav-b:hover { background: #f1f5f9; color: var(--text); }
.settings-nav-b.on {
  background: #eff6ff;
  color: var(--primary);
  font-weight: 600;
}
.settings-content { min-width: 0; }
.settings-panel { display: none; }
.settings-panel.on { display: block; }
.settings-panel[hidden] { display: none !important; }
.settings-content > .settings-panel + .settings-panel { margin-top: 0; }

@media (max-width: 860px) {
  .settings-wrap { grid-template-columns: 1fr; }
  .settings-nav {
    position: static;
    flex-direction: row;
    overflow-x: auto;
    gap: 4px;
    padding: 6px;
  }
  .settings-nav-b { flex: none; }
}
