:root {
  --bg: #F4F6F9;
  --panel: #FFFFFF;
  --line: #E4E8EE;
  --line-strong: #D2D8E0;
  --text: #1F2328;
  --text-2: #5A626E;
  --text-3: #8A94A6;
  --accent: #185FA5;
  --accent-soft: #E6F1FB;
  --accent-hover: #124B84;
  --danger: #C0392B;
  --danger-soft: #FCEBEB;
  --radius: 10px;
}

* { box-sizing: border-box; }

/* hidden 属性兜底：类上写了 display（如 .topbar/.login-view{display:flex}）会盖过
   浏览器默认样式表的 [hidden]{display:none}（作者样式优先于 UA 样式），
   导致 JS 里 el.hidden=true 却依然显示。用 !important 保证带 hidden 就一定隐藏。 */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: system-ui, -apple-system, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
}

.app { display: flex; min-height: 100vh; }

.sidebar {
  width: 228px;
  flex: 0 0 228px;
  background: linear-gradient(180deg, #24303F 0%, #2C3949 55%, #41505F 100%);
  border-right: 1px solid rgba(255,255,255,.10);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 18px 18px 16px;
  border-bottom: 1px solid rgba(255,255,255,.12);
}

.logo {
  width: 32px; height: 32px;
  border-radius: 9px;
  background: var(--accent);
  color: #fff;
  display: grid; place-items: center;
  font-size: 15px; font-weight: 500;
}

.brand-text { display: flex; flex-direction: column; line-height: 1.3; }
.brand-text strong { font-size: 14px; font-weight: 500; color: #fff; }
.brand-text small { font-size: 11px; color: rgba(255,255,255,.6); }

.brand-acct {
  display: none;   /* 默认隐藏；手机端 media query 里显示在页面右上角 */
  margin-left: auto;
  border: 1px solid var(--line-strong); background: #fff; color: var(--text);
  font: inherit; font-size: 13px; font-weight: 500;
  padding: 7px 14px; border-radius: 999px; cursor: pointer;
}
.brand-acct:hover { border-color: var(--accent); color: var(--accent); }

/* 施工人员（手机端）：本月天数 / 修改密码 / 退出 → 上移到最上方「施工台账」行的最右侧。
   默认隐藏（桌面端仍用右上角账号区），手机端 body.staff-mode 才显示 */
.brand-staff {
  display: none;
  margin-left: auto;
  align-items: center;
  gap: 2px;
}
.brand-staff .account-manage,
.brand-staff .account-logout { font-size: 11.5px; padding: 2px 6px; }
.brand-staff .staff-day-badge { font-size: 11px; padding: 1px 8px; }

.nav { padding: 12px 10px; display: flex; flex-direction: column; gap: 2px; overflow-y: auto; flex: 1; }

.nav button {
  display: flex; align-items: center; gap: 10px;
  width: 100%;
  padding: 9px 12px;
  border: 0; border-radius: 8px;
  background: transparent;
  color: rgba(255,255,255,.82);
  font: inherit; font-size: 13px;
  text-align: left; cursor: pointer;
}

.nav button:hover { background: rgba(255,255,255,.12); color: #fff; }
.nav button.active { background: var(--accent-soft); color: var(--accent); font-weight: 500; }
.nav .mark { width: 4px; height: 14px; border-radius: 2px; background: currentColor; opacity: .35; }
.nav button.active .mark { opacity: 1; }
.nav .count {
  margin-left: auto;
  font-size: 11px;
  color: #2A3340;
  background: rgba(255,255,255,.92);
  border-radius: 20px;
  padding: 1px 8px;
  min-width: 22px; text-align: center;
}
.nav button.active .count { background: #fff; color: var(--accent); }

.nav-group {
  padding: 14px 12px 5px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  color: rgba(255,255,255,.55);
  user-select: none;
}
.nav-group:first-child { padding-top: 4px; }

/* 快速查询：左侧菜单底部可收缩板块 */
.nav-quick { margin-top: 6px; border-top: 1px solid rgba(255,255,255,.12); padding-top: 6px; }
.nav-quick-head {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px; cursor: pointer; user-select: none;
  color: rgba(255,255,255,.82); font-size: 13px; font-weight: 600;
  border-radius: 8px;
}
.nav-quick-head:hover { background: rgba(255,255,255,.12); color: #fff; }
.nav-quick-caret { width: 12px; text-align: center; font-size: 11px; opacity: .7; }
.nav-quick-title { letter-spacing: .02em; }
.nav-quick-body { display: flex; flex-direction: column; gap: 1px; padding: 0 0 2px; }
.nav-quick-item {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 7px 12px 7px 30px; border: 0; border-radius: 8px;
  background: transparent; color: rgba(255,255,255,.82); font: inherit; font-size: 13px;
  text-align: left; cursor: pointer;
}
.nav-quick-item:hover { background: rgba(255,255,255,.12); color: #fff; }
.nav-quick-item.active { background: var(--accent); color: #fff; }
.nav-quick-item.active .nav-quick-item-mark { opacity: .7; }
.nav-quick-item-mark { width: 4px; height: 14px; border-radius: 2px; background: currentColor; opacity: .35; }

/* 命名规范（快速查询 → 命名规范，右侧主界面整页渲染） */
.naming-page { padding: 6px 2px; }
.naming-page .ns-format {
  font-size: 12.5px; color: var(--text-2);
  background: var(--accent-soft, #EEF3FF); border-radius: 8px;
  padding: 8px 12px; margin-bottom: 12px; line-height: 1.6;
}
.naming-page .ns-format code { background: rgba(0,0,0,.05); padding: 1px 5px; border-radius: 4px; font-size: 12px; }

/* 设备编码（快速查询 → 设备编码，按动环厂家分列，Excel 风格黑边网格） */
.devcode-page { padding: 6px 2px; min-width: 0; max-width: 100%; }
.devcode-page .dc-note {
  font-size: 12.5px; color: var(--text-2);
  background: #FFF8E6; border: 1px solid #F0E0B0; border-radius: 8px;
  padding: 8px 12px; margin-bottom: 10px; line-height: 1.6;
}
.devcode-page .dc-toolbar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 10px; }
.devcode-page .dc-add {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  background: #F7F9FC; border: 1px dashed var(--line-strong, #D2D8E0); border-radius: 8px;
  padding: 8px 10px; margin-bottom: 10px;
}
.devcode-page .dc-add .ns-search { flex: 1 1 180px; min-width: 140px; }
.devcode-page .dc-cols { display: flex; gap: 14px; align-items: flex-start; overflow-x: auto; overflow-y: hidden; padding-bottom: 8px; min-width: 0; max-width: 100%; width: 100%; }
.devcode-page .dc-col {
  flex: 0 0 auto; min-width: 420px; max-width: 560px;
  border: 1px solid #2B2B2B; border-radius: 4px; background: #fff; overflow: hidden;
}
.devcode-page .dc-col-head {
  background: #2C3949; color: #fff; font-weight: 600; font-size: 13.5px;
  padding: 8px 12px; letter-spacing: .02em;
}
.devcode-page .dc-table { width: 100%; border-collapse: collapse; }
.devcode-page .dc-table th, .devcode-page .dc-table td {
  border: 1px solid #2B2B2B; padding: 0; font-size: 12.5px; vertical-align: middle;
}
.devcode-page .dc-table th {
  background: #F2F2F2; color: #222; font-weight: 600;
  padding: 5px 8px; text-align: left; white-space: nowrap;
}
.devcode-page .dc-table th.dc-act-h { width: 1%; }
.devcode-page .dc-inp {
  width: 100%; border: none; background: transparent; padding: 5px 7px;
  font: inherit; font-size: 12.5px; color: #111; box-sizing: border-box;
}
.devcode-page .dc-inp:focus { outline: 2px solid var(--accent); outline-offset: -2px; background: #fff; }
/* 设备编码：列头厂家下拉（深色底白字）+ 单元格类型下拉（白底带箭头） */
.devcode-page .dc-col-head select.dc-mfr-sel {
  width: 100%; border: none; background: #2C3949 url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6'><path d='M0 0l5 6 5-6z' fill='%23ffffff'/></svg>") no-repeat right 8px center;
  color: #fff; font: inherit; font-weight: 600; font-size: 13.5px; padding: 6px 22px 6px 8px;
  box-sizing: border-box; cursor: pointer; letter-spacing: .02em;
}
.devcode-page .dc-col-head select.dc-mfr-sel option { color: #111; background: #fff; }
.devcode-page .dc-table select.dc-inp {
  cursor: pointer; -webkit-appearance: none; -moz-appearance: none; appearance: none;
  background: #fff url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6'><path d='M0 0l5 6 5-6z' fill='%23666'/></svg>") no-repeat right 6px center;
  padding-right: 20px;
}
.devcode-page .dc-add select.ns-search { flex: 1 1 180px; min-width: 140px; }
.devcode-page .dc-table td.dc-act { white-space: nowrap; text-align: center; padding: 3px 5px; }
.devcode-page .dc-copy {
  background: #07c160; color: #fff; border: none; border-radius: 4px;
  padding: 3px 9px; font-size: 12px; cursor: pointer;
}
.devcode-page .dc-copy:hover { background: #06ad56; }
.devcode-page .dc-del {
  background: #fff; color: #C8161D; border: 1px solid #E8B4B4; border-radius: 4px;
  padding: 3px 9px; font-size: 12px; cursor: pointer; margin-left: 4px;
}
.devcode-page .dc-del:hover { background: #FDECEC; }
.devcode-page .dc-row-add {
  width: 100%; border: none; border-top: 1px dashed #9aa; background: #FAFAFA;
  color: #2C3949; padding: 7px; font-size: 12.5px; cursor: pointer;
}
.devcode-page .dc-row-add:hover { background: #F0F0F0; }
.devcode-page .dc-empty { color: var(--text-3); padding: 24px 8px; }
/* 设备编码：列头按钮（弹出 + 复制本列） */
.devcode-page .dc-col-head-row { display: flex; align-items: center; gap: 6px; }
.devcode-page .dc-col-head-row .dc-mfr-sel { flex: 1; min-width: 0; }
.devcode-page .dc-pop {
  flex: none; border: 0; border-radius: 4px; padding: 4px 8px;
  font-size: 12px; cursor: pointer; white-space: nowrap; line-height: 1.3;
  background: rgba(255, 255, 255, .18); color: #fff;
}
.devcode-page .dc-pop:hover { background: rgba(255, 255, 255, .32); }
/* 设备编码：单个厂家浮窗 */
.modal.dc-popup-modal { max-width: 560px; }
.dc-popup-body { padding-bottom: 12px; }
.dc-popup-list { display: flex; flex-direction: column; gap: 8px; }
.dc-popup-row {
  border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px;
  background: #FBFCFE;
}
.dc-popup-meta { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 5px; align-items: center; }
.dc-popup-cat { font-size: 12.5px; font-weight: 600; color: #111; }
.dc-popup-brand {
  font-size: 12px; color: #111; font-weight: 500;
  background: #EAF2FD; border: 1px solid #C7DDF7; border-radius: 4px;
  padding: 1px 7px; line-height: 1.5;
}
.dc-popup-model { font-size: 12px; color: #111; }
.dc-popup-code-row { display: flex; align-items: center; gap: 10px; }
.dc-popup-code {
  flex: 1; min-width: 0; font-size: 14px; font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  color: #1a5fbf; word-break: break-all;
}
.dc-popup-copy {
  flex: none; border: 0; border-radius: 5px; background: #07c160; color: #fff;
  padding: 4px 10px; font-size: 12px; cursor: pointer;
}
.dc-popup-copy:hover { background: #06ad56; }
.naming-page .ns-toolbar {
  display: flex; align-items: center; gap: 8px; margin-bottom: 10px; flex-wrap: wrap;
}
.naming-page .ns-tab {
  border: 1px solid var(--line, #ECEFF3); background: #fff; color: var(--text-2);
  padding: 4px 12px; border-radius: 20px; font: inherit; font-size: 12.5px; cursor: pointer;
}
.naming-page .ns-tab.active { background: var(--accent, #2F6BFF); color: #fff; border-color: var(--accent, #2F6BFF); }
.naming-page .ns-search {
  flex: 1; min-width: 140px; padding: 6px 10px; border: 1px solid var(--line, #ECEFF3);
  border-radius: 8px; font: inherit; font-size: 13px;
}
.naming-page .ns-table-wrap { max-height: 64vh; overflow: auto; border: 1px solid var(--line, #ECEFF3); border-radius: 8px; }
.naming-page .ns-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.naming-page .ns-table th {
  position: sticky; top: 0; background: #F7F9FC; text-align: left;
  padding: 8px 12px; font-weight: 600; color: var(--text-3); font-size: 12px;
  border-bottom: 1px solid var(--line, #ECEFF3); z-index: 1;
}
.naming-page .ns-table td { padding: 7px 12px; border-bottom: 1px solid rgba(0,0,0,.06); vertical-align: middle; }
.naming-page .ns-table tbody tr:hover { filter: brightness(0.965); }
.naming-page .ns-table tbody tr:hover .ns-edit { border-color: rgba(0,0,0,.18); }
.naming-page .ns-mfr { color: var(--text); font-weight: 600; white-space: nowrap; width: 1%; font-size: 12.5px; }
.naming-page .ns-name-cell { width: 100%; }
.naming-page .ns-edit-wrap { display: inline-flex; align-items: stretch; gap: 0; width: auto; }
.naming-page .ns-edit {
  flex: 0 1 auto; min-width: 140px; width: auto;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px; color: var(--text);
  padding: 5px 8px; border: 1px solid var(--line, #ECEFF3); border-radius: 6px 0 0 6px;
  background: #fff;
}
.naming-page .ns-edit:focus { outline: none; border-color: var(--accent, #2F6BFF); box-shadow: 0 0 0 2px rgba(47,107,255,.12); }
.naming-page .ns-copy { flex: 0 0 auto; margin-left: -1px; border-radius: 0 6px 6px 0; background: #07c160; border-color: #07c160; color: #fff; font-weight: 600; }
.naming-page .ns-copy:hover { background: #06ad56; border-color: #06ad56; }
.naming-page .ns-table tbody tr:hover .ns-copy { visibility: visible; }
.naming-page .ns-act { width: 1%; white-space: nowrap; text-align: right; }
.naming-page .btn.tiny { padding: 3px 10px; font-size: 12px; }
.naming-page .ns-add { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; padding: 10px 12px; margin: 8px 0; background: rgba(47,107,255,.05); border: 1px dashed var(--line-strong, #D6DCE4); border-radius: 8px; }
.naming-page .ns-add .ns-search { flex: 1 1 150px; min-width: 130px; }
.naming-page .ns-add select.ns-search { flex: 0 1 150px; }

.sidebar-foot {
  padding: 12px 18px;
  border-top: 1px solid rgba(255,255,255,.12);
  font-size: 11px; color: rgba(255,255,255,.55);
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}
.foot-status { display: inline-flex; align-items: center; gap: 6px; }
/* 侧栏底部 ICP 备案号（2026-11-05）：独占一行，可点击跳转工信部 */
.beian-link {
  flex: 1 0 100%;
  color: rgba(255,255,255,.62); text-decoration: none;
  font-size: 11px; line-height: 1.6; letter-spacing: .2px;
}
.beian-link:hover { color: #fff; text-decoration: underline; }
/* 登录页底部备案号：未登录访客（含管局核查）看到的就是这一页 */
.login-beian {
  margin-top: 18px; padding-top: 14px;
  border-top: 1px solid var(--line);
  text-align: center;
}
.login-beian a {
  font-size: 12px; color: var(--text-3); text-decoration: none; letter-spacing: .3px;
}
.login-beian a:hover { color: var(--text); text-decoration: underline; }
.dot { width: 6px; height: 6px; border-radius: 50%; background: #1D9E75; }

.main { flex: 1; min-width: 0; padding: 22px 26px 32px; }

.topbar {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 16px;
}
.titles h1 { margin: 0; font-size: 19px; font-weight: 500; }
.titles p { margin: 4px 0 0; font-size: 12px; color: var(--text-3); }

.actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

.search {
  display: flex; align-items: center; gap: 7px;
  background: #fff;
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  padding: 0 10px;
  height: 34px;
}
.search input {
  border: 0; outline: 0; background: transparent;
  font: inherit; font-size: 13px; width: 190px; color: var(--text);
}
.search input::-webkit-search-cancel-button { -webkit-appearance: none; }

.btn {
  height: 34px; padding: 0 14px;
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  background: #fff; color: var(--text);
  font: inherit; font-size: 13px; cursor: pointer;
  transition: .12s;
}
.btn:hover { border-color: #B9C2CE; background: #FAFBFC; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn.ghost { border-color: transparent; color: var(--text-2); }
.btn.ghost:hover { background: #EDF0F4; }
.btn.danger { color: var(--danger); border-color: #EFCDCA; background: #fff; }
.btn.danger:hover { background: var(--danger-soft); }

.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

.btn.btn-sm { height: 28px; padding: 0 10px; font-size: 12.5px; }

/* hidden 属性优先级：这些类自带 display，必须显式覆盖才能被 hidden 隐藏 */
.home-view[hidden], .body-row[hidden], .detail-view[hidden],
.search[hidden], .btn[hidden] { display: none; }

/* ---------- 首页 ---------- */
.home-view { display: flex; flex-direction: column; gap: 16px; min-width: 0; }

.home-stats { display: flex; gap: 12px; flex-wrap: wrap; }
.home-stat {
  flex: 1 1 150px; min-width: 130px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 12px 16px;
  display: flex; flex-direction: column; gap: 4px;
  cursor: pointer; text-align: left; font: inherit; transition: .12s;
}
.home-stat:hover { border-color: var(--accent); background: var(--accent-soft); }
.home-stat-action { border-color: var(--accent); background: var(--accent-soft); }
.home-stat-action:hover { background: #DEEDFC; }
.home-stat-action .home-stat-num { color: var(--accent); }
.home-stat-num { font-size: 22px; font-weight: 600; color: var(--text); line-height: 1.1; }
.home-stat-label { font-size: 14px; font-weight: 700; color: var(--accent); }
/* 账单汇总卡（原「智能设备」卡位）：净额大字 + 总支出/总收入小字 */
.bill-stat { gap: 2px; }
.bill-net { font-size: 22px; font-weight: 600; color: var(--text); line-height: 1.15; font-variant-numeric: tabular-nums; }
.bill-net.neg { color: #C0392B; }
.bill-sub { display: flex; gap: 10px; font-size: 12px; font-weight: 400; font-variant-numeric: tabular-nums; }
.bill-sub .out { color: #C0392B; }
.bill-sub .in { color: #1E8449; }
/* 施工日志卡上的「点击添加」：做成醒目的实体小按钮 */
.home-stat-add {
  margin-top: 4px; align-self: flex-start;
  background: var(--accent); color: #fff; border-radius: 8px;
  padding: 6px 14px; font-size: 14px; font-weight: 600;
  display: inline-flex; align-items: center; gap: 4px;
  box-shadow: 0 1px 3px rgba(24, 95, 165, .28);
}
.home-stat-action:hover .home-stat-add { background: #1668B4; }
/* 首页顶部地区条 */
.home-citybar {
  display: flex; align-items: center; gap: 10px; margin-bottom: 12px;
  padding: 10px 14px; background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--radius);
}
.home-citybar b { font-size: 15px; color: var(--accent); }
.home-citybar .mini { margin-left: auto; }
.photo-home-tip { margin-left: auto; font-size: 12px; color: var(--text-3); }
/* 拍照账号首页：四个拍照上传入口大卡片（手机端为主，桌面端两列） */
.photo-home {
  display: grid; grid-template-columns: 1fr 1fr; gap: 12px;
}
@media (max-width: 720px) { .photo-home { grid-template-columns: 1fr; } }
.photo-card {
  display: flex; align-items: center; gap: 14px; text-align: left; font: inherit;
  background: var(--panel); border: 1px solid var(--accent); border-radius: 14px;
  padding: 18px 16px; cursor: pointer; transition: .14s;
  box-shadow: 0 1px 4px rgba(24, 95, 165, .12);
}
.photo-card:hover { background: var(--accent-soft); }
.photo-card:active { transform: scale(.99); }
.photo-ico {
  flex: none; width: 46px; height: 46px; border-radius: 12px;
  display: flex; align-items: center; justify-content: center; font-size: 24px;
  background: var(--accent-soft); border: 1px solid var(--line);
}
.photo-body { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.photo-body b { font-size: 16px; color: var(--text); display: flex; align-items: center; gap: 8px; }
.photo-count {
  font-style: normal; font-size: 12px; font-weight: 600; color: var(--accent);
  background: var(--accent-soft); border-radius: 999px; padding: 1px 9px;
}
.photo-body small { font-size: 12px; color: var(--text-3); line-height: 1.5; }
/* 地区选择页（新首页）：大按键 */
.city-wrap { padding: 8px 0 4px; }
.city-title { font-size: 15px; color: var(--text-2); margin-bottom: 14px; }
.city-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 16px; }
.city-card {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  min-height: 120px; padding: 18px; cursor: pointer; font: inherit;
  background: var(--panel); border: 1px solid var(--accent); border-radius: 14px;
  box-shadow: 0 1px 4px rgba(24, 95, 165, .12); transition: .14s;
}
.city-card:hover { background: var(--accent-soft); transform: translateY(-2px); }
.city-ico { font-size: 26px; color: var(--accent); }
.city-name { font-size: 20px; font-weight: 600; color: var(--accent); letter-spacing: 2px; }
.city-tag { font-size: 12px; color: var(--text-3); }
/* 地区账号：自己的地区高亮，其它地区置灰不可点 */
.city-card.mine { border-width: 2px; box-shadow: 0 2px 10px rgba(24, 95, 165, .22); }
.city-card.disabled {
  cursor: not-allowed; border-color: var(--line-strong);
  box-shadow: none; background: #FAFBFC; opacity: .75;
}
.city-card.disabled:hover { transform: none; background: #FAFBFC; }
.city-card.disabled .city-ico,
.city-card.disabled .city-name { color: var(--text-3); }
.city-tag.lock { color: var(--danger); }
.city-empty { color: var(--text-3); font-size: 13px; padding: 20px; }
@media (max-width: 620px) {
  .city-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 12px; }
  .city-card { min-height: 104px; }
  .city-name { font-size: 18px; }
}
/* 首页·当月施工日历卡
   2026-10-27（142）：原来 flex:3 抢宽度，一屏能撑到 900+px，7 列摊得很开显得空；
   改成固定约 480px（原来的一半），富余宽度让给旁边的数据卡。 */
.home-cal {
  flex: 0 1 480px; min-width: 280px; max-width: 100%;
  background: var(--panel); border: 1px solid var(--accent);
  border-radius: var(--radius); padding: 12px 16px;
  display: flex; flex-direction: column; gap: 8px;
}
.home-cal-head { display: flex; align-items: center; gap: 10px; }
.home-cal-head b { font-size: 14px; color: var(--accent); flex: none; }
.home-cal-head .mini { margin-left: auto; }
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; }
.cal-wd { font-size: 11px; color: var(--text-3); text-align: center; }
.cal-cell {
  position: relative; text-align: center; font-size: 12.5px; color: var(--text-2);
  padding: 4px 0; border-radius: 6px; line-height: 1.2;
}
.cal-cell.pad { visibility: hidden; }
/* 可点选的日期：手机上手指目标放大一点，悬停/按下给反馈 */
.cal-cell.pick { cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent; }
.cal-cell.pick:hover { background: var(--accent-soft); color: var(--accent); }
.cal-cell.pick.has-log:hover { background: #178A42; color: #fff; }
/* 选中态：深色描边 + 底部加粗横线（与「只看这天」呼应）；
   has-log 自带绿底，所以选中用描边而非改背景，两种状态能同时看清 */
.cal-cell.pick.sel { box-shadow: inset 0 0 0 2px var(--accent); color: var(--accent); font-weight: 700; }
.cal-cell.pick.sel.has-log { color: #fff; box-shadow: inset 0 0 0 2px #0B5C2E; }
/* 有施工的日子：绿色底 + 次数角标 */
.cal-cell.has-log { background: #1F9D4D; color: #fff; font-weight: 600; }
.cal-cell.has-log i {
  position: absolute; top: -4px; right: -2px; font-style: normal;
  background: #fff; color: #1F9D4D; border: 1px solid #1F9D4D;
  font-size: 9.5px; line-height: 1; border-radius: 999px; padding: 1px 4px;
}
/* ============ 184 · 首页日历「仓库人员施工」高亮（2026-10-30） ============
   某天有仓库人员施工 → 格子底色换成该人员颜色（单人纯色、多人按人切分渐变条带），
   --wh 由 JS 按天写入（自定义属性，便于 hover 用 filter 统一压暗）。
   刻意用红/蓝/紫/橙/青/粉等区别于「有施工」的绿色，图例见 .cal-legend。 */
.cal-cell.wh-day { background: var(--wh); color: #fff; font-weight: 600; text-shadow: 0 0 3px rgba(0,0,0,.5); }
.cal-cell.wh-day:hover { filter: brightness(.92); }
.cal-cell.wh-day i {
  position: absolute; top: -4px; right: -2px; font-style: normal;
  background: #fff; color: #222; border: 1px solid rgba(0,0,0,.25);
  font-size: 9.5px; line-height: 1; border-radius: 999px; padding: 1px 4px;
}
/* 仓库人员图例（色块 + 姓名） */
.cal-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; font-size: 11.5px; color: var(--text-2); margin-top: 2px; }
.cal-legend .wh-leg { display: inline-flex; align-items: center; gap: 4px; }
.cal-legend .wh-leg i { width: 11px; height: 11px; border-radius: 3px; display: inline-block; }
/* 全年弹层里的图例：居中、稍大一点 */
.cal-legend-year { justify-content: center; font-size: 12.5px; margin: 0 0 10px; }

/* 全年日历弹层 */
.cal-year-view {
  position: fixed; inset: 0; background: rgba(15, 30, 45, .45); z-index: 90;
  display: flex; align-items: center; justify-content: center; padding: 20px;
}
.cal-year-box {
  background: var(--panel); border-radius: 12px; padding: 16px 20px;
  width: min(920px, 96vw); max-height: 90vh; overflow: auto;
}
.cal-year-head { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.cal-year-head b { font-size: 16px; color: var(--accent); }
.cal-year-close { margin-left: auto; }
.cal-year-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 14px; }
.cal-month b { display: block; font-size: 12.5px; color: var(--text-2); margin-bottom: 6px; }

.home-grid {
  display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: 16px; align-items: start;
}
@media (max-width: 1000px) { .home-grid { grid-template-columns: 1fr; } }

.home-card {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 0 0 6px;
  display: flex; flex-direction: column; min-height: 0;
}
.home-card-head {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 14px 8px; border-bottom: 1px solid var(--line);
}
.home-card-head h3 { margin: 0; font-size: 15px; font-weight: 600; }
.home-count { font-size: 12px; color: var(--text-3); }
.home-card-head .btn { margin-left: auto; }

/* 待办清单板块：灰蓝底色（参考色 #7A8C99），深色底上标题转白以保证可读 */
.home-card-todo { background: #7A8C99; border-color: #6E8090; }
.home-card-todo .home-card-head { border-bottom-color: rgba(255,255,255,.18); }
.home-card-todo .home-card-head h3 { color: #fff; }
.home-card-todo .home-count { color: rgba(255,255,255,.82); }

.home-tabs { display: flex; gap: 4px; margin-left: 6px; }
.home-tabs .tab {
  border: 1px solid var(--line-strong); background: #fff; color: var(--text-2);
  border-radius: 6px; padding: 3px 9px; font: inherit; font-size: 12px; cursor: pointer;
}
.home-tabs .tab:hover { background: #F4F6F9; }
.home-tabs .tab.active { background: var(--accent); border-color: var(--accent); color: #fff; }

/* 待办快速添加 */
.todo-quick { display: flex; gap: 8px; padding: 10px 16px 4px; flex-wrap: wrap; }
.todo-sel {
  height: 30px; max-width: 180px; padding: 0 6px;
  border: 1px solid var(--line-strong); border-radius: 7px;
  background: #fff; font: inherit; font-size: 12.5px;
  color: var(--text-2); outline: 0; cursor: pointer;
}
.todo-sel:focus { border-color: var(--accent); }
.todo-quick input {
  flex: 1; height: 30px; padding: 0 10px;
  border: 1px solid var(--line-strong); border-radius: 7px;
  font: inherit; font-size: 13px; color: var(--text); outline: 0;
}
.todo-quick input:focus { border-color: var(--accent); }

.todo-list { list-style: none; margin: 0; padding: 6px 8px 8px; overflow: auto; }
.todo-empty { padding: 22px 8px; text-align: center; color: var(--text-3); font-size: 12.5px; }
.todo-item {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 10px; margin-bottom: 4px;
  border: 1px solid #AEB6C2; border-radius: 8px; background: #fff;
}
.todo-item:last-child { margin-bottom: 0; }
.todo-item:hover { background: #FAFCFE; }
.todo-item.done .todo-title { color: var(--text-3); text-decoration: line-through; }
/* 待办底色：置顶=红、遗留转来=橙（标记类写在 li 上，rounded 与 hover 一致） */
.todo-item.pin-bg { background: #FDECEC; border-radius: 8px; }
.todo-item.pin-bg:hover { background: #FAD9D9; }
.todo-item.pin-bg .todo-ops .mini.pin { color: #B42318; background: #FBD5D5; border-color: #F0B4B4; }
.todo-item.legacy-bg { background: #FFF3E0; border-radius: 8px; }
.todo-item.legacy-bg:hover { background: #FFE9CC; }
.todo-item.legacy-bg .todo-ops .mini.pin { color: #C0791F; background: #FFE2B8; border-color: #F0D3A6; }
.todo-check {
  flex: none; width: 18px; height: 18px;
  border: 1.5px solid var(--line-strong); border-radius: 50%;
  background: #fff; cursor: pointer; font-size: 11px; line-height: 1;
  color: #fff; padding: 0; display: flex; align-items: center; justify-content: center;
}
.todo-check:hover { border-color: var(--accent); }
.todo-check.on { background: var(--accent); border-color: var(--accent); }
/* 单行排布：归属 + 标题 + 进度信息 三个块横排，整体不换行 */
.todo-main {
  flex: 1; min-width: 0; display: flex; flex-wrap: nowrap;
  align-items: center; gap: 6px; overflow: hidden;
}
.todo-title {
  font-size: 13px; line-height: 1.5; flex: 1 1 auto; min-width: 30px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 由遗留问题转入的待办：标题前的小旗（配合橙底） */
.todo-flag { margin-right: 4px; font-size: 12px; cursor: help; }
/* 进度信息（进行中/截止/负责人/工单/备注）：同一行右排，空间不足时整块裁掉，不换行 */
.todo-meta {
  display: flex; flex: 0 1 auto; gap: 8px; max-width: 46%;
  font-size: 11.5px; color: var(--text-3);
  white-space: nowrap; overflow: hidden;
}
.todo-meta > span { flex: none; }
/* 归属：紧急程度 + 区域 + 服务对象（与标题同一行） */
.todo-tags {
  display: inline-flex; flex: none; align-items: center; gap: 6px;
  font-size: 11.5px; color: var(--text-3); white-space: nowrap;
}
.todo-meta .link { cursor: pointer; }
.todo-prio {
  padding: 0 6px; border-radius: 5px; font-size: 11px; line-height: 17px;
  background: #EEF1F5; color: var(--text-2);
}
.todo-prio.prio-高 { background: #FDECEA; color: var(--danger); }
.todo-prio.prio-中 { background: #FFF4E0; color: #B26A00; }
.todo-prio.prio-低 { background: #EAF3FF; color: var(--accent); }
.todo-doing { color: var(--accent); }
.todo-due.overdue { color: var(--danger); }
.todo-remark {
  max-width: 34%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 待办行尾「记录日期」：独立于主行之外，靠右显示，不会被标题省略号裁掉 */
.todo-date { flex: none; white-space: nowrap; font-size: 11.5px; color: var(--text-3); padding: 0 4px; }
.todo-ops { flex: none; display: flex; gap: 4px; opacity: .55; }
.todo-item:hover .todo-ops { opacity: 1; }
/* 上下移动 / 紧急置顶 小箭头 */
.todo-ops .mini.move, .todo-ops .mini.pin {
  padding: 1px 6px; font-size: 12px; line-height: 1.4; min-width: 22px;
}
.todo-ops .mini.pin { color: var(--text-3); }
.todo-ops .mini.pin.on { color: #C0791F; background: #FFF3E0; border-color: #F0D3A6; }
/* 手机端：单行已经很挤，操作按钮收紧，把宽度留给标题 */
@media (max-width: 620px) {
  .todo-list { padding: 4px 6px 6px; }
  .todo-item { gap: 6px; padding: 4px 6px; }
  .todo-main { gap: 5px; }
  .todo-meta { max-width: 40%; gap: 6px; }
  .todo-ops { gap: 3px; }
  .todo-ops .mini { padding: 1px 4px; font-size: 11px; min-width: 18px; }
}

/* ---------- 下单人：从服务对象联系人里挑 ---------- */
.cp-row { display: flex; flex-direction: column; gap: 6px; }
.cp-row .cp-sel {
  height: 30px; padding: 0 6px;
  border: 1px solid var(--line-strong); border-radius: 7px;
  background: #fff; font: inherit; font-size: 12.5px;
  color: var(--text-2); outline: 0; cursor: pointer;
}
.cp-row .cp-sel:focus { border-color: var(--accent); }
.cp-row input[type="text"] {
  height: 30px; padding: 0 8px;
  border: 1px solid var(--line-strong); border-radius: 7px;
  font: inherit; font-size: 13px; color: var(--text); outline: 0;
}
.cp-row input[type="text"]:focus { border-color: var(--accent); }
.cp-row .hint { margin: 0; font-size: 11.5px; }

/* ---------- 服务对象「三方」快捷行（填工单：选「三方」后多出来的那一行） ---------- */
.cat-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 8px; padding: 8px 10px;
  background: var(--accent-soft); border: 1px dashed #B9D6F2; border-radius: 8px;
}
.cat-row[hidden] { display: none !important; }
.cat-row .cat-label {
  flex: none; font-size: 12px; font-weight: 700; color: var(--accent);
  white-space: nowrap;
}
.cat-row .cat-sel {
  flex: 1; min-width: 160px; height: 30px; padding: 0 6px;
  border: 1px solid var(--line-strong); border-radius: 7px;
  background: #fff; font: inherit; font-size: 13px; color: var(--text); outline: 0; cursor: pointer;
}
.cat-row .cat-sel:focus { border-color: var(--accent); }
.cat-row .hint { flex-basis: 100%; margin: 0; }
.cat-row.err { border-color: var(--danger); background: #FDECEA; }

/* ---------- 区域 / 服务对象 彩色标记 ---------- */
/* 底色/文字色由 app.js 按 id 算出（同一个区域永远同色），这里只管形状 */
.scope-tag {
  display: inline-block; max-width: 100%; padding: 0 6px; margin-right: 2px;
  border: 1px solid transparent; border-radius: 5px;
  font-size: 11px; line-height: 17px; vertical-align: middle;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.todo-tags .scope-tag { font-size: 11.5px; }
.cell-sub .scope-tag { font-size: 10.5px; line-height: 16px; padding: 0 5px; }
.lc-sub .scope-tag { font-size: 11.5px; }

/* 右侧预留板块 */
.home-placeholder {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; padding: 36px 24px; text-align: center;
}
.home-placeholder .ph-icon { font-size: 30px; color: #C7CFDA; line-height: 1; }
.home-placeholder .ph-title { font-size: 13.5px; color: var(--text-2); font-weight: 500; }
.home-placeholder .ph-desc { font-size: 12px; color: var(--text-3); line-height: 1.6; max-width: 320px; }

/* 首页·400派单统计卡 */
/* 400派单数字卡（原「动环设备厂家」卡位）：一格并排 年度/季度/月度 三个数字 */
.dispatch-stat .dispatch-mini { display: flex; gap: 8px; }
.dispatch-stat .dispatch-mini span {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 1px;
  background: #F6F9FC; border: 1px solid var(--line); border-radius: 8px;
  padding: 7px 4px; font-size: 11px; color: var(--text-2); white-space: nowrap;
}
.dispatch-stat .dispatch-mini b {
  font-size: 19px; font-weight: 700; color: var(--accent); line-height: 1.1;
}

/* 首页快捷导出卡（原「厂家设备型号」卡位，2026-10-25）：
   第一个功能「订单总明细」= 采购订单 × 外包单汇总联合导出。
   2026-10-26 合并为单个「快捷导出」框：竖向列表 + 行尾「导出」按钮（带点引导线）。 */
.export-box {
  flex: 2 1 320px; min-width: 260px;
  cursor: default; gap: 8px;
}
/* 整框 hover 不整块高亮（行级 hover 才高亮），覆盖 .home-stat:hover 的整块效果 */
.export-box:hover { border-color: var(--line); background: var(--panel); }
.export-box-title {
  font-size: 14px; font-weight: 700; color: var(--accent);
  padding-bottom: 4px; border-bottom: 1px dashed var(--line);
}
.export-rows { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.export-row {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px; border-radius: 8px; cursor: pointer; transition: .12s;
}
.export-row:hover { background: var(--accent-soft); }
.export-name { font-size: 13px; font-weight: 500; color: var(--text); white-space: nowrap; }
/* 点引导线：flex 占满剩余宽度，底部虚线点 */
.export-dots {
  flex: 1 1 auto; min-width: 16px; height: 0; align-self: center;
  border-bottom: 2px dotted #C2CAD6; margin: 0 8px;
}
.export-go-btn {
  flex: none; align-self: center;
  background: var(--accent); color: #fff; border: none; border-radius: 8px;
  padding: 5px 14px; font-size: 13px; font-weight: 600; cursor: pointer;
  font-family: inherit; transition: .12s;
}
.export-go-btn:hover { background: #1668B4; }
/* 二级导出（2026-10-30）：订单总明细下的「维谛订单-胜赛 / 维谛订单-杰诚」。
   左边缩进 + 一个 └ 折线，明确是从上一行分出来的子项；字号略小、颜色略淡。 */
.export-row.sub { position: relative; padding-left: 18px; }
.export-row.sub::before {
  content: ""; position: absolute; left: 8px; top: -8px; bottom: 50%;
  border-left: 1.5px solid #C2CAD6;
}
.export-row.sub::after {
  content: ""; position: absolute; left: 8px; top: 50%;
  width: 7px; border-top: 1.5px solid #C2CAD6;
}
.export-row.sub .export-name { font-weight: 400; font-size: 11.5px; color: var(--text-2); }
.export-row.sub .export-go-btn { padding: 4px 7px; font-size: 11.5px; }
/* 二级项的引导线让位给名字（卡片窄，名字要单行完整显示） */
.export-row.sub .export-dots { min-width: 4px; margin: 0 2px; }
/* 二级项名字必须看得全：卡片窄的窗口（≤1440）单行放不下，会被省略成「维谛订单...」，
   两个子项就分不清了。所以二级项允许换行，但 word-break:keep-all 保证只在「-」处断，
   最差也就是「维谛订单-」换行接「胜赛」，不会在汉字中间劈开。
   一级项（订单总明细 / 移动新增采集器汇总）仍是原来的单行省略号，不受影响。 */
.export-row.sub .export-name {
  white-space: normal; word-break: keep-all; line-height: 1.25;
  overflow: visible; text-overflow: clip;
}

/* ---------- 「关联工单」自绘下拉（2026-10-26）：PC 端一次平铺全部，不出内部滚动条 ---------- */
.ref-picker { position: relative; }
.ref-picker-btn {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 9px 11px; border: 1px solid var(--line); border-radius: var(--radius);
  background: #fff; font: inherit; color: var(--text); cursor: pointer; text-align: left;
}
.ref-picker-btn:hover { border-color: var(--accent); }
.ref-picker.open .ref-picker-btn { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.ref-picker-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ref-picker-arrow { flex: none; color: var(--text-3); font-size: 12px; }
/* 面板跟着内容长高（不设 max-height / overflow），由弹窗自身滚动把剩下的看完 */
.ref-picker-panel {
  margin-top: 6px; padding: 6px;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: 0 6px 18px rgba(20, 35, 60, .10);
}
.ref-picker-search {
  width: 100%; box-sizing: border-box; margin-bottom: 6px; padding: 6px 9px;
  border: 1px solid var(--line); border-radius: var(--radius); font: inherit; font-size: 13px;
}
.ref-picker-search:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.ref-picker-list { max-height: none; overflow: visible; }
/* 行高收紧（2026-10-26）：原来 padding 8px 太松，一屏只能看十几条；现在压到 3px，
   同一屏能多看一倍左右，一次把工单列完更好找 */
.ref-picker-item {
  display: block; width: 100%; padding: 3px 9px; border: 0; border-radius: 5px;
  background: transparent; font: inherit; font-size: 13px; color: var(--text); text-align: left;
  cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 1.5;
}
.ref-picker-item:hover { background: var(--accent-soft); }
.ref-picker-item.on { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
/* 手机端才收着点：面板限高可滚动，免得一次占满屏幕 */
@media (max-width: 620px) {
  .ref-picker-list { max-height: 52vh; overflow: auto; }
}

/* ---------- 材料收发单（2026-10-26 新增模块） ---------- */
.mf-ticker {
  display: flex; align-items: center; gap: 10px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 8px 12px; overflow: hidden;
}
.mf-ticker-home { margin: 10px 0 0; }
.mf-ticker-label {
  flex: none; font-size: 12px; font-weight: 700; color: var(--accent);
  background: var(--accent-soft); border-radius: 6px; padding: 3px 8px; white-space: nowrap;
}
.mf-ticker-track {
  display: inline-flex; white-space: nowrap; will-change: transform;
  animation: mfmarquee 40s linear infinite;
}
.mf-ticker:hover .mf-ticker-track { animation-play-state: paused; }
.mf-chip {
  font-size: 13px; color: var(--text-3); padding: 0 22px; white-space: nowrap;
  border-right: 1px dashed var(--line);
}
.mf-chip b { color: var(--text); font-weight: 600; }
.mf-chip .in { color: #1f8a4c; font-style: normal; font-weight: 600; }
.mf-chip .out { color: #c2410c; font-style: normal; font-weight: 600; }
.mf-chip .rem { color: var(--accent); font-style: normal; font-weight: 700; }
.mf-chip .rem.zero { color: #d33; }
.mf-chip.muted { color: var(--text-3); }
@keyframes mfmarquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* ---------- 首页「材料收发」板块（2026-10-27 新增） ----------
   位置：紧挨「快捷导出」卡片右侧（同属 .home-stats 那一排）。
   形态：卡片里**整行上下滚动** —— 一条工程一行（工程名 + FSU 总数 / 已发 / 余）。
   原来是一条占满整行的横向跑马灯，chip 全挤在一行不好读，也塞不进卡片。 */
.mf-home-box {
  flex: 1 1 260px; min-width: 240px;
  cursor: default; gap: 6px;
}
/* 整卡不可点，覆盖 .home-stat:hover 的整块高亮 */
.mf-home-box:hover { border-color: var(--line); background: var(--panel); }
.mf-vticker {
  position: relative; overflow: hidden;
  /* 2026-10-27（145）：滚动窗口跟着卡片长（同排卡片把它撑多高就显示几行），
     原来固定 96px，卡片被撑高后下面空一大块，看着像内容没铺满 */
  /* flex-basis 必须是 0：用 auto 的话轨道内容高度会反过来撑高卡片，
     卡片越高轨道越长，一路滚雪球（实测被撑到 433px） */
  flex: 1 1 0; min-height: 96px; margin-top: 2px;
}
.mf-vticker-track { display: flex; flex-direction: column; will-change: transform; }
.mf-vticker-track.run { animation: mfvmarquee 22s linear infinite; }
.mf-vticker:hover .mf-vticker-track { animation-play-state: paused; }
.mf-vticker-item {
  display: flex; align-items: center; gap: 8px;
  height: 32px; flex: none; min-width: 0;
  font-size: 13px; color: var(--text-2); white-space: nowrap;
}
.mf-vticker-item + .mf-vticker-item { border-top: 1px dashed var(--line); }
.mf-vticker-item .vt-name {
  flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  font-weight: 600; color: var(--text);
}
.mf-vticker-item .vt-nums { flex: none; font-size: 12px; color: var(--text-3); }
.mf-vticker-item .vt-nums .in { color: #1f8a4c; font-style: normal; font-weight: 600; }
.mf-vticker-item .vt-nums .out { color: #c2410c; font-style: normal; font-weight: 600; }
.mf-vticker-item .vt-nums .rem { color: var(--accent); font-style: normal; font-weight: 700; }
.mf-vticker-item .vt-nums .rem.zero { color: #d33; }
/* 2026-10-27（145）：已发完的工程沉底、灰字，一眼区分「还有余量」和「发完了」 */
.mf-vticker-item .vt-nums .rem.done { color: var(--text-3); font-weight: 600; }
.mf-vticker-item.vt-done .vt-name { color: var(--text-3); font-weight: 500; }
.mf-vticker-item .vt-sep { margin: 0 5px; color: #C2CAD6; }
.mf-vticker-item.muted { color: var(--text-3); font-size: 12px; }
@keyframes mfvmarquee { from { transform: translateY(0); } to { transform: translateY(-50%); } }


.mf-page { display: flex; flex-direction: column; gap: 14px; padding: 4px 0; }
.mf-summary { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 12px 14px; }
.mf-summary-head { font-size: 14px; font-weight: 600; margin-bottom: 8px; }
/* 2026-11-05：材料汇总模糊搜索栏 */
.mf-search-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.mf-search-top { margin-bottom: 4px; }
.mf-search-input { flex: 1; min-width: 0; max-width: 420px; padding: 7px 12px; border: 1px solid var(--line); border-radius: 6px; font-size: 13px; background: var(--bg); color: var(--text); }
.mf-search-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft, rgba(45,133,255,.12)); }
.mf-search-count { font-size: 12px; color: var(--text-3); white-space: nowrap; }
/* 2026-11-05：页签默认收起，面板 hidden 时强制隐藏（.mf-panel 是 flex，会盖过 hidden 默认值） */
.mf-panel[hidden] { display: none !important; }
.mf-ticker-lg { margin-bottom: 10px; }
.mf-sum-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.mf-sum-table th, .mf-sum-table td { padding: 6px 8px; border-bottom: 1px solid var(--line); text-align: left; }
.mf-sum-table th { color: var(--text-3); font-weight: 600; }
.mf-sum-table .num, .mf-rec .num { text-align: right; font-variant-numeric: tabular-nums; }
.mf-sum-table .rem { font-weight: 700; color: var(--accent); }
.mf-sum-table .rem.zero { color: #d33; }
/* 2026-10-27：按工程维度的材料汇总表 */
.mf-os td { vertical-align: top; }
.mf-os .mf-os-proj { min-width: 0; }
.mf-os .mf-os-proj b { display: block; font-size: 13px; }
.mf-os .mf-os-list { font-size: 12px; line-height: 1.55; color: var(--text-2); min-width: 0; }
.mf-os .mf-os-man { white-space: nowrap; font-weight: 600; }
.mf-os .mf-os-none { color: var(--text-3); }
.mf-os .mf-os-inst { font-weight: 700; color: var(--accent); }
/* 2026-10-27：数量列改成「每种材料一行」，跟旁边的清单列逐行对齐（不再是一个总和） */
.mf-os .mf-os-qty-td { text-align: right; white-space: nowrap; }
.mf-os .mf-os-qty-td > span { display: block; font-size: 12px; line-height: 1.6; }
.mf-os .mf-os-qty-td.rem > span { font-weight: 700; color: var(--accent); }
.mf-os .mf-os-qty-td .zero, .mf-os .mf-os-qty { color: #d33; }
/* 2026-10-27：中间不留大片空白 —— 列一律按内容宽（width:1% 是「别给我分富余」的写法），
   表格和卡片本身也不再铺满整行，而是按内容收窄，这样列与列之间不会拉出一大片白。
   注意：这几条必须写在 .mf-rec / .mf-sum-table 的 width:100% 之后才生效。 */
.mf-os .mf-os-list,
.mf-os .mf-os-qty-td,
.mf-os .mf-os-man,
.mf-os .mf-os-inst { white-space: nowrap; }
.mf-os .mf-os-list { min-width: 0; }
.mf-os tbody tr:nth-child(even) { background: rgba(127, 127, 127, .04); }
/* 2026-10-27（140）：采集器（FSU）行染色 —— 材料汇总表 / 已登记收货单 / 已发货记录共用，
   由 app.js 的 mfListCell()、mfQtyLines() 按 it.is_fsu 打上 .mf-fsu-li。
   这几处清单是纯文本行（不是下拉框，138 节那套 select 染色用不上），所以按行给背景；
   清单列和数量列同一个 class，横着看是一条连续的浅紫色带。
   只染底、不动文字颜色 —— 「剩余 0」的红色、「已安装」的蓝色、「剩余数量」的强调色都保留。 */
/* 2026-10-27（149）：底色加深 —— 原来 #F1ECFC 太淡，采集器行在长表里几乎看不出来。
   改成 #E5DBFA（一档中深）：一眼能认出采集器行，但黑色文字、
   「剩余 0」的红字、「已安装」的蓝字都还清晰。 */
.mf-fsu-li {
  background: #E5DBFA; border-radius: 4px;
  /* 左右各补 6px 内边距 + 等量负外边距：色块有呼吸感，文字位置不变（数量列右对齐也不会被挤歪） */
  padding-left: 6px; padding-right: 6px; margin-left: -6px; margin-right: -6px;
}
/* 「订单已结算」小标（这些记录整组沉在最下面） */
.mf-sub.mf-done-tag { color: #B26A00; }

.mf-tabs { display: flex; gap: 8px; }
.mf-tab {
  font: inherit; cursor: pointer; border: 1px solid var(--line); background: var(--panel);
  color: var(--text); border-radius: 8px; padding: 7px 16px; font-size: 13px; font-weight: 600;
}
.mf-tab.active { background: var(--accent); color: #fff; border-color: var(--accent); }

.mf-panel { display: flex; flex-direction: column; gap: 14px; }
.mf-form-card, .mf-list-card {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px;
}
.mf-form-title { font-size: 14px; font-weight: 600; margin-bottom: 10px; }
.mf-hint { font-size: 12px; font-weight: 400; color: var(--text-3); margin-left: 8px; }
.mf-form-row { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; align-items: flex-end; }
.mf-form-row label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--text-3); }
/* 2026-10-27（146）：表单整行平铺 —— 行内各字段按 1:1:1 均分占满卡片宽度，不再左挤留白
   注意：不要给 .mf-flex 单独设 flex:1 1 100% —— 「合同材料模板」那页的「合同名称」
   也带 mf-flex，它和「合同号 / 关联采购订单」同在一行，必须三者均分。
   flex:1 1 0 对「只有它一个 label」的行（备注）自然会撑满整行，无需特例。 */
.mf-form-row > label { flex: 1 1 0; min-width: 150px; }
.mf-form-row input, .mf-form-row select {
  font: inherit; font-size: 13px; color: var(--text); background: var(--bg);
  border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px;
  width: 100%; max-width: 100%;
}
/* 采购订单下拉：以前用 mfFitSelect() 量最长选项写成固定像素宽（上限 460px），
   结果只占左边一截、右边大片留白；现在交给 CSS 占满整列（下行 !important 压过 JS 写的 px） */
.mf-po { flex: 1 1 0; min-width: 150px; max-width: 100%; }
.mf-po select { width: 100% !important; max-width: 100%; text-overflow: ellipsis; }
/* 2026-10-26：「＋ 加一行」挪到最左边，标题跟在按钮后面（原 space-between 改成靠左排列） */
/* 收货登记「动环设备厂家」：选完只留该厂家 + 通用（2026-10-27） */
.mf-mfr-row {
  display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; margin: 2px 0 4px;
}
.mf-mfr-row label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--text-3); flex: 1 1 0; min-width: 150px; }
.mf-mfr-row select {
  font: inherit; font-size: 13px; color: var(--text); background: var(--bg);
  border: 1px solid var(--line); border-radius: 7px; padding: 7px 9px;
  width: 100% !important; max-width: 100%;
}
.mf-mfr-row .mf-hint { margin-left: 0; padding-bottom: 8px; }
.mf-items-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; margin: 6px 0; }
.mf-items-title { font-weight: 600; color: var(--text-2); }
/* 2026-10-27（146）：材料清单表格占满整卡（以前 width:auto 只按内容宽、右边一大片白）；
   材料名下拉填满所在列，不再按最长选项收窄 */
.mf-items { width: 100%; max-width: 100%; border-collapse: collapse; font-size: 13px; }
.mf-rec { width: 100%; border-collapse: collapse; font-size: 13px; }
.mf-items th, .mf-items td, .mf-rec th, .mf-rec td { padding: 5px 6px; border-bottom: 1px solid var(--line); }
.mf-items input {
  font: inherit; font-size: 13px; width: 100%; border: 1px solid var(--line); border-radius: 6px;
  padding: 6px 7px; background: var(--bg); color: var(--text);
}
/* 材料名称下拉（候选＝厂家设备型号）：占满所在列（!important 压过 mfFitSelect 写的 px 宽） */
.mf-items select {
  font: inherit; font-size: 13px; width: 100% !important; max-width: 100%;
  border: 1px solid var(--line); border-radius: 6px;
  padding: 6px 7px; background: var(--bg); color: var(--text); text-overflow: ellipsis;
}
.mf-items select:focus { border-color: var(--accent); outline: 0; }
/* 只留「名称 + 数量」：数量列收窄，右对齐 */
.mf-items .mf-th-qty { width: 110px; }
.mf-items .mf-qty { width: 110px; text-align: right; }
.mf-items th { color: var(--text-3); font-weight: 600; text-align: left; }
.mf-rec th { color: var(--text-3); font-weight: 600; text-align: left; }
/* 2026-10-27：清单列只放材料名，数量单独一列（逐行对齐）。列表表格里两列行高、
   内边距完全一致才能横着对齐；不加虚线（清单列很宽，横线会拉成一条长虚线很难看） */
.mf-os-list .mf-li { display: block; line-height: 1.6; }
.mf-rec .mf-os-list,
.mf-rec .mf-os-qty-td { font-size: 13px; white-space: nowrap; }
/* 2026-10-27（144）：表格铺满卡片、列宽平均分配 —— 取代 137 节那套「列一律 width:1%
   按内容最小化」的做法（那是为了收紧列距，代价是表格右边留一大片白）。
   现在的做法：表格 width:100% 铺满，短列（数量 / 日期 / 项数 / 操作 / 删除）给固定像素宽，
   剩下的宽度由「工程名称 / 清单」这类需要宽的列平均分担，视觉上整行排满、不留空档。
   注意：不要用 table-layout:fixed —— 清单列是 nowrap、行行要与数量列逐行对齐，
   定死列宽会把长材料名挤出格子。 */
.mf-sum-table, .mf-rec { width: 100%; }
.mf-sum-table .mf-c-qty, .mf-rec .mf-c-qty { width: 92px; }
.mf-sum-table .mf-c-rem { width: 96px; }
.mf-sum-table .mf-c-inst { width: 92px; }
.mf-sum-table .mf-c-man { width: 96px; }
.mf-rec .mf-c-act { width: 62px; }
.mf-rec .mf-c-date { width: 108px; }
.mf-rec .mf-c-n { width: 58px; }
.mf-rec .mf-c-man { width: 96px; }
.mf-rec .mf-c-del { width: 42px; }
/* 窄屏/列多时列表可横向滚动，不至于把卡片撑破 */
#mfRList, #mfIList, #mfCList { overflow-x: auto; }
.mf-rec .mf-os-list .mf-li,
.mf-rec .mf-os-qty-td > span { display: block; line-height: 1.6; padding: 3px 0; }
.mf-form-actions { margin-top: 10px; display: flex; gap: 10px; }
.mf-list-title { font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--text); }
/* 收货单列表里订单号下方的工程名称（2026-10-26） */
.mf-sub { display: block; font-size: 11px; line-height: 1.3; color: var(--text-3); margin-top: 2px; }
/* 2026-10-26：针对性发货 —— 数量框下方显示「该采购订单还剩多少」 */
.mf-remain {
  display: block; font-size: 11px; line-height: 1.3; margin-top: 2px;
  color: var(--ok, #2E7D32); white-space: nowrap;
  /* 2026-10-27：点一下就把可发余量填进数量框（数量仍可自己改） */
  cursor: pointer; user-select: none;
}
.mf-remain:hover { text-decoration: underline; }
.mf-remain.zero { color: #D93025; font-weight: 600; }
.mf-remain.none { color: var(--text-3); }
.mf-ct-meta {
  font-size: 11.5px; color: var(--text-3); font-weight: 400;
  margin-left: auto; margin-right: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mf-empty { color: var(--text-3); font-size: 13px; padding: 8px 0; }
.mf-contract { border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; margin-bottom: 8px; }
.mf-contract-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }
.mf-contract-items { font-size: 12px; color: var(--text-3); line-height: 1.6; }
.mf-del {
  border: none; background: transparent; color: var(--text-3); cursor: pointer; font-size: 13px;
  border-radius: 6px; padding: 3px 7px; font-family: inherit;
}
.mf-del:hover { background: #fde8e8; color: #d33; }
.mf-td-del { text-align: center; width: 36px; }
/* 2026-10-27：单据列表行首「编辑」按钮（收货单 / 发货单都可编辑，编辑按钮统一在左边） */
.mf-th-act { width: 56px; }
.mf-td-act { text-align: center; white-space: nowrap; }
.mf-edit {
  border: 1px solid var(--line-strong); background: transparent; color: var(--accent);
  cursor: pointer; font: inherit; font-size: 12px; padding: 2px 9px; border-radius: 6px;
}
.mf-edit:hover { background: var(--accent-soft); border-color: var(--accent); }
.mf-form-card.editing { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
/* 2026-10-27：同一采购订单的多次收货并成一组 —— 组间一条粗分隔线，订单号单元格跨整组 */
.mf-rec tr.mf-grp-first > td { border-top: 2px solid var(--line-strong); }
.mf-rec tbody tr:first-child.mf-grp-first > td { border-top: 1px solid var(--line); }
.mf-po-cell {
  vertical-align: top; background: var(--accent-soft);
  border-right: 1px dashed var(--line-strong);
}

/* ---------- 2026-10-27：成套模板（收货套模板 / 发货按套摊开） ---------- */
/* 合同模板下拉：与同排其他字段均分占满整行 */
.mf-ct { flex: 1 1 0; min-width: 150px; max-width: 100%; }
.mf-ct select { width: 100% !important; max-width: 100%; text-overflow: ellipsis; }
/* 模板说明 + 套数输入：一条浅底横条，收货 / 发货共用 */
.mf-plan-row {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: 4px 0 6px; padding: 8px 10px;
  background: var(--accent-soft); border: 1px solid var(--line); border-radius: 8px;
  font-size: 12.5px; color: var(--text-2); line-height: 1.5;
}
.mf-plan { flex: 1 1 320px; min-width: 0; }
.mf-plan b { color: var(--text); font-weight: 600; }
.mf-sets {
  display: flex; align-items: center; gap: 6px;
  font-size: 12.5px; color: var(--text-2); white-space: nowrap;
}
.mf-sets input {
  font: inherit; font-size: 13px; width: 78px; text-align: right;
  border: 1px solid var(--line-strong); border-radius: 6px; padding: 5px 7px;
  background: var(--panel); color: var(--text);
}
.mf-sets-max {
  font: inherit; font-size: 12px; cursor: pointer; white-space: nowrap;
  border: 1px solid var(--line-strong); background: var(--panel); color: var(--accent);
  border-radius: 999px; padding: 3px 10px;
}
.mf-sets-max:hover { border-color: var(--accent); background: var(--panel); }
.mf-sets-max b { font-weight: 700; }
/* 材料行「采集器」标记：成套里哪一行是动环采集器（FSU），一眼看出来 */
.mf-td-mat { white-space: nowrap; }
.mf-fsu-tag {
  display: inline-block; margin-left: 6px; padding: 1px 6px; border-radius: 999px;
  font-size: 11px; font-weight: 600; line-height: 1.5; vertical-align: middle;
  color: #fff; background: #6B46C1;
}
/* 收货 / 发货列表里「模板 · N 套」的副行 */
.mf-sub.mf-ct-sub { color: var(--accent); }

/* ---------- 施工日志·监控对象行编辑 ---------- */
/* 间距体系统一为 6px：盒内(头/行/脚) 6px、行与行之间 6px、行内控件与型号副行 6px；
   之前 .target-rows 是裸 div（行与行 0px，副行与下一行贴在一起），网格又用 8px，故「有大有小」 */
.target-box { display: flex; flex-direction: column; gap: 6px; }
.target-rows { display: flex; flex-direction: column; gap: 6px; }
.target-head, .target-row {
  display: grid; grid-template-columns: minmax(150px, 1fr) 1.5fr 76px 44px;
  gap: 6px 8px; align-items: center;
}
.target-head {
  font-size: 12.5px; font-weight: 600; color: var(--text);
  background: #F1F3F6; border-radius: 8px; padding: 9px 12px;
}
.target-row select, .target-row input {
  width: 100%; padding: 7px 10px;   /* 用 padding 撑高，不锁死 height，避免高分屏文字被裁 */
  border: 1px solid var(--line-strong); border-radius: 7px;
  background: #fff; font: inherit; font-size: 13px; color: var(--text); outline: 0;
  min-width: 0;
}
.target-row select:focus, .target-row input:focus { border-color: var(--accent); }
/* 删除：红字文本按钮（设计稿样式） */
.target-row .row-del {
  width: auto; height: auto; border-radius: 6px;
  color: var(--danger); font-size: 13px; padding: 4px 2px;
}
.target-row .row-del:hover { background: transparent; color: #C22B21; text-decoration: underline; }
.target-foot { display: flex; align-items: center; gap: 10px; }
/* 窄屏（手机）：单行紧凑排版——端口(窄列) / 设备(弹性) / 数量 / 删除 同一行，
   表头四列正好对齐继续显示；智能型号副行整行。此前「端口独占一行」把每行拆成
   3 行，8 个串口会堆出 20+ 行，浪费大量空间。 */
@media (max-width: 620px) {
  .target-head { padding: 7px 10px; }
  .target-row {
    grid-template-columns: minmax(76px, auto) minmax(0, 1fr) 52px auto;
    gap: 6px;
  }
}

/* 施工日志·清单站点快选（工单 → 清单 → 区域筛选 → 点站名填入） */
.site-picker { margin-top: 8px; }
.site-picker .sp-head { font-size: 11.5px; color: var(--text-3); margin-bottom: 6px; }
.site-picker .sp-hint {
  font-size: 11.5px; color: var(--text-3); line-height: 1.6;
  background: #FAFBFC; border: 1px dashed var(--line-strong);
  border-radius: 8px; padding: 7px 10px;
}
/* 选定站名后收起列表，只留一行小字 */
.site-picker .sp-done { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 6px; }
.site-picker .sp-done b { color: var(--text); font-weight: 500; word-break: break-all; }
/* 施工次数提示（数据来自清单明细备注9） */
.site-picker .sp-count {
  font-size: 11.5px; font-weight: 600; color: #222;
  background: #EEF0F2; border-radius: 999px; padding: 2px 9px;
}
/* 已施工过：绿色字体 */
.site-picker .sp-count.done {
  color: #1F9D4D; background: #E7F6EC;
}
.site-picker .sp-again {
  margin-left: auto; flex: none;
  border: 1px solid var(--line-strong); background: #fff; border-radius: 999px;
  padding: 3px 10px; font: inherit; font-size: 11.5px; color: var(--accent); cursor: pointer;
}
.site-picker .sp-again:hover { border-color: var(--accent); background: var(--accent-soft); }
.site-picker .sp-list {
  display: flex; flex-wrap: wrap; gap: 6px;
  max-height: 148px; overflow: auto;
}
.site-picker .sp-chip {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  border: 1px solid var(--line-strong); background: #fff; border-radius: 999px;
  padding: 5px 11px; font: inherit; font-size: 12.5px; color: var(--text);
  cursor: pointer; text-align: left;
}
.site-picker .sp-chip:hover { border-color: var(--accent); color: var(--accent); }
.site-picker .sp-chip.on {
  background: var(--accent-soft); border-color: var(--accent); color: var(--accent);
}
.site-picker .sp-chip .sp-region {
  font-size: 11px; color: var(--text-3); background: #F1F3F6;
  border-radius: 999px; padding: 1px 7px; flex: none;
}
.site-picker .sp-chip.on .sp-region { background: #fff; color: var(--accent); }
/* 已施工过的站点：站名绿色（未施工保持黑色），后缀绿色次数徽标 */
.site-picker .sp-chip.done .sp-name { color: #1F9D4D; font-weight: 600; }
.site-picker .sp-chip.done:hover .sp-name { color: #178A42; }
.site-picker .sp-chip .sp-cnt {
  font-size: 10.5px; font-weight: 600; color: #1F9D4D;
  background: #E7F6EC; border-radius: 999px; padding: 1px 7px; flex: none;
}
.site-picker .sp-chip.on.done .sp-name,
.site-picker .sp-chip.on .sp-cnt { color: #12733A; }
.site-picker .sp-chip.on .sp-cnt { background: #fff; }
.field input.flash, .field select.flash {
  border-color: var(--accent); box-shadow: 0 0 0 3px rgba(24, 95, 165, .18);
}
@media (max-width: 620px) {
  .site-picker .sp-chip { padding: 8px 12px; font-size: 14px; }
  .site-picker .sp-list { max-height: 190px; }
}

/* 首页右侧·遗留问题列表 */
.legacy-list { max-height: 460px; }
.legacy-item { cursor: pointer; display: flex; align-items: center; gap: 8px;
  padding: 6px 10px; margin-bottom: 4px;
  border: 1px solid #AEB6C2; border-radius: 8px; background: #fff; }
.legacy-item:last-child { margin-bottom: 0; }
.legacy-item:hover { background: #FAFCFE; }
/* 标签类子项不收缩，保持原样 */
.legacy-item > .scope-tag, .legacy-item > .tag, .legacy-item > .legacy-so { flex: none; }
.legacy-so { flex: none; font-size: 11.5px; font-weight: 500; color: #1A5FB4;
  background: #E8F0FB; border: 1px solid #C9DDF5; border-radius: 4px; padding: 0 6px;
  line-height: 1.6; white-space: nowrap; }
.legacy-site { font-size: 12.5px; font-weight: 500; color: var(--text);
  flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.legacy-date { font-size: 11.5px; color: var(--text-3); flex: none; white-space: nowrap; }
.legacy-flag {
  flex: none; border: 1px solid var(--line); background: #fff; border-radius: 6px;
  padding: 2px 7px; font-size: 12.5px; line-height: 1.4; cursor: pointer; color: #8a8f98;
  display: inline-flex; align-items: center; gap: 4px;
}
.legacy-flag:hover { border-color: #F0A32F; background: #FFF7E8; }
.legacy-flag-svg { display: block; flex: none; }
.legacy-flag-txt { white-space: nowrap; }
/* 已加入待办的遗留：三角旗布变红（由 SVG 内部控制），文字也跟着加深 */
.legacy-flag.on { color: #D9433A; }
.legacy-text {
  flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; font-size: 12px; color: var(--danger); font-weight: 500;
}

.table-wrap { overflow-x: auto; }

table { width: 100%; border-collapse: collapse; font-size: 13px; }
thead th {
  position: sticky; top: 0;
  background: #FAFBFC;
  color: var(--text-2);
  font-weight: 500; font-size: 12px;
  text-align: left; white-space: nowrap;
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
}
tbody td {
  padding: 11px 14px;
  border-bottom: 1px solid #F1F3F6;
  color: var(--text);
  vertical-align: middle;
}
/* 行分隔线：画在 <tr> 上而不是只画在 td 上——折叠边框模型里单元格的背景层
   会盖住自己单元格上的 border，整行有底色时（已上线的淡绿行）分隔线就“消失”了。
   行边框位于单元格背景之上，任何行底色下都清晰可见。
   只作用于主列表 #table（排除 .tree-table 树形表，它有自己的行列边框）。 */
/* 行分隔线颜色用字面量（与已上线行 #B7DCC3 一致）：jsdom 无法解析 var()，
   用字面量才能被自动化测试计算样式校验；真实浏览器里等同 --line-strong。 */
#table:not(.tree-table) tbody tr { border-bottom: 1px solid #D2D8E0; }
#table:not(.tree-table) tbody tr.row-online { border-bottom-color: #B7DCC3; }
/* 折叠边框模型里 td 的边框优先级高于 tr（同宽同样式时单元格赢），
   必须在 td 上声明同色边框，否则上面 tr 的边框被 td 自带的 #F1F3F6 盖掉 */
#table:not(.tree-table) tbody tr > td { border-bottom: 1px solid #D2D8E0; }
#table:not(.tree-table) tbody tr.row-online > td { border-bottom-color: #B7DCC3; }
#table:not(.tree-table) tbody tr:last-child,
#table:not(.tree-table) tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: #FAFCFE; }
/* 已上线（toggle=1）的整行淡绿底；悬停稍深一点保持可辨识 */
tbody tr.row-online td { background: #EAF7EE; }
tbody tr.row-online:hover td { background: #DFF2E5; }
/* 采购订单：整行可点进详情（拍照上传区就在详情页最上面）——指针 + 悬停底色提示可点 */
tbody tr.row-click { cursor: pointer; }
tbody tr.row-click:hover td { background: #EFF5FB; }
tbody tr.row-click.row-online:hover td { background: #DFF2E5; }
/* 采购订单整行底色：已结算=绿（优先）；有验收报告=淡黄。
   优先级靠 class 互斥保证（已结算时只加 row-settled，不加 row-accept）
   2026-10-29（179）：已结算的绿由 #EAF7EE（接近白，看不出）加深到 #CDEBD8，
   hover / 分隔线同步加深，黑字仍然清晰可读。施工日志的「已上线」绿（row-online）不受影响 */
#table:not(.tree-table) tbody tr.row-settled,
#table:not(.tree-table) tbody tr.row-settled > td { border-bottom-color: #93CDA8; }
#table:not(.tree-table) tbody tr.row-accept,
#table:not(.tree-table) tbody tr.row-accept > td { border-bottom-color: #EBD9A8; }
tbody tr.row-settled td { background: #CDEBD8; }
tbody tr.row-settled:hover td { background: #BCE1CC; }
tbody tr.row-click.row-settled:hover td { background: #BCE1CC; }
tbody tr.row-accept td { background: #FDF7E4; }
tbody tr.row-accept:hover td { background: #FAF1D5; }
tbody tr.row-click.row-accept:hover td { background: #FAF1D5; }
/* 施工日志列表：内容多列高低不齐，改顶对齐（标签和 FSU型号 贴着行首，不再悬在中间） */
#table.log-table tbody td { vertical-align: top; }
td.idx { color: var(--text-3); width: 48px; }
td.ops { white-space: nowrap; text-align: right; }
td.time { color: var(--text-3); font-size: 12px; white-space: nowrap; }
.cell-empty { color: #C3CAD4; }
/* 单元格副行（如订单编号下方的工程名称） */
.cell-sub { margin-top: 3px; color: var(--text-3); font-size: 12px; line-height: 1.4; }
/* 施工日志列表：遗留问题副行（橙色提醒） */
.cell-sub.legacy { color: var(--danger); }
/* 施工日志列表遗留问题副行里的小旗（与首页遗留板块同步） */
.cell-sub.legacy .legacy-flag {
  margin-right: 4px; padding: 1px 4px; font-size: 11px; line-height: 14px;
  vertical-align: -2px; border-radius: 4px;
}
/* 采购订单：订单编号下方的「工程名称」副行用黑色（2026-10-25 用户要求：
   跟编号一样是黑的，别再做成灰色小字，扫单子时一眼看到是哪个工程） */
.cell-sub.cell-sub-pn { color: var(--text); }
/* FSU型号 副行里的所属厂家（比型号略深一点，先看到厂家） */
.cell-sub .mfr-name { color: var(--text-2); font-weight: 600; }
/* 开关按钮（已上线）：未选中灰白、选中绿底白字 */
button.mini.tg-toggle, .toggle-btn {
  border: 1px solid var(--line-strong); background: #fff; color: var(--text-2);
  border-radius: 999px; padding: 4px 12px; font: inherit; font-size: 12px; cursor: pointer;
}
button.mini.tg-toggle:hover, .toggle-btn:hover { border-color: #1F9D4D; color: #1F9D4D; }
button.mini.tg-toggle.on, .toggle-btn.on {
  background: #1F9D4D; border-color: #1F9D4D; color: #fff; font-weight: 600;
}
button.mini.tg-toggle.on:hover, .toggle-btn.on:hover { background: #178A42; color: #fff; }
button.mini.tg-toggle:disabled, .toggle-btn:disabled { opacity: .6; cursor: default; }
/* 表单里的开关 */
.toggle-box { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.toggle-box .toggle-btn { padding: 8px 20px; font-size: 13.5px; }
.toggle-hint { font-size: 11.5px; color: var(--text-3); }
/* 施工日志列表：站点列下方的现场照片入口（📷 N张，点了才加载大图，列表里不插 <img>） */
.cell-photos { margin-top: 5px; }
.cell-photos .thumb { width: 40px; height: 40px; object-fit: cover; border-radius: 6px; }
.cell-photo-btn {
  display: inline-flex; align-items: center; gap: 4px;
  border: 1px solid var(--line-strong); background: #fff; color: var(--accent);
  border-radius: 999px; padding: 2px 9px; font-size: 12px; cursor: pointer; font: inherit;
}
.cell-photo-btn:hover { border-color: var(--accent); background: var(--accent-soft); }
/* 施工日志列表：监控对象每个串口一行 */
.tg-line { line-height: 1.7; font-size: 12.5px; white-space: nowrap; }
/* 监控对象行编辑：选了串口后出现的「智能设备型号」副行 */
.tl-model-line { grid-column: 1 / 4; display: flex; align-items: center; gap: 8px; }  /* 截止到「数量」列，不占「删除」列 */
/* 没选串口时也保留这行的高度（只隐藏内容），保证每行间距一致 */
.tl-model-line.hidden { display: none; }  /* 原为 visibility:hidden——不可见但占位，导致智能监控对象行下方出现大段留白 */
.tl-model-line .tl-model { flex: 1; min-width: 0; }
/* 手机端：型号副行占满整行（须写在其上 1/4 规则之后才能覆盖生效） */
@media (max-width: 620px) {
  .tl-model-line { grid-column: 1 / -1; }
}
/* 下拉展开的型号选项：淡蓝底色更醒目；select 本体（选完关闭后）不加底色 */
.tl-model-line .tl-model option {
  background: #EAF3FE; color: #1B3A5C;
  border-bottom: 1px solid #C9DFF5; padding: 6px 10px;
}
/* FSU型号用过模板方案的：青色底小徽块（悬停显示模板方案名） */
.tpl-chip {
  display: inline-block; background: #D8F3F5; color: #1F7680;
  border-radius: 6px; padding: 1px 8px; font-size: 12px;
}
.link { color: var(--accent); }
.tag {
  display: inline-block; padding: 1px 8px; border-radius: 20px;
  background: var(--accent-soft); color: var(--accent); font-size: 12px;
}

.mini {
  border: 0; background: transparent; cursor: pointer;
  font: inherit; font-size: 12px; padding: 4px 8px; border-radius: 6px;
  color: var(--accent);
}
.mini:hover { background: var(--accent-soft); }
/* 采购订单「清单」按钮：清单里有站点明细 → 蓝底加粗 + 条数徽标；空清单 → 灰底，一眼可辨 */
.mini.has-items {
  background: var(--accent-soft); border: 1px solid #B9D6F2;
  color: var(--accent); font-weight: 600; padding: 3px 7px;
}
.mini.has-items:hover { background: #DCEBFA; }
.mini.empty-list {
  color: var(--text-3); border: 1px dashed var(--line-strong);
  background: transparent; padding: 3px 7px;
}
.mini.empty-list:hover { background: #F2F4F7; color: var(--text-2); }
.mini .mini-badge {
  font-style: normal; font-size: 10px; margin-left: 3px;
  opacity: .9; font-weight: 600;
}

/* 拍照账号列表「拍照情况」列：已拍/未拍 徽标 */
td.photo-state { white-space: nowrap; }
/* 拍照列表列宽（用 class 而非内联 style，窄屏媒体查询才能覆盖） */
#table .col-photo, #table td.photo-state { width: 84px; }
#table .col-ops { width: 96px; }
.photo-done {
  display: inline-block; padding: 2px 8px; border-radius: 999px;
  font-size: 12px; font-weight: 600; line-height: 1.4;
  background: #E5F6EC; color: #1B7F4D; border: 1px solid #BFE6CF;
}
.photo-none {
  display: inline-block; padding: 2px 8px; border-radius: 999px;
  font-size: 12px; font-weight: 500; line-height: 1.4;
  background: #F2F4F7; color: var(--text-3); border: 1px dashed var(--line-strong);
}

/* 手机（拍照账号主要就在手机上用）：列变多后「📷 拍照」容易被挤出屏幕——
   窄屏固定布局 + 收紧内边距 + 让序号列让位，保证拍照按钮不用横向滚动就能点到 */
@media (max-width: 620px) {
  body.photo-mode #table { table-layout: fixed; }
  body.photo-mode #table thead th,
  body.photo-mode #table tbody td { padding-left: 8px; padding-right: 8px; }
  /* 序号列在手机上价值最低，优先让位 */
  body.photo-mode #table .col-idx,
  body.photo-mode #table td.idx { display: none; }
  body.photo-mode #table .col-type { width: 24%; }
  body.photo-mode #table .col-photo,
  body.photo-mode #table td.photo-state { width: 62px; }
  body.photo-mode #table .col-ops,
  body.photo-mode #table td.ops { width: 74px; }
  body.photo-mode #table td.photo-state .photo-done,
  body.photo-mode #table td.photo-state .photo-none {
    padding: 1px 6px; font-size: 11px;
  }
  body.photo-mode #table td.ops button.mini { padding: 4px 7px; font-size: 12px; }
  /* 名称列超长时省略，不把表格撑宽 */
  body.photo-mode #table td .link {
    display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  body.photo-mode #table td .cell-sub {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
}
/* 小屏手机（≤400px）：再收一档，拍照按钮始终在屏内 */
@media (max-width: 400px) {
  body.photo-mode #table thead th,
  body.photo-mode #table tbody td { padding-left: 6px; padding-right: 6px; }
  body.photo-mode #table .col-type { width: 18%; }
  body.photo-mode #table .col-photo,
  body.photo-mode #table td.photo-state { width: 56px; }
  body.photo-mode #table .col-ops,
  body.photo-mode #table td.ops { width: 68px; }
  body.photo-mode #table td.ops button.mini { padding: 4px 5px; }
}
.mini.del { color: var(--danger); }
.mini.del:hover { background: var(--danger-soft); }

.btn.small { height: 28px; padding: 0 10px; font-size: 12px; }
.btn.small:disabled { opacity: .5; cursor: not-allowed; }

.thumb {
  width: 40px; height: 40px; object-fit: cover;
  border-radius: 6px; border: 1px solid var(--line-strong);
  cursor: zoom-in; display: block; background: #fff;
}
.thumb:hover { border-color: var(--accent); }

.photo-box { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.photo-preview-slot { width: 100%; }
.photo-preview {
  max-width: 220px; max-height: 150px; width: auto; height: auto;
  border-radius: 8px; border: 1px solid var(--line-strong); display: block; background: #fff;
}
.photo-empty {
  width: 220px; height: 96px;
  border: 1px dashed var(--line-strong); border-radius: 8px;
  display: grid; place-items: center;
  color: var(--text-3); font-size: 12px; background: #FAFBFC;
}
.photo-actions { display: flex; gap: 8px; }
.photo-view { align-items: center; }
.photo-view img {
  max-width: 92vw; max-height: 86vh; border-radius: 10px;
  box-shadow: 0 12px 40px rgba(20, 26, 35, .3); background: #fff;
}
.photo-close { position: absolute; top: 18px; right: 24px; font-size: 26px; color: #fff; }

/* 手机端施工日志卡片布局（≤620px）：贴合屏幕、纵向可拉长、内容简略 */
/* 手机端施工日志卡片（≤620px 断点在 renderLogCards 里用 isMobile() 判定）：
   卡片铺满列表卡片宽度，与上方日历等板块对齐，右侧不留白 */
/* display:block 让表格变成普通块、宽度铺满；overflow:visible 关闭横向滚动条留白 */
#table.log-cards { display: block; width: 100%; overflow: visible; }
#table.log-cards thead { display: none; }
#table.log-cards tbody,
#table.log-cards tbody tr,
#table.log-cards tbody td.log-card-cell { display: block; width: 100%; max-width: none; }
#table.log-cards tbody tr { border-bottom: 0 !important; }
#table.log-cards tbody td.log-card-cell {
  padding: 0 !important; border: 0 !important;
  white-space: normal; overflow: visible; text-overflow: clip;
}
.log-card {
  border: 1px solid var(--line); border-radius: 10px; background: var(--panel);
  margin: 8px 0; padding: 10px 12px; box-sizing: border-box;
}
/* 已上线（仅 admin / 城市账号视角可见该状态）：整卡淡绿底 */
.log-card.is-online { background: #EAF7EE; border-color: #B7DCC3; }
.lc-top { display: flex; align-items: baseline; gap: 8px; }
.lc-idx { color: var(--text-3); font-size: 12px; flex: none; }
.lc-site { flex: 1; min-width: 0; font-size: 15px; font-weight: 600; color: var(--text);
  word-break: break-word; }
.lc-sub { margin-top: 2px; color: var(--text-3); font-size: 12.5px; word-break: break-word; }
/* 站点/区域/服务对象下方的照片小图标：点击放大查看现场照片 */
.lc-photos { margin-top: 6px; }
.lc-photo {
  display: inline-flex; align-items: center; gap: 4px;
  border: 1px solid var(--line-strong); background: #fff; color: var(--accent);
  border-radius: 999px; padding: 3px 10px; font-size: 12px; cursor: pointer; font: inherit;
}
.lc-photo:hover { border-color: var(--accent); }
.lc-kv { display: flex; gap: 8px; margin-top: 7px; font-size: 13px; align-items: flex-start; }
/* 标签列：短标签（日期/类型/上线）保持 44px 对齐；更长的（监控对象）不许换行，按内容撑开 */
.lc-k { flex: none; min-width: 44px; width: auto; color: var(--text-3); white-space: nowrap; }
.lc-v { flex: 1; min-width: 0; word-break: break-word; }
.lc-block { margin-top: 7px; }
.lc-block .lc-k { margin-bottom: 2px; }
.lc-line { font-size: 12.5px; color: var(--text-2); line-height: 1.6; word-break: break-word; }
.lc-line.legacy { color: var(--danger); }
/* 卡片「类型」区里型号下面那行 IP：等宽字体，方便对照抄录 */
.lc-ip { font-family: ui-monospace, SFMono-Regular, Consolas, "Courier New", monospace; letter-spacing: .02em; color: var(--text); }
/* 采集器型号那一行（厂家 · 型号）也用黑色，与 IP 一致 */
.cell-sub.lc-model { color: var(--text); }
.cell-sub.lc-model .mfr-name { color: var(--text); font-weight: 600; }
/* 工程施工清单表格里的「遗留问题」列值也用红色，与日志卡片/列表一致 */
.sitegrid td[data-col="legacy_issue"] { color: var(--danger); }
/* 导入预览里的遗留问题值同样标红 */
.cell-legacy { color: var(--danger); }
.lc-ops { margin-top: 10px; display: flex; gap: 6px; justify-content: flex-end; }
/* 放大查看：一组照片竖向排列、可滚动 */
.gallery {
  display: flex; flex-direction: column; gap: 10px; align-items: center;
  max-height: 86vh; overflow-y: auto; padding: 22px 12px;
}
.gallery-img { max-width: 92vw; height: auto; border-radius: 8px;
  box-shadow: 0 12px 40px rgba(20, 26, 35, .3); background: #fff; }

/* 图片查看器（灯箱）：左右切换 + 滚轮/按钮/键盘缩放 + 拖动平移 + 双指捏合 */
.lb-stage {
  position: absolute; inset: 0; z-index: 1;
  display: flex; align-items: center; justify-content: center;
  touch-action: none;   /* 自带手势，别让浏览器跟着滚动/缩放页面 */
}
.photo-view .lb-img {
  max-width: 92vw; max-height: 80vh; border-radius: 10px;
  box-shadow: 0 12px 40px rgba(20, 26, 35, .3); background: #fff;
  will-change: transform; user-select: none; -webkit-user-drag: none; cursor: zoom-in;
}
.lb-stage.zoomable .lb-img { cursor: grab; }
.lb-stage.dragging .lb-img { cursor: grabbing; }
/* 底部：‹ 上一张 / 计数 / 下一张 › */
.lb-bar {
  position: absolute; left: 50%; bottom: 18px; transform: translateX(-50%);
  display: flex; align-items: center; gap: 10px; z-index: 3;
}
.lb-count {
  color: #fff; font-size: 13px; background: rgba(20, 26, 35, .55);
  border-radius: 999px; padding: 6px 12px; font-variant-numeric: tabular-nums;
}
/* 右上角（关闭按钮下方）：− 百分比 ＋ 缩放 */
.lb-zoom { position: absolute; top: 64px; right: 24px; display: flex; align-items: center; gap: 8px; z-index: 3; }
.lb-btn {
  width: 38px; height: 38px; border-radius: 999px; padding: 0; font-family: inherit;
  border: 1px solid rgba(255, 255, 255, .35); background: rgba(20, 26, 35, .55);
  color: #fff; font-size: 20px; line-height: 1; cursor: pointer;
  display: grid; place-items: center;
}
.lb-btn:hover { background: rgba(20, 26, 35, .78); }
.lb-btn:disabled { opacity: .35; cursor: default; }
.lb-btn.lb-pct { width: auto; min-width: 58px; padding: 0 12px; font-size: 13px; }
@media (max-width: 620px) {
  .lb-zoom { top: 58px; right: 14px; gap: 6px; }
  .lb-btn { width: 42px; height: 42px; font-size: 22px; }
  .lb-btn.lb-pct { min-width: 52px; font-size: 12px; }
}


.photo-gallery { width: 100%; }
.photo-gallery-actions { margin: 10px 0 4px; display: flex; flex-wrap: wrap; gap: 10px; }
.photo-gallery-actions .btn.small {
  border-color: var(--line-strong); color: var(--text);
  background: #fff; font-weight: 500;
}
.photo-gallery-actions .btn.small:hover { border-color: var(--accent); color: var(--accent); background: #fff; }
.photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, 108px);
  gap: 10px;
}
.photo-gallery .slot {
  width: 108px; height: 108px;
  border: 1px solid var(--line-strong); border-radius: 8px;
  position: relative; overflow: hidden; background: #fff;
}
.photo-gallery .slot.filled img {
  width: 100%; height: 100%; object-fit: cover; display: block; cursor: zoom-in;
}
.photo-gallery .slot.empty {
  display: grid; place-items: center;
  border-style: dashed; color: var(--text-3); font-size: 24px;
  cursor: pointer; background: #FAFBFC;
}
.photo-gallery .slot.empty:hover { border-color: var(--accent); color: var(--accent); }
.photo-gallery .slot-del {
  position: absolute; top: 4px; right: 4px;
  width: 20px; height: 20px; border-radius: 50%;
  border: none; background: rgba(20,26,35,.55); color: #fff;
  font-size: 14px; line-height: 1; cursor: pointer; padding: 0;
  display: grid; place-items: center;
}
.photo-gallery .slot-del:hover { background: #e0453a; }
/* 附件窗口里的非图片（PDF 等）：图标 + 文件名，点击新窗口打开 */
.photo-gallery .slot.doc { display: block; }
.photo-gallery .slot .slot-doc {
  width: 100%; height: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; padding: 8px 6px; box-sizing: border-box;
  text-decoration: none; color: var(--text);
}
.photo-gallery .slot .slot-doc:hover { color: var(--accent); }
.photo-gallery .slot .slot-doc-icon { font-size: 26px; line-height: 1; }
.photo-gallery .slot .slot-doc-name {
  font-size: 11px; line-height: 1.35; text-align: center;
  word-break: break-all; max-height: 52px; overflow: hidden;
}
.thumb-wrap { position: relative; display: inline-block; }
.photo-count {
  position: absolute; right: -2px; bottom: -2px;
  background: var(--accent); color: #fff;
  font-size: 10px; padding: 1px 5px; border-radius: 8px; line-height: 1.4;
}

.empty { padding: 56px 20px; text-align: center; color: var(--text-3); font-size: 13px; }

/* 详情页：flex 列布局。高度用 min-height 而不是 height——内容比窗口高时
   （信息栅格高 + 明细表 min-height 140）让整页滚动，避免明细卡被 flex 压扁后
   .card 的 overflow:hidden 把表格连滚动条一起裁掉（2026-10-24 现场：矮窗口下
   明细只有表头可见、行滚不到）。窗口够高时行为与原来一致（卡片拉伸填满）。 */
.detail-view {
  display: flex; flex-direction: column; gap: 10px;
  min-height: max(calc(100vh - 54px), 660px);
}
.detail-view > section.card { display: flex; flex-direction: column; min-height: 0; flex: 1; }
.detail-view > section.card > .grid-wrap { flex: 1; min-height: 160px; }
/* 订单附件区按内容高度自适应（原来跟着 flex:1 一起撑高，下方空出一大片） */
.detail-view > section.card.order-attach { flex: 0 0 auto; }

.detail-head {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
}
.detail-title { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 200px; }
.detail-title h1 { margin: 0; font-size: 19px; font-weight: 500; }
.detail-actions { display: flex; gap: 8px; align-items: center; }

.info-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 16px 18px;
}
.info-item { display: flex; flex-direction: column; gap: 4px; }
.info-item.wide { grid-column: 1 / -1; }
.info-item span { font-size: 12px; color: var(--text-3); }
.info-item strong { font-size: 14px; font-weight: 500; color: var(--text); }
.info-item .amount { color: var(--accent); font-size: 16px; }

/* ============ 外包单汇总详情页 ============
   头部信息栅格（按内容高度自适应）+ 12 列明细表（横向滚动、行内编辑/新增/删除） */
.detail-sub { font-size: 12px; color: var(--text-3); }
/* 订单详情页标题下的「工程名称」同样用黑色（与列表副行一致） */
.detail-sub.detail-sub-pn { color: var(--text); }
/* 详情页里信息卡不参与 flex 平分，只占内容高度；明细表卡吃掉剩余高度 */
.detail-view > section.card.os-info-card { flex: 0 0 auto; }
.detail-view > section.card > .os-table-wrap { flex: 1; min-height: 140px; overflow: auto; }

/* 信息区：整体 4 列 —— 前 3 列是头部字段，第 4 列（右侧）放订单原件 */
.os-info-layout {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)) 158px;
  gap: 10px 20px; padding: 2px 18px 16px; align-items: start;
}
.os-info-grid {
  grid-column: 1 / 4;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px 20px;
}
.os-info-side { grid-column: 4; min-width: 0; }
/* 右侧第 4 列里的原件：缩略图铺满列宽、高度收紧，不再占一整行 */
.os-info-side .os-file-thumb { width: 100%; height: 88px; }
.os-info-item { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.os-info-item.os-info-wide { grid-column: 1 / -1; }
.os-info-k { font-size: 12px; color: var(--text-3); }
.os-info-v { font-size: 13.5px; color: var(--text); word-break: break-all; }
.os-info-v.os-pre { white-space: pre-wrap; line-height: 1.6; }

table.os-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13px; }
table.os-table thead th {
  position: sticky; top: 0; z-index: 2;
  background: #FAFBFC;
  padding: 0 8px 0 10px;
  height: 36px;
  white-space: nowrap;
  border-right: 1px solid var(--line-strong);
  border-bottom: 2px solid var(--line-strong);
  font-weight: 700; font-size: 12.5px; color: var(--text);
  text-align: left;
}
table.os-table thead th:last-child,
table.os-table tbody td:last-child { border-right: 0; }
table.os-table td {
  height: 32px; padding: 0 8px 0 10px;
  border-bottom: 1px solid var(--line);
  border-right: 1px solid var(--line);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 200px;
  color: var(--text);
}
table.os-table tbody tr:hover td { background: #F7FAFD; }
table.os-table td.num, table.os-table th.num {
  text-align: right; font-variant-numeric: tabular-nums;
}
table.os-table td.os-seq { width: 42px; min-width: 42px; text-align: center; color: var(--text-3); }
table.os-table td.os-amount { font-weight: 600; }
table.os-table td.ops { white-space: nowrap; text-align: right; }
/* 编辑/新增行：整行淡蓝底，输入框白底 */
table.os-table tr.os-editing td,
table.os-table tr.os-editing:hover td { background: var(--accent-soft); }
.os-in {
  width: 100%; height: 28px;
  border: 1px solid var(--line-strong); border-radius: 5px;
  padding: 0 6px; font: inherit; font-size: 12.5px;
  color: var(--text); background: #fff; outline: none;
}
.os-in:focus { border-color: var(--accent); }
.os-in.os-num { text-align: right; }
/* 空态：整行跨列，文字可换行 */
table.os-table td.empty {
  padding: 40px 16px; text-align: center; color: var(--text-3);
  white-space: normal; font-size: 13px;
}
/* 表尾总金额行 */
table.os-table tfoot td {
  border-top: 2px solid var(--line-strong);
  background: #FAFBFC;
  font-weight: 600; color: var(--text);
  height: 34px;
}
table.os-table tfoot td.os-amount { color: var(--accent); font-size: 14px; }
/* 订单原件附件：详情页缩略图 / 文件链接，列表里的「原件」按钮 */
.os-files { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.os-file-thumb {
  width: 76px; height: 56px; object-fit: cover; border-radius: 6px;
  border: 1px solid var(--line-strong); cursor: zoom-in; background: #F2F4F7;
}
.os-file-thumb:hover { border-color: var(--accent); }
.os-file-link { color: var(--accent); text-decoration: none; font-size: 13px; }
.os-file-link:hover { text-decoration: underline; }
th.col-file, td.col-file { width: 92px; min-width: 92px; text-align: center; }
td.col-file { white-space: nowrap; }
/* 采购订单「验收报告」列（窄列）：PDF 等非图片附件在列宽内省略，别把表格撑开 */
td.col-file .att-file-link { display: block; max-width: 84px; overflow: hidden; text-overflow: ellipsis; }
td.col-file .thumb-wrap { vertical-align: middle; }
/* 采购订单列表「验收报告」列：缩略图加一圈明显的外框（扫描件本身是白的，
   压在白底 / 淡黄底的行上看不出边界，加框后一眼就能看到这单有没有验收报告） */
td.col-file .accept-thumb {
  width: 44px; height: 44px; padding: 2px; background: #fff;
  border: 1px solid #AEB8C6; border-radius: 6px;
  box-shadow: 0 1px 2px rgba(16, 24, 40, .08);
}
td.col-file .accept-thumb:hover { border-color: var(--accent); }
button.os-file-btn { display: inline-flex; align-items: center; gap: 3px; }

/* 报账资料：详情页 5 行（行名 + 附件 + 上传/清空），列表里的进度小徽章 */
.list-actions { display: flex; align-items: center; gap: 8px; }
.os-doc-box { padding: 0 18px 14px; display: flex; flex-direction: column; gap: 8px; }
.os-doc-empty, .os-doc-none { font-size: 12.5px; color: var(--text-3); }
.os-doc-row {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  border: 1px solid var(--line); border-radius: 8px; padding: 8px 12px; background: #FAFBFC;
}
.os-doc-row.os-doc-todo { border-style: dashed; border-color: var(--line-strong); }
.os-doc-row.busy { opacity: .6; pointer-events: none; }
.os-doc-name { flex: 0 0 210px; font-size: 13.5px; color: var(--text); font-weight: 500; }
.os-doc-name > i { font-style: normal; color: var(--text-3); margin-right: 4px; }
.os-doc-hint { display: block; font-size: 11.5px; color: var(--text-3); font-weight: 400; margin-top: 2px; }
.os-doc-files { flex: 1 1 240px; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; min-width: 0; }
.os-doc-thumb {
  width: 64px; height: 48px; object-fit: cover; border-radius: 6px; cursor: zoom-in;
  border: 1px solid var(--line-strong); background: #F2F4F7;
}
.os-doc-thumb:hover { border-color: var(--accent); }
.os-doc-ops { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.os-doc-chip {
  display: inline-block; font-size: 12px; padding: 2px 8px; border-radius: 10px;
  background: #F2F4F7; color: var(--text-3); border: 1px solid var(--line);
}
.os-doc-chip.ok { background: #E8F6EE; color: #1F8A4C; border-color: #BFE3CE; }
/* 不含税金额与「总金额 − 税费」对不上时整项标红 */
.os-info-warn { background: #FFF4F4; border-radius: 6px; }
.os-info-warn .os-info-v { color: #D33; font-weight: 600; }
/* 外包单状态四态配色：进行中（蓝）/ 已完工（绿）/ 已报账（橙）/ 已结算（紫） */
.tag.os-st-0 { background: #E6F1FB; color: #185FA5; }
.tag.os-st-1 { background: #E8F6EE; color: #1F8A4C; }
.tag.os-st-2 { background: #FFF2E0; color: #B35C00; }
.tag.os-st-3 { background: #EFEAFA; color: #5B3FA8; }
/* 详情页头部的状态下拉：选了直接存，跟按钮一排 */
.os-status-sel {
  height: 34px; padding: 0 8px; border: 1px solid var(--line-strong); border-radius: 6px;
  background: #fff; color: var(--text); font-size: 13.5px; cursor: pointer;
}
.os-status-sel:focus { outline: none; border-color: var(--accent); }
.os-status-sel:disabled { opacity: .6; cursor: default; }
@media (max-width: 900px) {
  .os-doc-row { flex-direction: column; align-items: stretch; }
  .os-doc-name { flex: none; }
  .os-doc-ops { margin-left: 0; }
}

/* 外包单导入弹窗：第 1 步选原件 → 第 2 步核对识别结果
   注意：本规则必须放在 .modal 之后（同优先级，靠后生效）——
   早前放在前面被 .modal{max-width:600px} 覆盖，弹窗只有 600px 宽，
   明细表被挤到出横向滚动条、列看不全（2026-10-24 用户反馈）。 */
.os-imp-head {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px 16px; margin-bottom: 4px;
}
.os-imp-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.os-imp-field > label { font-size: 12px; color: var(--text-3); }
.os-imp-field.wide { grid-column: 1 / -1; }
.os-imp-ta {
  width: 100%; border: 1px solid var(--line-strong); border-radius: 6px;
  padding: 6px 8px; font: inherit; font-size: 12.5px; color: var(--text);
  background: #fff; outline: none; resize: vertical;
}
.os-imp-ta:focus { border-color: var(--accent); }
/* 明细预览表：横向可滚、纵向限高（行多时不顶飞弹窗） */
.os-imp-wrap { max-height: 42vh; overflow: auto; margin-top: 8px; }
.os-imp-wrap table.os-table td { padding: 2px 6px; height: 34px; }
/* 「单价 × 数量 ≠ 合计」的行：合计标红，提示识别可能有误 */
table.os-table td.os-imp-bad { color: #C0392B; background: #FDECEA; font-weight: 700; }
/* 导入预览：点选表格里的金额，点到的合计即「施工费」 */
table.os-table td.os-pick { cursor: pointer; user-select: none; }
table.os-table td.os-pick:hover { background: var(--accent-soft); }
table.os-table td.os-pick.picked { background: #E7F4EA; box-shadow: inset 0 0 0 1px #7BC48B; }
table.os-table td.os-pick.picked::after { content: " ✓"; color: #2E7D46; font-size: 11px; }
.os-pick-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 8px; }
.os-pick-chip {
  border: 1px dashed var(--line-strong); background: #fff; color: var(--text);
  border-radius: 999px; padding: 5px 14px; font-size: 12.5px; cursor: pointer;
}
.os-pick-chip:hover { border-color: var(--accent); color: var(--accent); }
.os-pick-chip.on { border-style: solid; border-color: #2E7D46; background: #E7F4EA; color: #2E7D46; font-weight: 600; }
.os-pick-hint { font-size: 12px; color: var(--text-3); }
@media (max-width: 900px) {
  .os-info-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-column: 1 / -1; }
  /* 手机上第 4 列（订单原件）挪到字段区下面，不再并排挤 */
  .os-info-layout { grid-template-columns: minmax(0, 1fr); }
  .os-info-side { grid-column: 1; }
  .os-info-side .os-file-thumb { height: 120px; }
  .os-imp-head { grid-template-columns: repeat(2, 1fr); }
  .os-imp-wrap { max-height: 46vh; }
}

.list-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; padding: 16px 18px 12px;
}
.list-head h2 { margin: 0; font-size: 15px; font-weight: 500; }
.list-head .sub { font-size: 12px; color: var(--text-3); margin-top: 3px; }
/* 附件区标题行也收紧 */
.order-attach > .list-head { padding: 10px 14px 6px; align-items: baseline; }
.order-attach > .list-head .sub { margin-top: 2px; font-size: 11.5px; }

/* 订单附件区（材料单 / 工程订单 / 外包订单）
   紧凑版：整区按内容高度自适应、缩略图小一号、上传按钮并排更窄，
   让下面的「工程施工清单」表格尽量往上占屏 */
.att-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 10px; padding: 0 14px 12px;
}
.att-block {
  border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px 10px;
  background: var(--bg-soft, #FAFBFC);
}
.att-title {
  font-size: 13px; font-weight: 500; margin-bottom: 6px;
  display: flex; align-items: center; gap: 6px;
}
.att-title .att-count {
  font-size: 11px; color: var(--text-3);
  background: var(--line); border-radius: 8px; padding: 0 6px; line-height: 1.6;
}
.att-items { display: flex; flex-wrap: wrap; gap: 6px; align-items: flex-start; }
.att-none { font-size: 12px; color: var(--text-3); }
/* 每栏直接上传：📷 大按钮（手机点一下调相机）+ 🖼 / 📄 小按钮 */
.att-actions { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 8px; }
.att-cam, .att-mini {
  display: inline-flex; align-items: center; gap: 4px; cursor: pointer;
  border-radius: 6px; font-size: 12px; user-select: none; line-height: 1.4;
}
.att-cam {
  padding: 8px 14px; background: var(--accent); color: #fff;
  border: 1px solid var(--accent); font-weight: 500;
}
.att-cam:hover { filter: brightness(1.08); }
.att-mini { padding: 7px 10px; background: #fff; color: var(--text); border: 1px solid var(--line-strong); }
.att-mini:hover { color: var(--accent); border-color: var(--accent); }
/* 上传中：本栏入口全禁用，标题右侧提示 */
.att-block.busy .att-cam, .att-block.busy .att-mini { opacity: .55; pointer-events: none; }
.att-block.busy > .att-title::after {
  content: '上传中…'; margin-left: auto; font-size: 11px; color: var(--accent); font-weight: 400;
}
/* 手机（拍照主要在手机上）：每栏独占一行铺满，📷 按钮加大到好点 */
@media (max-width: 620px) {
  .att-grid { grid-template-columns: 1fr; }
  .att-cam { padding: 10px 16px; font-size: 13.5px; }
  .att-mini { padding: 9px 12px; }
  .att-actions { gap: 6px; }
}

/* 缩略图 / 文件卡上的删除小钮 */
.att-thumb { position: relative; }
.att-del {
  position: absolute; top: 3px; right: 3px; width: 20px; height: 20px;
  border: 0; border-radius: 50%; background: rgba(0,0,0,.55); color: #fff;
  font-size: 13px; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center; padding: 0;
}
.att-del:hover { background: var(--danger, #D4380D); }
.att-file { position: relative; display: inline-flex; align-items: center; gap: 5px; padding-right: 30px; }
.att-file .att-del { position: static; background: var(--line-strong); color: var(--text); width: 18px; height: 18px; }
.att-file .att-del:hover { background: var(--danger, #D4380D); color: #fff; }
.att-file-link {
  display: inline-flex; align-items: center; gap: 5px; max-width: 100%;
  font-size: 12px; color: var(--text); text-decoration: none;
  border: 1px solid var(--line-strong); border-radius: 6px;
  padding: 6px 10px; background: #fff;
}
.att-file-link:hover { color: var(--accent); border-color: var(--accent); }
.att-thumb {
  width: 56px; height: 56px; border-radius: 6px; overflow: hidden;
  border: 1px solid var(--line-strong); display: block; background: #fff;
}
.att-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; cursor: zoom-in; }
.info-grid.flat {
  border: 0; border-radius: 0; background: transparent;
  padding: 4px 18px 16px; border-bottom: 1px solid var(--line);
}

.import-steps { display: flex; flex-direction: column; gap: 14px; }
.step { display: none; }
.step.show { display: block; }
.step-title { font-size: 13px; font-weight: 500; color: var(--text); margin-bottom: 8px; }
.step-note { font-size: 12px; color: var(--text-3); line-height: 1.7; }
.map-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.map-row label { width: 88px; font-size: 12px; color: var(--text-2); }
.map-row select { flex: 1; }
.map-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.map-table th, .map-table td { border: 1px solid var(--line); padding: 6px 8px; text-align: left; }
.map-table th { background: #FAFBFC; color: var(--text-2); font-weight: 500; }
.row-ok { color: #12694A; }
.row-bad { color: var(--danger); }
.chk { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-2); }
.file-drop {
  border: 1px dashed var(--line-strong); border-radius: 10px;
  padding: 22px; text-align: center; background: #FAFBFC;
}
.file-drop .btn { margin-top: 10px; }

@media (max-width: 900px) {
  .info-grid { grid-template-columns: 1fr 1fr; }
  .detail-head { align-items: flex-start; }
}

.pager {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 14px;
  border-top: 1px solid var(--line);
  font-size: 12px; color: var(--text-3);
}
.pager .pg-btns { display: flex; gap: 6px; }
.pager button {
  border: 1px solid var(--line-strong); background: #fff; color: var(--text-2);
  border-radius: 6px; height: 28px; padding: 0 10px; font: inherit; font-size: 12px; cursor: pointer;
}
.pager button:disabled { opacity: .45; cursor: not-allowed; }

.overlay {
  position: fixed; inset: 0; background: rgba(23, 28, 36, .38);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 6vh 16px 24px; overflow-y: auto; z-index: 50;
}

.modal {
  background: #fff; border-radius: 14px;
  width: 100%; max-width: 600px;
  box-shadow: 0 12px 40px rgba(20, 26, 35, .18);
}
/* 外包单导入弹窗：加宽到能把 11 列明细一次看全（列宽合计约 1160px + 内边距）
   —— 必须写在 .modal 之后，否则被上面的 max-width:600px 覆盖。 */
.os-imp-modal { width: 96vw; max-width: 1280px; }
/* 含接口端口的表单：加宽铺满，端口行不再挤在半列 */
.modal.has-ports { max-width: min(1100px, 94vw); }
/* 施工日志这类只带「监控对象行」的表单：保持普通宽度，单列更好填 */
.modal.has-targets { max-width: 600px; }
.modal-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 22px 14px; border-bottom: 1px solid var(--line);
}
.modal-head h2 { margin: 0; font-size: 15px; font-weight: 500; }
.modal-head .sub { font-size: 12px; color: var(--text-3); margin-top: 3px; }
.close {
  border: 0; background: transparent; font-size: 20px; line-height: 1;
  color: var(--text-3); cursor: pointer; padding: 2px 6px; border-radius: 6px;
}
.close:hover { background: #F1F3F6; color: var(--text); }

.modal-body { padding: 18px 22px 6px; }
/* 表单一律单列：一行一个字段，不左右分割（主要在手机上填，窄屏更好填） */
.grid { display: grid; grid-template-columns: 1fr; gap: 14px; }
.field.wide { grid-column: 1 / -1; }
.field label { display: block; font-size: 13px; font-weight: 600; color: var(--text); margin-bottom: 6px; }
.field label .req { color: var(--danger); margin-left: 3px; }
.field label .note { font-weight: 400; font-size: 12px; color: var(--text-3); margin-left: 2px; }
.field input, .field select, .field textarea {
  width: 100%; border: 1px solid var(--line-strong); border-radius: 8px;
  padding: 8px 10px; font: inherit; font-size: 13px; color: var(--text); background: #fff;
  outline: none;
}
.field input:focus, .field select:focus, .field textarea:focus {
  border-color: var(--accent); box-shadow: 0 0 0 3px rgba(24, 95, 165, .12);
}
.field textarea { resize: vertical; min-height: 68px; }
.field .hint { font-size: 11px; color: var(--text-3); margin-top: 4px; }
.field.err input, .field.err select { border-color: var(--danger); }
.field .msg { font-size: 11px; color: var(--danger); margin-top: 4px; display: none; }
/* 下拉选项（如 FSU型号 / 状态）展开时加边框与底色，选择时更清楚；选中后控件本身不加底色 */
.field select option, select.col-status option {
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--text);
  padding: 4px 6px;
}
.field.err .msg { display: block; }

/* 遗留问题等警示面板：橙色浅底 + 左侧粗橙条，说明内联在标签后 */
.field.warn-field {
  background: #FCF2E3; border: 1px solid #F3DDBE; border-left: 4px solid #E8A23D;
  border-radius: 10px; padding: 12px 14px 14px;
}
.field.warn-field label { color: #B9791F; }
.field.warn-field label .note { color: #C9882B; font-weight: 500; }
.field.warn-field textarea { background: #fff; }

/* 重点字段强调面板（施工备注等）：蓝色浅底 + 左侧粗蓝条，同遗留问题样式 */
.field.info-field {
  background: #EDF4FC; border: 1px solid #C9DEF5; border-left: 4px solid #4A90D9;
  border-radius: 10px; padding: 12px 14px 14px;
}
.field.info-field label { color: #2B6CB0; }
.field.info-field label .note { color: #5A8FC4; font-weight: 500; }
.field.info-field textarea { background: #fff; }
/* 模板方案下拉：青色底（仅施工日志表单这一处） */
.field[data-field="port_template_id"] select {
  background: #D8F3F5; border-color: #7FCBD3;
}
.field[data-field="port_template_id"] select:focus {
  border-color: #3FA9B5; box-shadow: 0 0 0 3px rgba(63, 169, 181, .18);
}
/* 选「利旧」时模板方案禁用：灰底、置灰、禁用光标 */
.field[data-field="port_template_id"] select:disabled,
.field.disabled-field select:disabled {
  background: #EEF1F3; border-color: var(--line); color: #9AA3AB;
  box-shadow: none; cursor: not-allowed;
}
/* 勾选组（新增 / 利旧）：手机上好点的大块勾选 */
.check-pair { display: flex; align-items: center; gap: 26px; flex-wrap: wrap; }
.contact-box { display: flex; flex-direction: column; gap: 8px; }
.contact-rows { display: flex; flex-direction: column; gap: 8px; }
.contact-row { display: flex; align-items: center; gap: 8px; }
.contact-row .ct-name { flex: 1 1 0; min-width: 0; }
.contact-row .ct-phone { flex: 1 1 0; min-width: 0; }
.contact-row .ct-del { flex: none; }
/* 列表里的联系人：每个联系人独占一行（姓名 + 电话） */
td.ct-cell { vertical-align: top; }
td.ct-cell .ct-line {
  display: block; white-space: nowrap; line-height: 1.6;
}
td.ct-cell .ct-line + .ct-line { color: var(--text-2); }
/* 列表里的多行文本（开票信息等）：按原换行显示，限宽避免撑爆表格 */
td.cell-pre {
  white-space: pre-line; vertical-align: top; line-height: 1.5;
  max-width: 320px; overflow-wrap: anywhere;
}
/* 派单号（400派单清单）：表单里一行一个，行数跟着「派单数量」走 */
.nos-box { display: flex; flex-direction: column; gap: 8px; }
.nos-rows { display: flex; flex-direction: column; gap: 8px; }
.nos-row { display: flex; align-items: center; gap: 8px; }
.nos-row .nos-idx { flex: none; width: 54px; font-size: 12px; color: var(--text-3); }
.nos-row .nos-input { flex: 1 1 auto; min-width: 0; }
.nos-empty { font-size: 12px; color: var(--text-3); line-height: 1.5; }
/* 列表里的派单号：一个一行，前面带序号 */
td.nos-cell { vertical-align: top; }
td.nos-cell .nos-line { white-space: nowrap; line-height: 1.6; }
td.nos-cell .nos-line i { font-style: normal; color: var(--text-3); margin-right: 4px; }

/* 400派单清单：行内直接编辑派单数量/派单号（失焦自动保存） */
.nos-cnt-in {
  width: 64px; padding: 3px 6px; font-size: 12.5px; color: var(--text);
  border: 1px solid var(--line-strong); border-radius: 5px; background: #fff;
}
.nos-cnt-in:focus { outline: none; border-color: var(--accent); }
.nos-inline { min-width: 150px; }
.nos-inline-hint { font-size: 12px; color: var(--text-3); white-space: nowrap; }
.nos-row-inline { display: flex; align-items: center; gap: 4px; margin-bottom: 4px; }
.nos-row-inline:last-child { margin-bottom: 0; }
.nos-row-inline i {
  font-style: normal; color: var(--text-3); font-size: 11px;
  min-width: 16px; text-align: right; flex: none;
}
.nos-in {
  width: 132px; padding: 3px 6px; font-size: 12.5px; color: var(--text);
  border: 1px solid var(--line-strong); border-radius: 5px; background: #fff;
}
.nos-in:focus { outline: none; border-color: var(--accent); }
/* ---------- 单据互跳链接（第 175 节，2026-10-28） ----------
   采购订单「外包单号」、外包单「采购订单号」、施工日志「关联工单」：
   长得跟普通链接一样，但点了会切到对应模块并打开那张单的详情 */
.jump-link { cursor: pointer; text-decoration: underline; text-decoration-style: dotted; }
.jump-link:hover { text-decoration-style: solid; }
   选项来自本城市 400维修单 的单号（单号比较长，比原来的手填框宽一点才显示得全） */
select.nos-in, select.nos-input { width: 190px; cursor: pointer; }
@media (max-width: 620px) {
  .nos-in { width: 118px; font-size: 15px; }
  select.nos-in { width: 152px; font-size: 15px; }
}
td.num-cell { white-space: nowrap; }
@media (max-width: 620px) {
  .contact-row { gap: 6px; }
  .contact-row .ct-name, .contact-row .ct-phone { font-size: 15px; }
  .nos-row { gap: 6px; }
  .nos-row .nos-input { font-size: 15px; }
}

.check-item {
  display: inline-flex; align-items: center; gap: 14px; cursor: pointer;
  border: 1px solid var(--line-strong); border-radius: 999px;
  padding: 8px 20px 8px 16px; font-size: 13.5px; color: var(--text-2); background: #fff;
  user-select: none; -webkit-user-select: none;
}
.check-item input { width: 16px; height: 16px; accent-color: var(--accent); margin: 0; flex: none; }
.check-item:has(input:checked), .check-item.on {
  border-color: var(--accent); color: var(--accent); background: var(--accent-soft);
}
@media (max-width: 620px) {
  .check-item { padding: 9px 16px; font-size: 14.5px; }
}
/* 二选一按钮（接入方式：新增/接入智能）：无勾选框，选中深蓝底白字 */
.check-pair.single { gap: 26px; }
.check-pair.single .check-item {
  border: 1px solid var(--line-strong); color: var(--text);
  padding: 9px 26px; font-size: 13.5px; font-weight: 600;
}
.check-pair.single .check-item:hover { border-color: var(--accent); color: var(--accent); }
.check-pair.single .check-item.on,
.check-pair.single .check-item.on:hover {
  background: #1D5FA9; border-color: #1D5FA9; color: #fff;
}

.modal-foot {
  display: flex; align-items: center; justify-content: flex-end; gap: 8px;
  padding: 14px 22px 18px; border-top: 1px solid var(--line); margin-top: 12px;
}
/* 表单底部主按钮：绿色「保存」（设计稿样式），其余 primary 按钮保持蓝色 */
.modal-foot .btn.primary { background: #3F9B4F; border-color: #3F9B4F; }
.modal-foot .btn.primary:hover { background: #35813F; border-color: #35813F; }
.modal-foot .btn.primary:disabled { background: #9CC7A3; border-color: #9CC7A3; }
.form-error {
  margin: 0 22px; padding: 9px 12px; border-radius: 8px;
  background: var(--danger-soft); color: #8E2A20; font-size: 12.5px; display: none;
}
.form-error.show { display: block; }

/* 手机端弹窗：铺满宽度、内边距收紧；输入框 16px 防止 iOS 聚焦时自动放大 */
@media (max-width: 620px) {
  .overlay { padding: 10px 10px 20px; }
  .modal { max-width: 100%; }
  .modal-head { padding: 14px 14px 12px; }
  .modal-body { padding: 14px 14px 6px; }
  .form-error { margin: 0 14px; }
  .modal-foot { padding: 12px 14px 14px; }
  .field label { font-size: 12.5px; }
  .field input, .field select, .field textarea { font-size: 16px; padding: 9px 10px; }
  .field textarea { min-height: 84px; }
  .modal-foot .btn { flex: 1; justify-content: center; }
}

.confirm-box { max-width: 420px; padding-bottom: 4px; }
.confirm-box p { margin: 0; font-size: 13px; color: var(--text-2); line-height: 1.7; }
.confirm-box strong { color: var(--text); }

/* 模板方案管理弹窗 */
/* ---------- 企业微信推送配置弹窗 ---------- */
.wc-modal { max-width: 720px; }
.wc-loading { color: var(--text-3); font-size: 13px; padding: 8px 0; }
.wc-city {
  border: 1px solid var(--line); border-radius: 10px;
  padding: 12px 14px; margin-bottom: 14px; background: #FCFDFE;
}
.wc-city-h { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.wc-city-h b { font-size: 15px; font-weight: 600; }
.wc-state { font-size: 12px; padding: 1px 9px; border-radius: 999px; }
.wc-state.on { background: #E7F6EC; color: #1D7A3C; border: 1px solid #B7DCC3; }
.wc-state.off { background: #F1F3F6; color: var(--text-3); border: 1px solid var(--line); }
.wc-warn { font-size: 12px; color: #C87A1E; }
.wc-url { font-size: 12px; }
.wc-row { display: flex; gap: 14px; flex-wrap: wrap; margin: 8px 0; }
.wc-chk { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; color: var(--text-2); cursor: pointer; }
.wc-chk input { width: 15px; height: 15px; accent-color: var(--accent); }
.wc-acts { display: flex; gap: 8px; flex-wrap: wrap; }
.wc-out { margin-top: 8px; font-size: 13px; }
.wc-ok { color: #1D7A3C; font-weight: 600; }
.wc-bad { color: var(--danger); font-weight: 600; }
.wc-doing { color: var(--text-3); }
.wc-prev-title { font-size: 12px; color: var(--text-3); margin-bottom: 4px; }
/* 按人拆的预览：每人一个名字 + 一段正文 */
.wc-prev-name { font-size: 12.5px; font-weight: 600; margin: 10px 0 4px; }
.wc-prev-name:first-of-type { margin-top: 4px; }
.wc-prev {
  margin: 0; padding: 10px 12px; background: #F7F9FB;
  border: 1px solid var(--line); border-radius: 8px;
  font-size: 12.5px; line-height: 1.7; white-space: pre-wrap; word-break: break-word;
  max-height: 260px; overflow-y: auto;
}
.wc-logs { border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.wc-log-row {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 10px; font-size: 12.5px; border-bottom: 1px solid #F1F3F6;
}
.wc-log-row:last-child { border-bottom: 0; }
.wc-flag { flex: none; font-size: 11px; padding: 0 7px; border-radius: 999px; }
.wc-flag.ok { background: #E7F6EC; color: #1D7A3C; }
.wc-flag.bad { background: var(--danger-soft); color: var(--danger); }
.wc-when { flex: none; color: var(--text-3); }
.wc-msg { flex: 1; min-width: 0; color: var(--text-2); word-break: break-word; }

.tpl-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.tpl-table th, .tpl-table td { text-align: left; padding: 9px 10px; border-bottom: 1px solid var(--line); }
.tpl-table th { font-size: 11.5px; color: var(--text-3); font-weight: 500; }
.tpl-table tr:last-child td { border-bottom: 0; }
.tpl-actions { white-space: nowrap; text-align: right; }
.tpl-actions .btn + .btn { margin-left: 6px; }
.tpl-empty { color: var(--text-3); font-size: 13px; padding: 26px 0; text-align: center;
  border: 1px dashed var(--line-strong); border-radius: 10px; }

/* 模板方案列表：绑定内容列（左边「智能监控对象」、右边「非智能监控对象」两竖排） */
.tg-bind { display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
/* 两列等宽（flex-basis:0 + grow:1）：不管各方案条目长短，所有行的左右分栏线都在同一位置；
   min-width 保证窄屏放不下时自动回落成上下两排 */
.tg-col { flex: 1 1 0; min-width: 240px; }
.tg-head {
  font-size: 11.5px; font-weight: 600; white-space: nowrap;
  padding-bottom: 3px; margin-bottom: 3px; border-bottom: 1px solid var(--line);
}
.tg-head.smart { color: #1B6FC8; }
.tg-head.nonsmart { color: #6B7C93; }
.tg-cnt { color: var(--text-3); font-weight: 400; margin-left: 6px; }
/* 模板方案里的明细允许在列内折行（施工日志列表的 .tg-line 仍是 nowrap 不受影响），
   否则超长条目会把列撑宽，各方案的左右分栏线就不齐了 */
.tg-bind .tg-line { white-space: normal; overflow-wrap: anywhere; line-height: 1.6; }
.tg-line.tg-empty { color: var(--text-3); }

/* ---------- 列表常驻横向滚动条 ----------
   原生横向滚动条在 .table-wrap 的底部 = 整张表格的最下面，
   页面不滚到底根本看不到。这条 fixed 在视口底部，始终可见，与表格双向同步。 */
.hscroll-bar {
  position: fixed; bottom: 0; z-index: 60; height: 14px;
  overflow-x: auto; overflow-y: hidden;
  background: #F7F8FA; border-top: 1px solid var(--line);
  overscroll-behavior-x: contain;
}
.hscroll-bar[hidden] { display: none; }
.hscroll-inner { height: 1px; }
.hscroll-bar::-webkit-scrollbar { height: 12px; }
.hscroll-bar::-webkit-scrollbar-track { background: #F1F3F6; }
.hscroll-bar::-webkit-scrollbar-thumb {
  background: #B6BCC8; border-radius: 6px; border: 2px solid #F1F3F6;
}
.hscroll-bar::-webkit-scrollbar-thumb:hover { background: #8A93A3; }
/* 有这条常驻滚动条时，页面底部留出让位，别盖住分页栏 */
body.has-hbar { padding-bottom: 18px; }
/* 窄屏（手机）直接手指滑表格就行，不占位 */
@media (max-width: 900px) { .hscroll-bar { display: none !important; } }

.toast-root {
  position: fixed; top: 18px; right: 20px; z-index: 90;
  display: flex; flex-direction: column; gap: 8px;
}
.toast {
  background: #1F2328; color: #fff;
  padding: 10px 14px; border-radius: 9px; font-size: 13px;
  box-shadow: 0 6px 20px rgba(20, 26, 35, .22);
  animation: pop .16s ease-out;
  max-width: 380px;
}
.toast.ok { background: #12694A; }
.toast.err { background: #A32D2D; }

@keyframes pop { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }

@media (max-width: 900px) {
  .app { flex-direction: column; }
  .sidebar { width: auto; flex: none; height: auto; position: static; }
  /* 手机端隐藏底部状态行（本地 SQLite · 已连接）：纯信息、与操作无关。
     但 ICP 备案号必须保留（2026-11-05 备案通过）——只隐藏状态，备案号居中显示一行。 */
  .sidebar-foot {
    display: flex; justify-content: center;
    padding: 4px 10px 8px; border-top: 0;
  }
  .sidebar-foot .foot-status { display: none; }
  .sidebar-foot .beian-link { flex: 0 0 auto; font-size: 11px; color: rgba(255,255,255,.62); }
  /* 施工人员视角（2026-10-27（153））：菜单已有「施工日志 + 收货信息」两项，
     不再隐藏——与其他账号一样走底部横向菜单行（.nav 已改横向滚动）。
     admin / 城市账号 / 拍照账号不能隐藏——手机端这是切换菜单的唯一入口 */
  .brand-acct { display: inline-flex; }
  /* 施工人员 / 拍照账号手机端：入口已上移到标题行右侧，右上角账号区不再重复显示 */
  body.staff-mode .brand-staff,
  body.photo-mode .brand-staff { display: inline-flex; }
  body.staff-mode .account-chip,
  body.photo-mode .account-chip { display: none; }
  /* 施工人员 / 拍照账号标题行要塞下几个入口：收起「基础数据管理」副标题腾空间，实在不够才换行 */
  body.staff-mode .brand-text small,
  body.photo-mode .brand-text small { display: none; }
  body.staff-mode .brand,
  body.photo-mode .brand { flex-wrap: wrap; row-gap: 6px; }
  .nav { flex-direction: row; overflow-x: auto; padding: 10px; }
  .nav button { width: auto; white-space: nowrap; }
  .nav .count { display: none; }
  .nav-group {
    padding: 0 10px; display: flex; align-items: center;
    white-space: nowrap; letter-spacing: .04em;
  }
  .nav-group::after {
    content: ''; width: 1px; height: 16px; background: var(--line);
    margin-left: 10px;
  }
  /* 移动端横向导航：快速查询板块改为整行堆叠，避免被挤成横向一行 */
  .nav-quick { flex: 1 0 100%; margin-top: 4px; border-top: 0; }
  .nav-quick-item { width: auto; white-space: nowrap; padding-left: 12px; }
  .main { padding: 16px; }
  .grid { grid-template-columns: 1fr; }
  .search input { width: 130px; }
}

/* ---------- 站点明细：Excel 式可编辑表格 ---------- */
.grid-wrap {
  overflow: auto;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: #fff;
}
table.sitegrid { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13px; }
table.sitegrid thead th {
  position: sticky; top: 0; z-index: 2;
  background: #FAFBFC;
  padding: 0 8px 0 10px;
  height: 36px;
  white-space: nowrap;
  /* 行列都有线条：右侧线 + 表头下方线 */
  border-right: 1px solid var(--line-strong);
  border-bottom: 2px solid var(--line-strong);
  font-weight: 700; font-size: 12.5px; color: var(--text);
  text-align: left;
}
table.sitegrid thead th:last-child,
table.sitegrid tbody td:last-child { border-right: 0; }
table.sitegrid thead th .g-th-label {
  display: inline-flex; align-items: center;
  padding-right: 16px;           /* 避开右侧筛选箭头 */
  max-width: calc(100% - 20px);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
table.sitegrid thead th .req { color: var(--danger); margin-left: 3px; font-style: normal; }
table.sitegrid td {
  height: 32px; padding: 0 8px 0 10px;
  border-bottom: 1px solid var(--line);
  border-right: 1px solid var(--line);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 260px;
  cursor: cell; color: var(--text);
}
table.sitegrid tbody tr:hover td { background: #F7FAFD; }
table.sitegrid td.g-idx, table.sitegrid th.g-idx {
  width: 42px; min-width: 42px; text-align: center;
  color: var(--text-3); cursor: default;
}
/* 冻结左侧 4 列：左右拖动时不跟着滚（列宽动态，left 由 JS 量出后写在行内） */
table.sitegrid th.frz, table.sitegrid td.frz {
  position: sticky;
  z-index: 2;
  background: #fff;
  box-shadow: 1px 0 0 var(--line-strong);   /* 冻结区右边缘的分隔线 */
}
table.sitegrid thead th.frz { z-index: 4; background: #FAFBFC; }
table.sitegrid tbody tr:hover td.frz { background: #F7FAFD; }
tr.g-ghost td.frz { background: #FCFDFE; }
table.sitegrid td.frz.editing { z-index: 5; }
/* 表头里的序号列同样加粗（td 才用浅灰） */
table.sitegrid th.g-idx { color: var(--text); font-weight: 700; }
table.sitegrid td.g-ops, table.sitegrid th.g-ops {
  width: 34px; min-width: 34px; text-align: center; padding: 0;
}
tr.g-ghost td { border-bottom: 0; border-top: 1px dashed var(--line-strong); background: #FCFDFE; }
.g-ghost-hint { color: #C3CAD4; font-size: 12px; }
.g-ghost-hint.miss { color: #B8860B; }
td.editing { padding: 0; overflow: visible; background: #fff !important; }
.g-editor {
  width: 100%; height: 100%; min-height: 30px;
  border: 2px solid var(--accent); outline: none;
  padding: 0 6px; font: inherit; font-size: 13px; color: var(--text);
  background: #fff; border-radius: 3px;
}
td.err, td.err:hover { background: var(--danger-soft); }
td.err .g-editor { border-color: var(--danger); }
.row-del {
  border: 0; background: transparent; cursor: pointer;
  color: #C3CAD4; font-size: 15px; line-height: 1;
  width: 22px; height: 22px; border-radius: 6px; padding: 0;
}
.row-del:hover { background: var(--danger-soft); color: var(--danger); }
.funnel {
  position: absolute; top: 50%; right: 10px;
  transform: translateY(-50%);
  border: 0; background: transparent; cursor: pointer;
  color: #AEB7C4; font-size: 15px; line-height: 1;
  padding: 2px 5px; border-radius: 5px; z-index: 2;
}
.funnel:hover { background: #EDF0F4; color: var(--text-2); }
.funnel.on { color: var(--accent); background: var(--accent-soft); }
.grid-status {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  padding: 10px 16px; font-size: 12px; color: var(--text-3);
}
.grid-status b { color: var(--text-2); font-weight: 500; }
.grid-status .g-hint { color: #A6AEBA; }
.grid-status .g-saved { color: #12694A; }

/* 列筛选弹层 */
.filter-pop {
  position: fixed; z-index: 120;
  background: #fff; border: 1px solid var(--line-strong); border-radius: 10px;
  box-shadow: 0 10px 32px rgba(20, 26, 35, .16);
  font-size: 13px; display: flex; flex-direction: column;
  max-height: 340px;
}
.fp-head { display: flex; gap: 8px; padding: 10px 10px 6px; align-items: center; }
.fp-head input {
  flex: 1; border: 1px solid var(--line-strong); border-radius: 7px;
  padding: 6px 9px; font: inherit; font-size: 12.5px; outline: none; color: var(--text);
}
.fp-head input:focus { border-color: var(--accent); }
.fp-actions {
  display: flex; align-items: center; gap: 10px;
  padding: 2px 12px 8px; border-bottom: 1px solid var(--line);
}
.fp-count { margin-left: auto; font-size: 11.5px; color: var(--text-3); }
.fp-link {
  border: 0; background: transparent; color: var(--accent); cursor: pointer;
  font: inherit; font-size: 12px; padding: 2px 4px; border-radius: 5px;
}
.fp-link:hover { background: var(--accent-soft); }
.fp-list { overflow-y: auto; padding: 6px 0; }
.fp-item { display: flex; align-items: center; gap: 8px; padding: 5px 12px; cursor: pointer; font-size: 12.5px; }
.fp-item:hover { background: #F4F6F9; }
.fp-item input { margin: 0; flex: none; }
.fp-item span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fp-empty { padding: 14px; text-align: center; color: var(--text-3); font-size: 12px; }
.fp-foot { padding: 8px 10px; border-top: 1px solid var(--line); text-align: right; }

.toast { display: flex; align-items: center; gap: 10px; }
.toast-act {
  border: 1px solid rgba(255, 255, 255, .5); background: transparent; color: #fff;
  font: inherit; font-size: 12px; padding: 3px 10px; border-radius: 6px; cursor: pointer; flex: none;
}
.toast-act:hover { background: rgba(255, 255, 255, .18); }

/* 列管理 */
.col-add { margin-top: 14px; padding-top: 14px; border-top: 1px dashed var(--line); }
.col-add .add-grid { display: flex; gap: 8px; margin: 8px 0; }
.col-add .add-grid input, .col-add .add-grid select {
  flex: 1; min-width: 0; padding: 8px 10px; border: 1px solid var(--line-strong);
  border-radius: 8px; font: inherit; background: #fff; color: var(--text);
}
.col-add textarea {
  width: 100%; padding: 8px 10px; border: 1px solid var(--line-strong); border-radius: 8px;
  font: inherit; resize: vertical; background: #fff; color: var(--text);
}
.col-list { margin: 4px 0; }
.col-empty { padding: 14px; text-align: center; color: var(--text-3); font-size: 12.5px; }
.col-list-head {
  display: flex; align-items: center; gap: 10px; padding: 2px 12px 6px; margin-top: 2px;
  color: var(--text-3); font-size: 12px;
}
.col-list-head span:nth-child(1) { flex: 1; min-width: 0; }
.col-list-head span:nth-child(2) { flex: none; width: 150px; }
.col-list-head span:nth-child(3) { flex: none; width: 26px; }
.col-item {
  display: flex; align-items: center; gap: 10px; padding: 7px 12px; margin: 6px 0;
  background: var(--bg); border: 1px solid var(--line); border-radius: 8px;
}
.col-item .col-name-input {
  flex: 1; min-width: 0; padding: 6px 9px; border: 1px solid var(--line-strong);
  border-radius: 7px; font: inherit; background: #fff; color: var(--text);
}
.col-item .col-name-input:focus { border-color: var(--primary); outline: none; }
.col-item .col-type { color: var(--text-3); font-size: 12px; flex: none; width: 150px; }
.col-item .row-del {
  margin-left: auto; border: 0; background: var(--danger-soft); color: var(--danger);
  width: 26px; height: 26px; border-radius: 6px; font-size: 16px; line-height: 1; cursor: pointer; flex: none;
}
.col-item .row-del:hover { background: #F6D7D3; }
.col-note { margin-top: 12px; }

/* ---------- 树形分类工作区：表格 + 树合成一整块 ---------- */
.body-row { display: flex; gap: 16px; align-items: flex-start; }
.body-row > .card { flex: 1; min-width: 0; }

/* 有树时：整块面板，表格与树左右并列、上下贯通整高，中间一条分隔线 */
.body-row.has-tree {
  gap: 0; align-items: stretch;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  min-height: calc(100vh - 196px);
}
.body-row.has-tree > .card {
  display: flex; flex-direction: column; min-width: 0;
  border: 0; border-radius: 0; background: transparent;
}
.body-row.has-tree .table-wrap { flex: 1; overflow: auto; }
.body-row.has-tree .pager { flex: none; }

.tree-panel {
  width: 236px; flex: 0 0 236px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 12px 10px; max-height: calc(100vh - 170px); overflow-y: auto;
}
.tree-panel[hidden] { display: none; }

/* 合成整块后的树：通栏到底、独立滚动，靠分隔线与表格区分 */
.body-row.has-tree > .tree-panel {
  width: 272px; flex: 0 0 272px; align-self: stretch;
  border: 0; border-left: 1px solid var(--line); border-radius: 0;
  background: var(--bg);
  max-height: none;
}
.body-row.has-tree > .tree-panel:not(.tree-right) {
  border-left: 0; border-right: 1px solid var(--line);
}

.tree-head {
  font-size: 12px; font-weight: 600; color: var(--text-3);
  letter-spacing: .06em; padding: 2px 8px 10px;
}
/* 厂家设备型号：左侧筛选条（发货厂家 / 设备对象 / 设备类别） */
.model-filters {
  padding: 10px 10px 12px; border-bottom: 1px solid var(--line);
  background: var(--panel-2, #FBFCFE); margin-bottom: 4px;
}
.model-filters .mf-title {
  font-size: 12px; font-weight: 600; color: var(--text-3);
  letter-spacing: .06em; margin-bottom: 8px;
}
.model-filters .mf-row {
  display: flex; align-items: center; gap: 8px; margin-bottom: 8px;
}
.model-filters .mf-row > span {
  flex: none; width: 56px; font-size: 12px; color: var(--text-2);
}
.model-filters .mf-row > select {
  flex: 1; min-width: 0; padding: 5px 6px; border: 1px solid var(--line);
  border-radius: 7px; background: #fff; color: var(--text); font-size: 12.5px;
  max-width: 100%;
}
.model-filters .mf-clear {
  display: block; width: 100%; margin-top: 2px; padding: 5px 0;
  border: 1px solid var(--line); border-radius: 7px; background: #fff;
  color: var(--accent); font-size: 12.5px; cursor: pointer;
}
.model-filters .mf-clear:hover { background: var(--accent-soft); }
/* 「模板方案」条目：与树节点同排，点击后右侧列表区显示模板方案 */
.tree-row.tpl-row { color: var(--text-2); }
.tree-row.tpl-row .tree-name { font-weight: 500; }

.tree-row {
  display: flex; align-items: center; gap: 6px;
  padding: 7px 8px; border-radius: 8px; cursor: pointer;
  font-size: 13px; color: var(--text-2); user-select: none;
}
.tree-row:hover { background: #F4F6F9; color: var(--text); }
.tree-row.active { background: var(--accent-soft); color: var(--accent); font-weight: 500; }

.tree-toggle {
  width: 20px; height: 20px; flex: 0 0 20px;
  display: grid; place-items: center;
  border: 0; background: transparent; padding: 0;
  color: var(--text-2); font-size: 13px; cursor: pointer; border-radius: 5px;
}
.tree-toggle:hover { background: var(--line); color: var(--accent); }
.tree-toggle.blank { cursor: default; }
.tree-toggle.blank:hover { background: transparent; }

.tree-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.tree-count {
  font-size: 11px; color: var(--text-3);
  background: var(--bg); border-radius: 999px; padding: 1px 7px; flex: none;
}
.tree-row.active .tree-count { background: #fff; color: var(--accent); }

@media (max-width: 960px) {
  /* 竖排后必须改回 stretch：flex-start 会让卡片按内容收缩，
     施工日志卡片列表就会在右侧留出一大块空白（与上方日历宽度不一致） */
  .body-row { flex-direction: column; align-items: stretch; }
  .tree-panel { width: 100%; flex: none; max-height: 240px; }
  /* 窄屏取消整块高度，树排在表格上方 */
  .body-row.has-tree { min-height: 0; }
  .body-row.has-tree .table-wrap { max-height: 60vh; }
  .body-row.has-tree > .tree-panel {
    width: 100%; flex: none; max-height: 260px;
    border-left: 0; border-right: 0; border-bottom: 1px solid var(--line);
  }
}

/* 型号叶子节点（挂在分类下的子树） */
.tree-row.leaf { padding-top: 5px; padding-bottom: 5px; font-size: 12.5px; }
.tree-row.leaf .tree-name { color: var(--text-2); }
.tree-row.leaf:hover .tree-name { color: var(--text); }
.tree-row.leaf.active .tree-name { color: var(--accent); }
.tree-leaf-ico {
  width: 18px; flex: 0 0 18px; text-align: center;
  color: var(--text-3); font-size: 9px; line-height: 1;
}
.tree-leaf-ico::before { content: '\25AA'; opacity: .5; }
.tree-row.uncat-row .tree-name { color: var(--text-3); }

/* 智能设备层级树：停靠右侧（类型/厂家/型号/协议） */
.tree-panel.tree-right { order: 2; }
.tree-panel .tree-hint { display: block; font-size: 11px; color: var(--text-3); padding: 2px 6px; }

/* 树筛选提示条 */
.tree-chip {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 6px;
  padding: 3px 8px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent); font-size: 12px; max-width: 100%;
}
.tree-chip[hidden] { display: none; }
.tree-chip .chip-tag { font-weight: 600; opacity: .75; flex: none; }
.tree-chip .chip-path {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 420px;
}
.tree-chip .chip-clear {
  flex: none; border: 0; background: transparent; color: inherit;
  font: inherit; cursor: pointer; padding: 0 2px; line-height: 1; opacity: .7;
}
.tree-chip .chip-clear:hover { opacity: 1; }

/* 窄屏：纵向排列时树面板统一排在表格上方（右侧树需复位 order） */
@media (max-width: 960px) {
  .tree-panel.tree-right { order: 0; }
}

/* ---------- 智能设备树：资料层 + 动环厂家分支 ---------- */
.tree-sec {
  margin: 10px 8px 4px; padding-top: 8px;
  border-top: 1px dashed var(--line);
  font-size: 11px; font-weight: 600; color: var(--text-3); letter-spacing: .06em;
}
.tree-doc-ico {
  width: 18px; flex: 0 0 18px; text-align: center;
  color: var(--text-3); font-size: 11px; line-height: 1;
}
.tree-row.doc-row { padding-top: 4px; padding-bottom: 4px; font-size: 12.5px; }
.tree-row.doc-row .tree-name { color: var(--text-2); display: flex; gap: 6px; align-items: baseline; }
.tree-row.doc-row .doc-val {
  font-style: normal; font-size: 11.5px; color: var(--text-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 130px;
}
.tree-row.doc-empty-row .tree-name { color: var(--text-3); }
.tree-row.doc-row:hover .tree-name { color: var(--accent); }
.tree-row.leaf .tree-count { font-size: 10px; }

/* 协议类附件控件 */
.doc-box { display: flex; flex-direction: column; gap: 8px; }
.doc-current {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  padding: 8px 10px; border: 1px dashed var(--line-strong);
  border-radius: 8px; background: var(--bg); font-size: 13px;
}
.doc-current a { color: var(--accent); text-decoration: none; word-break: break-all; }
.doc-current a:hover { text-decoration: underline; }
.doc-size, .doc-empty { color: var(--text-3); font-size: 12px; }
.doc-actions { display: flex; gap: 8px; }

/* ---------- 智能设备树形表格（主表格即树） ---------- */
#table.tree-table { width: 100%; }
#table.tree-table th { background: var(--bg); white-space: nowrap; }
#table.tree-table tr.tree-group > td {
  background: #FAFBFC; border-top: 1px solid var(--line); font-weight: 500;
}
#table.tree-table tr.tree-group:hover > td { background: #F4F6F9; }
#table.tree-table tr.tree-group-empty > td { color: var(--text-3); font-weight: 400; }
#table.tree-table tr.tree-lvl-head > td,
#table.tree-table td.tree-lvl { vertical-align: middle; }
.tree-sum {
  font-size: 12px; color: var(--text-3); font-weight: 400;
  padding-left: 4px !important; white-space: nowrap;
}
.tree-cell-toggle {
  width: 28px; height: 28px; margin-right: 6px; flex: none;
  border: 0; background: transparent; color: var(--text-2);
  font-size: 20px; line-height: 1; font-family: inherit;
  cursor: pointer; border-radius: 6px;
  vertical-align: middle;
}
.tree-cell-toggle:hover { background: var(--line); color: var(--accent); }
.tree-lvl-name { color: var(--text); font-weight: 500; }
.tree-lvl-name.leaf-name { font-weight: 400; cursor: pointer; }
.tree-lvl-name.leaf-name:hover { color: var(--accent); text-decoration: underline; }
#table.tree-table tr.tree-doc > td { background: #FCFDFE; font-size: 12.5px; }
.tree-doc-cell { color: var(--text-2); }
.tree-doc-tag {
  display: inline-block; margin-right: 8px; padding: 1px 7px;
  border-radius: 999px; background: var(--bg); color: var(--text-3); font-size: 11.5px;
}
.doc-link { color: var(--accent); text-decoration: none; word-break: break-all; }
.doc-link:hover { text-decoration: underline; }
.thumb.thumb-sm { width: 34px; height: 34px; margin-right: 4px; }

/* 型号行：型号名 + 聚合资料 + 新增动环厂家按钮 */
#table.tree-table tr.tree-model > td { background: #fff; border-top: 1px solid var(--line); }
#table.tree-table tr.tree-model:hover > td { background: #FAFBFC; }
.tree-count-inline {
  margin-left: 8px; font-size: 11px; font-weight: 400; color: var(--text-3);
}
.tree-sub-name {
  margin-left: 8px; font-size: 11.5px; color: var(--text-3);
}
button.mini.add {
  color: var(--accent); border-color: #C6D8F5; background: var(--accent-soft);
  white-space: nowrap;
}
button.mini.add:hover { background: #DCE9FB; border-color: var(--accent); }
/* 智能设备型号行：未加入 = 橙底「＋加入关联清单」，已加入 = 绿底「✓ 已在关联清单」 */
#table.tree-table button[data-act="toggle-city-list"] {
  white-space: nowrap; color: #B4610A; border-color: #F0C48A; background: #FFF3E0;
}
#table.tree-table button[data-act="toggle-city-list"]:hover {
  background: #FFE7CC; border-color: #E09A3C;
}
#table.tree-table button.mini.on {
  color: #1B7A45; border-color: #B7DCC3; background: #EAF7EF; white-space: nowrap;
}
#table.tree-table button.mini.on:hover { background: #DDF1E6; }
/* 动环厂家叶子行：淡蓝灰底色，和上方型号行（白底）区分开，一眼看出是下一层 */
#table.tree-table tr.tree-leaf > td { background: #F4F7FB; }
#table.tree-table tr.tree-leaf:hover > td { background: #EDF2F8; }

/* 树形表格文字不换行（列宽不够时改为横向滚动） */
#table.tree-table td.tree-lvl,
#table.tree-table .tree-lvl-name,
#table.tree-table .tree-sub-name,
#table.tree-table .tree-count-inline { white-space: nowrap; }
#table.tree-table { min-width: 1240px; }
#table.tree-table .tree-lvl-name.leaf-name { display: inline-block; max-width: 190px;
  overflow: hidden; text-overflow: ellipsis; vertical-align: bottom; }
#table.tree-table .tree-sub-name { display: inline-block; max-width: 120px;
  overflow: hidden; text-overflow: ellipsis; vertical-align: bottom; }

/* 型号行内联上传小按钮 */
#table.tree-table button.mini.add.tiny {
  margin-left: 6px; padding: 1px 6px; font-size: 11px; line-height: 16px;
  vertical-align: middle;
}
#table.tree-table .cell-empty + button.mini.add.tiny { margin-left: 8px; }

/* 型号行：图片横向排列（可横向滚动）、协议附件单行省略 */
#table.tree-table .photo-row {
  display: flex; align-items: center; gap: 4px; flex-wrap: nowrap;
  max-width: 420px; overflow-x: auto; overflow-y: hidden; padding-bottom: 2px;
}
#table.tree-table .photo-row .thumb.thumb-sm { flex: none; display: block; }
#table.tree-table .photo-row .cell-empty { flex: none; }
#table.tree-table .doc-cell {
  display: flex; align-items: center; gap: 6px; max-width: 240px;
}
#table.tree-table .doc-cell .doc-link {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
#table.tree-table .doc-cell .mini { flex: none; }

/* 精简表单：单图控件（.photo1-box） */
.photo1-box { display: flex; flex-direction: column; gap: 8px; }
.photo1-box .photo-preview-slot {
  width: 180px; height: 130px; border: 1px dashed var(--line-strong);
  border-radius: 8px; background: var(--bg); display: grid; place-items: center; overflow: hidden;
}
.photo1-box .photo-preview { max-width: 100%; max-height: 100%; object-fit: contain; }
.photo1-box .photo-actions { display: flex; gap: 8px; }

/* 型号行操作区：编辑在前、加号在后 */
#table.tree-table tr.tree-model > td.ops { white-space: nowrap; }
#table.tree-table tr.tree-model > td.ops .mini { margin-left: 6px; }
#table.tree-table tr.tree-model > td.ops .mini:first-child { margin-left: 0; }
/* 型号行与图片/协议区连成一片，便于识别「这一行才是主体」
   （层级列合并成 1 列后：第 1 列=层级名，第 2 列=图片，第 3 列=协议附件） */
#table.tree-table tr.tree-model > td.tree-lvl,
#table.tree-table tr.tree-model > td:nth-child(2),
#table.tree-table tr.tree-model > td:nth-child(3) { border-bottom: 1px solid var(--line); }

/* ---------- 树形表格紧凑化（右侧内容要能看全） ---------- */
/* auto：列宽按内容自适应，型号名过长时优先把宽度让给它 */
#table.tree-table { min-width: 0; table-layout: auto; }
#table.tree-table th,
#table.tree-table td { padding: 5px 8px; }
#table.tree-table th { font-size: 12px; }
#table.tree-table td { font-size: 12.5px; }
/* 正文列超宽省略，不再把表格撑宽（备注格/型号资料面板格除外：要保留填写格式） */
#table.tree-table td:not(.tree-lvl):not(.ops):not(.time) {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 缩略图更小 */
#table.tree-table .thumb.thumb-sm { width: 26px; height: 26px; border-radius: 4px; }
#table.tree-table .photo-row { max-width: 210px; gap: 3px; }
#table.tree-table .doc-cell { max-width: 150px; }
/* 按钮更紧凑 */
#table.tree-table button.mini { padding: 1px 7px; font-size: 11.5px; }
#table.tree-table tr.tree-model > td.ops .mini { margin-left: 4px; }
#table.tree-table tr.tree-model > td.ops .mini:first-child { margin-left: 0; }
/* 副标题与计数更小 */
#table.tree-table .tree-sub-name { max-width: 90px; font-size: 11px; }
#table.tree-table .tree-count-inline { margin-left: 6px; font-size: 10.5px; }
/* 行高更紧凑 */
#table.tree-table tr.tree-group > td,
#table.tree-table tr.tree-model > td,
#table.tree-table tr.tree-leaf > td { padding-top: 4px; padding-bottom: 4px; }

/* 型号/动环厂家名优先显示完整；超长才省略并可悬停查看 */
#table.tree-table td.tree-lvl { white-space: nowrap; }
#table.tree-table .tree-lvl-name {
  display: inline-block; max-width: 100%; overflow: hidden;
  text-overflow: ellipsis; vertical-align: middle;
}
#table.tree-table .tree-count-inline { white-space: nowrap; }

/* 动环厂家叶子行：自己的图片（缩略图比型号行小一号，省地方） */
#table.tree-table tr.tree-leaf .leaf-photos { max-width: 190px; gap: 4px; }
#table.tree-table tr.tree-leaf .leaf-photos .thumb.thumb-sm {
  width: 56px; height: 56px; border-radius: 6px;
}
#table.tree-table tr.tree-leaf .leaf-photos .thumb.thumb-sm:hover { border-color: var(--accent); }
#table.tree-table tr.tree-leaf .doc-cell { max-width: 170px; }
/* 叶子行操作区：编辑 + 删除 */
#table.tree-table tr.tree-leaf > td.ops { white-space: nowrap; }
#table.tree-table tr.tree-leaf > td.ops .mini { margin-left: 6px; }
#table.tree-table tr.tree-leaf > td.ops .mini:first-child { margin-left: 0; }

/* 树形层级名（类型/厂家/型号/动环厂家）：放大加粗（2026-10-22，两次下调 25→20→16px） */
#table.tree-table .tree-lvl-name { font-size: 16px; font-weight: 700; line-height: 1.25; }
#table.tree-table .tree-cell-toggle { font-size: 20px; width: 28px; height: 28px; }
/* 放大后行距相应加高，避免挤在一起 */
#table.tree-table tr.tree-group > td,
#table.tree-table tr.tree-model > td,
#table.tree-table tr.tree-leaf > td { padding-top: 7px; padding-bottom: 7px; }

/* 型号行内联缩略图放大（2026-10-22：小图放大、面板不重复出图；横向一排，放不下横向滚动） */
#table.tree-table tr.tree-model .photo-row {
  flex-wrap: nowrap; max-width: 680px; overflow-x: auto; overflow-y: hidden;
  gap: 8px; padding-bottom: 4px;
}
#table.tree-table tr.tree-model .photo-row .thumb.thumb-sm {
  width: 110px; height: 110px; border-radius: 8px;
}
#table.tree-table tr.tree-model .photo-row .thumb.thumb-sm:hover { border-color: var(--accent); }

/* 型号行图片格：备注框在前、图片在后（2026-10-23 用户要求） */
#table.tree-table tr.tree-model .photo-cell {
  display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap;
}
#table.tree-table tr.tree-model textarea.mk-remark {
  flex: none; box-sizing: border-box;
  width: 320px; height: 110px;            /* 高度跟图片一致；宽度是旧备注框(640px)的一半 */
  font: inherit; font-size: 13px; line-height: 1.6; color: var(--text);
  padding: 8px 10px; border: 1px solid var(--line-strong); border-radius: 8px;
  background: #fff; resize: vertical;
}
#table.tree-table tr.tree-model textarea.mk-remark:focus {
  outline: none; border-color: var(--accent);
}
#table.tree-table tr.tree-model textarea.mk-remark::placeholder { color: var(--text-3); }
@media (max-width: 700px) {
  #table.tree-table tr.tree-model .photo-row .thumb.thumb-sm { width: 84px; height: 84px; }
  #table.tree-table tr.tree-model textarea.mk-remark { width: 180px; height: 84px; }
}

/* ---------- 多选绑定（安排员工等）：原生勾选框平铺（设计稿样式） ---------- */
.multiref-box { display: flex; flex-direction: column; gap: 6px; }
.multiref-list {
  display: flex; flex-wrap: wrap; gap: 12px 24px;
  padding: 2px 0;
}
.multiref-item {
  display: inline-flex; align-items: center; gap: 8px;
  cursor: pointer; user-select: none;
  font-size: 14.5px; font-weight: 600; color: var(--text);
}
.multiref-item input {
  display: inline-block; width: 16px; height: 16px;
  accent-color: var(--accent); margin: 0; flex: none; cursor: pointer;
}
.multiref-item:hover { color: var(--accent); }
.multiref-item.on { color: var(--text); }
.multiref-count { font-size: 12px; color: var(--text-3); }
.multiref-tags { display: inline-flex; flex-wrap: wrap; gap: 4px; }
/* 施工人员账号：安排员工锁定本人时的提示 */
.multiref-tip { flex-basis: 100%; font-size: 12px; color: var(--text-3); }

/* 通用列表：单元格不换行（列宽不够时省略号，悬停看全）
   注意排除卡片单元格 .log-card-cell：它是卡片容器，必须占满宽度、
   且内部自行换行，否则手机上会被 max-width:360px 卡住、右侧留白 */
#table:not(.tree-table) td:not(.ops):not(.empty):not(.time):not(.log-card-cell):not(.nos-cell):not(.flag-cell) {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 360px;
}
/* ---------- 重点关注：一列旗帜（平时空的灰旗，点一下插红旗） ---------- */
th.col-flag, td.flag-cell { width: 64px; text-align: center; }
/* ---------- 采购订单：「FSU安装 / 材料数量」列（两行；材料＝剩余/FSU总数） ---------- */
td.fsu-stat-cell {
  font-size: 12px; line-height: 1.5; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
td.fsu-stat-cell .fs-row { display: block; }
td.fsu-stat-cell .fs-row i { font-style: normal; color: var(--text-3); margin-right: 5px; }
td.fsu-stat-cell .fs-row b { font-weight: 600; }
td.fsu-stat-cell .fs-row.fs-zero b { color: #D93025; }
/* ---------- 采购订单：「水印照片」列（张数 + 下载按钮）2026-10-28 / 177 ---------- */
td.wm-photo-cell { text-align: left; white-space: nowrap; font-size: 12px; }
.wm-dl-btn {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; border: 1px solid #C7D3E4; border-radius: 6px;
  background: #F3F7FD; color: #1D63B6; font-size: 12px; cursor: pointer;
}
.wm-dl-btn:hover { background: #E6EFFB; border-color: #9DB8DC; }
.wm-dl-btn:disabled { opacity: .55; cursor: default; }
.wm-dl-btn .wm-dl-n { font-variant-numeric: tabular-nums; }
.wm-dl-btn .wm-dl-i { font-size: 11px; }

.flag-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0;
  border: 1px solid transparent; border-radius: 6px;
  background: transparent; color: #C7CEDB; cursor: pointer;
}
.flag-btn:hover { background: #F1F5FA; color: #98A3B4; }
.flag-btn.on { color: #E13B30; }
.flag-btn.on:hover { background: #FDECEA; color: #C32A20; }
.flag-btn:disabled { opacity: .6; cursor: default; }
.flag-btn svg { display: block; }
/* 详情页标题旁的旗帜：稍大一点，跟标题基线对齐 */
.detail-title .flag-btn { width: 28px; height: 28px; }
.os-info-v .flag-btn { vertical-align: middle; }
#table:not(.tree-table) td.ops { white-space: nowrap; }
/* 行首「清单」按钮列：左对齐、紧凑 */
td.lead-ops { text-align: left; width: 64px; }
/* 采购订单：「清单」右边的「编辑」独立列 */
td.lead-edit { text-align: left; width: 56px; white-space: nowrap; }

/* 删除清单确认框里的风险提示段 */
.confirm-box p.warn-line {
  margin-top: 10px; padding: 9px 11px;
  background: var(--danger-soft); border: 1px solid #EFCDCA;
  border-radius: 8px; font-size: 12.5px; color: var(--text-2);
}
.confirm-box p.warn-line strong { color: var(--danger); }

/* 导入映射区的告警提示（未指定必填列 / 两槽位选了同一列） */
.map-warn {
  flex: none; font-size: 11.5px; color: var(--text-3);
  max-width: 190px; line-height: 1.4;
}
.map-warn.req { color: var(--danger); font-weight: 500; }
/* 未匹配说明的小字 */
.sub-note {
  display: block; margin-top: 6px;
  font-size: 12px; color: var(--text-3); font-weight: 400; line-height: 1.6;
}

/* ---------- 清单表格：列宽拖拽手柄 ---------- */
table.sitegrid thead th { position: sticky; user-select: none; }
table.sitegrid th .col-resize {
  position: absolute; top: 0; right: -3px;
  width: 7px; height: 100%;
  cursor: col-resize; z-index: 3;
}
table.sitegrid th .col-resize::after {
  content: ''; position: absolute; left: 3px; top: 8px; bottom: 8px;
  width: 1px; background: transparent;
}
table.sitegrid th:hover .col-resize::after { background: var(--line-strong); }
table.sitegrid th .col-resize:hover::after,
body.col-resizing table.sitegrid th .col-resize::after {
  width: 2px; background: var(--accent);
}
/* 拖动中：全局禁用文字选择与鼠标手势 */
body.col-resizing {
  cursor: col-resize;
  user-select: none;
  -webkit-user-select: none;
}
body.col-resizing iframe { pointer-events: none; }

/* ---------- 设备接口清单（采集器设备：串口 / 非智能通道等） ---------- */
.port-box { display: flex; flex-direction: column; gap: 6px; }
.port-head, .port-row {
  display: grid; grid-template-columns: 1.2fr 110px 1.6fr 26px; gap: 6px; align-items: center;
}
.port-head { font-size: 11.5px; color: var(--text-3); padding: 0 2px; }
/* 弹窗加宽后端口行两列排布，长列表不用滚太久；列标签隐藏，靠输入框占位提示 */
.modal.has-ports .port-head { display: none; }
.modal.has-ports .port-rows {
  display: grid; grid-template-columns: 1fr 1fr; gap: 6px 18px;
}
.port-rows { display: flex; flex-direction: column; gap: 6px; }
.port-row input {
  width: 100%; height: 30px; padding: 0 8px;
  border: 1px solid var(--line); border-radius: 6px; background: #fff;
  font: inherit; font-size: 13px; color: var(--text);
}
.port-row input:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
}
/* 窄屏（手机）：端口行同样改成两行，端口名独占一行 */
@media (max-width: 620px) {
  .modal.has-ports .port-rows { grid-template-columns: 1fr; }
  .port-head { display: none; }
  .port-row { grid-template-columns: 1fr 1fr 26px; }
  .port-row .port-name { grid-column: 1 / -1; }
}
.port-row .port-qty { text-align: center; }
.port-row button.row-del {
  width: 24px; height: 24px; border-radius: 5px;
  border: 1px solid var(--line); background: #fff; color: var(--text-3);
  cursor: pointer; font-size: 14px; line-height: 1; flex: none;
}
.port-row button.row-del:hover { color: var(--danger); border-color: #EFCDCA; background: var(--danger-soft); }
.port-foot { display: flex; align-items: center; gap: 10px; }
.port-total { font-size: 12px; color: var(--text-3); }
.port-tags { display: inline-flex; flex-wrap: wrap; gap: 4px; }

/* ---------- 端口批量生成区 ---------- */
.port-gen {
  display: grid; grid-template-columns: 1.2fr 110px 1.4fr auto;
  gap: 6px; align-items: center; margin-bottom: 4px;
  padding: 8px; background: var(--bg); border-radius: 8px;
}
.port-gen input {
  width: 100%; height: 30px; padding: 0 8px;
  border: 1px solid var(--line); border-radius: 6px; background: #fff;
  font: inherit; font-size: 13px; color: var(--text);
}
.port-gen input:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
}
.port-empty {
  padding: 14px 10px; text-align: center;
  color: var(--text-3); font-size: 12.5px;
  border: 1px dashed var(--line-strong); border-radius: 8px; background: #FCFDFE;
}
.port-row .port-group { text-align: center; }

/* ---------- 施工人员工作台横幅（本月日历 + 年度/月度施工天数） ---------- */
.staff-top {
  display: flex; flex-direction: column; gap: 12px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 14px 16px; margin-bottom: 12px;
}
.staff-top-h { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.staff-top-h b { font-size: 16px; color: var(--accent); }
.staff-days { font-size: 13px; color: var(--text-2); margin-left: 4px; }
.staff-days b { color: var(--accent); font-size: 15px; }
.staff-top-h .mini { margin-left: auto; }
.staff-top .home-cal { box-shadow: none; }
/* 列表上方「正在只看某天」提示条（施工人员点日历后出现） */
.staff-day-chip {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 10px 14px 0; padding: 7px 12px;
  background: var(--accent-soft); color: var(--accent);
  border: 1px solid #C9DFF5; border-radius: 8px; font-size: 13px;
}
.staff-day-chip b { font-weight: 700; }
.staff-day-chip .mini { margin-left: auto; color: var(--accent); }
@media (max-width: 620px) {
  .staff-top-h { gap: 8px; }
  .staff-days { font-size: 12.5px; }
}

/* ---------- 施工日志筛选栏（区域 / 人员 / 时间段 / 厂家 / 设备型号 + 导出） ---------- */
.filter-bar {
  padding: 10px 14px 8px;
  border-bottom: 1px solid var(--line);
  background: #FCFDFF;
}
.fb-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.fb-label {
  font-size: 12.5px; font-weight: 700; color: var(--text-2);
  letter-spacing: .5px; flex: none;
}
.fb-sel {
  height: 30px; max-width: 168px; padding: 0 6px;
  border: 1px solid var(--line-strong); border-radius: 7px;
  background: #fff; font: inherit; font-size: 12.5px;
  color: var(--text-2); outline: 0; cursor: pointer;
}
.fb-sel:focus { border-color: var(--accent); }
/* 选中态：非空值的高亮一下，让「现在正按什么筛」一眼可见 */
.fb-sel.on { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); font-weight: 600; }
/* 筛选栏多选下拉（2026-10-25）：按钮 + 复选面板，替代原单选 select */
.fb-ms { position: relative; display: inline-flex; }
.fb-ms-btn {
  height: 30px; max-width: 168px; padding: 0 6px;
  border: 1px solid var(--line-strong); border-radius: 7px;
  background: #fff; font: inherit; font-size: 12.5px;
  color: var(--text-2); outline: 0; cursor: pointer;
  display: inline-flex; align-items: center; gap: 4px;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.fb-ms-btn:hover { border-color: var(--accent); }
.fb-ms-btn.open { border-color: var(--accent); }
.fb-ms-btn.on { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.fb-ms-num {
  font-style: normal; font-size: 11px; line-height: 1;
  background: var(--accent); color: #fff; border-radius: 999px;
  padding: 2px 5px; min-width: 16px; text-align: center;
}
.fb-ms-panel {
  position: absolute; top: calc(100% + 4px); left: 0; z-index: 60;
  min-width: 180px; max-width: 260px;
  background: #fff; border: 1px solid var(--line-strong);
  border-radius: 10px; box-shadow: 0 8px 24px rgba(15, 23, 42, .14);
  padding: 6px;
}
.fb-ms-head {
  display: flex; gap: 6px; padding: 2px 2px 6px;
  border-bottom: 1px solid var(--line); margin-bottom: 4px;
  align-items: center;
}
/* 面板内关键字搜索（关联工单按工程名称筛） */
.fb-ms-search {
  width: 100%; height: 28px; margin: 0 0 6px; padding: 0 8px;
  border: 1px solid var(--line-strong); border-radius: 7px;
  background: #fff; font: inherit; font-size: 12.5px; color: var(--text-1); outline: 0;
  box-sizing: border-box;
}
.fb-ms-search:focus { border-color: var(--accent); }
.fb-ms-cnt { margin-left: auto; font-size: 11.5px; color: var(--text-3); }
/* 加宽面板：工程名称较长，窄面板会全被省略号吃掉 */
.fb-ms-panel.wide { min-width: 300px; max-width: 380px; }
.fb-ms-list { max-height: 260px; overflow: auto; }
.fb-ms-item {
  display: flex; align-items: center; gap: 7px;
  padding: 5px 6px; border-radius: 6px; font-size: 12.5px;
  color: var(--text-2); cursor: pointer;
}
.fb-ms-item:hover { background: var(--accent-soft); }
.fb-ms-item[hidden] { display: none; }
.fb-ms-item input { margin: 0; accent-color: var(--accent); flex: 0 0 auto; }
.fb-ms-item span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fb-ms-item .fb-ms-t { flex: 1 1 auto; min-width: 0; }
.fb-ms-item .fb-ms-s {
  flex: 0 0 auto; font-style: normal; font-size: 11.5px;
  color: var(--text-3); max-width: 42%; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.fb-ms-empty { padding: 10px 6px; font-size: 12px; color: var(--text-3); text-align: center; }
.fb-dates { display: inline-flex; align-items: center; gap: 5px; }
.fb-date {
  height: 30px; padding: 0 6px;
  border: 1px solid var(--line-strong); border-radius: 7px;
  background: #fff; font: inherit; font-size: 12.5px;
  color: var(--text-2); outline: 0;
}
.fb-date:focus { border-color: var(--accent); }
.fb-date.on { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.fb-sep { font-size: 12.5px; color: var(--text-3); }
/* 「已筛选 N 项」提示条 */
.fb-chip {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin-top: 8px; padding: 6px 10px;
  background: var(--accent-soft); border: 1px solid #C9DFF5;
  border-radius: 8px; font-size: 12px; color: var(--accent);
}
.fb-chip-item {
  background: #fff; border: 1px solid #C9DFF5;
  border-radius: 999px; padding: 2px 8px;
}
/* 「已筛选 N 项」小条里的记录数汇总：白底强调，清空按钮靠右前 */
.fb-chip-count {
  background: #fff; border: 1px solid var(--accent);
  border-radius: 999px; padding: 2px 10px; font-weight: 600;
}
.fb-chip-clear {
  margin-left: auto; border: 0; background: transparent;
  color: var(--accent); font: inherit; font-size: 12px;
  cursor: pointer; text-decoration: underline;
}
@media (max-width: 720px) {
  .filter-bar { padding: 8px 10px 6px; }
  .fb-sel { max-width: 130px; height: 32px; }
  .fb-date { height: 32px; }
  .fb-row { gap: 6px; }
  /* 手机：加宽面板别顶出屏幕（工程名称长，但宽度必须收在视口内） */
  .fb-ms-panel.wide { min-width: 0; width: calc(100vw - 40px); max-width: 320px; }
}

/* ---------- 账号系统：右上角账号区 ---------- */
.account-chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 4px 6px 4px 4px; background: var(--panel);
  border: 1px solid var(--line); border-radius: 999px;
}
.account-ava {
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--accent); color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 700;
}
.account-name { font-size: 13px; font-weight: 600; color: var(--text); white-space: nowrap; }
.account-logout {
  border: none; background: transparent; cursor: pointer;
  color: var(--text-3); font-size: 12px; padding: 2px 8px; border-radius: 999px;
}
.account-logout:hover { color: var(--danger); background: var(--danger-soft); }
/* 登录账号管理入口（右上角账户区，从左侧菜单移过来） */
.account-manage {
  border: none; background: transparent; cursor: pointer;
  color: var(--accent); font: inherit; font-size: 12px;
  padding: 2px 8px; border-radius: 999px; white-space: nowrap;
}
.account-manage:hover { background: var(--accent-soft, #EAF2FB); }
/* 施工人员账号：右上角「本月 X 天」角标，点开看我的施工日历 */
.staff-day-badge {
  border: 1px solid var(--accent); background: var(--accent-soft, #EAF2FB);
  color: var(--accent); font: inherit; font-size: 11.5px; font-weight: 600;
  padding: 1px 9px; border-radius: 999px; cursor: pointer; white-space: nowrap;
}
.staff-day-badge:hover { background: #DCEAF8; }
@media (max-width: 900px) {
  .account-name { display: none; }
}

/* 手机端：顶栏「新增」按钮放大一倍 + 绿底（施工人员现场随手记，够大才点得中） */
@media (max-width: 620px) {
  .actions { gap: 6px; }
  #btnNew {
    font-size: 22px; font-weight: 700; letter-spacing: .04em;
    min-height: 68px; padding: 14px 44px; border-radius: 999px;
    color: #fff; background: #2E9E4F; border-color: #2E9E4F;
    box-shadow: 0 4px 14px rgba(46, 158, 79, .32);
  }
  #btnNew:hover { background: #268445; border-color: #268445; }
  #btnNew:active { background: #1F7039; box-shadow: none; }
}

/* 右上角·施工人员施工日历弹层 */
.staff-popover {
  position: fixed; top: 56px; right: 16px; z-index: 60;
  width: 320px; max-width: calc(100vw - 24px);
  background: var(--panel); border: 1px solid var(--line-strong); border-radius: 12px;
  box-shadow: 0 10px 30px rgba(20, 40, 70, .16); padding: 12px 14px 14px;
}
.staff-pop-head {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px;
}
.staff-pop-head b { font-size: 14px; color: var(--text); }
.staff-pop-head .staff-days { font-size: 12px; color: var(--text-2); margin-right: auto; }
.staff-pop-head .staff-days b { color: var(--accent); font-size: 14px; }
.staff-popover .home-cal { box-shadow: none; border: 1px solid var(--line); }

/* ---------- 账号系统：登录页 ---------- */
.login-view {
  position: fixed; inset: 0; z-index: 500;
  background: linear-gradient(160deg, #EEF3F9 0%, #E3ECF6 60%, #DCE8F5 100%);
  display: flex; align-items: center; justify-content: center; padding: 20px;
}
.not-logged-in .app { display: none; }
.login-card {
  width: 100%; max-width: 360px; background: var(--panel);
  border: 1px solid var(--line); border-radius: 16px;
  box-shadow: 0 8px 30px rgba(24, 95, 165, .14);
  padding: 32px 28px 24px; text-align: center;
}
.login-logo {
  width: 52px; height: 52px; margin: 0 auto 12px; border-radius: 14px;
  background: var(--accent); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 26px; font-weight: 700;
}
.login-title { margin: 0; font-size: 20px; color: var(--text); }
.login-sub { margin: 4px 0 20px; font-size: 13px; color: var(--text-3); }
.login-error {
  background: var(--danger-soft); color: var(--danger);
  border-radius: 8px; padding: 8px 12px; font-size: 13px; margin-bottom: 14px; text-align: left;
}
.login-field { display: block; text-align: left; margin-bottom: 14px; }
.login-field span { display: block; font-size: 13px; color: var(--text-2); margin-bottom: 5px; }
.login-field input {
  width: 100%; padding: 9px 12px; font-size: 14px; color: var(--text);
  background: #fff; border: 1px solid var(--line-strong); border-radius: 8px; outline: none;
}
.login-field input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.login-btn {
  width: 100%; padding: 10px; margin-top: 4px; border: none; cursor: pointer;
  border-radius: 8px; background: var(--accent); color: #fff;
  font-size: 15px; font-weight: 600; letter-spacing: 2px;
}
.login-btn:hover { background: var(--accent-hover); }

/* ============================================================
   手机端弹窗整屏化：修复表单弹窗「卡在半屏」、滚不到底部的问题
   部分手机浏览器对 position:fixed + flex 的 overlay 滚动支持差，
   改为全屏弹层：头部/底部固定，表单区（modal-body）内部滚动。
   ============================================================ */
@media (max-width: 620px) {
  .overlay:not(.photo-view) { padding: 0; align-items: stretch; }
  .overlay:not(.photo-view) .modal {
    max-width: 100%; width: 100%;
    max-height: 100vh;          /* 老浏览器回退 */
    max-height: 100dvh;         /* 跟随手机地址栏动态视口 */
    border-radius: 0;
    display: flex; flex-direction: column;
  }
  /* modal 的直接子级可能是 form（表单弹窗）或 modal-body（确认框） */
  .overlay:not(.photo-view) .modal form {
    display: flex; flex-direction: column;
    flex: 1 1 auto; min-height: 0;
  }
  .overlay:not(.photo-view) .modal-body {
    flex: 1 1 auto; min-height: 0;
    overflow-y: auto; -webkit-overflow-scrolling: touch;
  }
  .overlay:not(.photo-view) .modal-foot {
    flex: none;
    border-top: 1px solid var(--line);
    padding-bottom: max(14px, env(safe-area-inset-bottom));
  }
}

/* 账号管理：管理员明文密码列 + 表单内当前密码展示 */
.pwd-cell code, .pwd-current code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px; background: #F1F3F6; color: var(--text);
  padding: 1px 6px; border-radius: 5px; word-break: break-all;
}
.pwd-current { margin-bottom: 6px; font-size: 13px; color: var(--text-2); }
.pwd-current code { color: var(--danger); background: #FDECEA; }

/* 智能设备树形表：按层级深浅上底色（2026-10-25 用户要求：
   第 1 层级（类型）深色底，下一层级（厂家）淡一点，往下依次更淡） */
#table.tree-table tr.tree-d0 > td { background: #C7D6E8; }
#table.tree-table tr.tree-d1 > td { background: #E9F0F8; }
#table.tree-table tr.tree-d2 > td { background: #F5F8FC; }
#table.tree-table tr.tree-d3 > td { background: #FCFDFE; }
/* 未命名分组（空名字）用更灰一点的底，别跟正常类型抢眼 */
#table.tree-table tr.tree-d0.tree-group-empty > td { background: #E4E9F0; }

/* 通用编辑弹窗：「返回」「保存」放到左上角（2026-10-25 用户要求：
   表单长，滚到底才找「保存」太麻烦；保存按钮用 form="entityForm" 关联提交） */
.form-modal .modal-head { justify-content: flex-start; gap: 12px; }
.modal-head-ops { display: flex; align-items: center; gap: 8px; flex: none; }
.modal-head-title { flex: 1; min-width: 0; }
/* 头部保存按钮沿用原来底部绿色主按钮的配色 */
.modal-head-ops .btn.primary { background: #3F9B4F; border-color: #3F9B4F; }
.modal-head-ops .btn.primary:hover { background: #35813F; border-color: #35813F; }
.modal-head-ops .btn.primary:disabled { background: #9CC7A3; border-color: #9CC7A3; }
/* 底部按钮条取消后，弹窗内容区补足下边距 */
.form-modal .modal-body { padding-bottom: 20px; }

/* ---------- 拍照账号 · 发货登记（2026-10-27） ----------
   拍照账号在手机上用，材料收发单的桌面表单（多列 flex）在窄屏会挤成一团，
   这里把表单改成「一行一个控件、整行占满」，材料行下拉自适应，数量列收窄。 */
body.photo-mode .mf-page { gap: 12px; padding: 0; }
body.photo-mode .mf-form-card,
body.photo-mode .mf-list-card { padding: 12px 12px 14px; }
body.photo-mode .mf-form-title { font-size: 14px; line-height: 1.5; }
body.photo-mode .mf-hint { display: block; margin: 4px 0 0; }
body.photo-mode .mf-form-row { flex-direction: column; align-items: stretch; gap: 10px; }
body.photo-mode .mf-form-row label,
body.photo-mode .mf-form-row label.mf-po,
body.photo-mode .mf-form-row label.mf-ct,
body.photo-mode .mf-form-row label.mf-flex { flex: 1 1 auto; width: 100%; max-width: 100%; }
body.photo-mode .mf-form-row input,
body.photo-mode .mf-form-row select,
body.photo-mode .mf-po select { width: 100%; min-width: 0; }
body.photo-mode .mf-plan-row { gap: 8px; }
body.photo-mode .mf-plan { flex: 1 1 100%; }
body.photo-mode .mf-sets { flex: 1 1 auto; }
body.photo-mode .mf-sets input { width: 72px; }
body.photo-mode .mf-form-actions { gap: 8px; }
body.photo-mode .mf-form-actions .btn { flex: 1 1 auto; padding: 9px 12px; }
/* 2026-10-27（146）：桌面端下拉改成占满整列后，手机端把「动环设备厂家」这一行也改成竖排，
   否则下拉会把后面那行提示文字挤没 */
body.photo-mode .mf-mfr-row { flex-direction: column; align-items: stretch; }
body.photo-mode .mf-mfr-row label { flex: 1 1 auto; width: 100%; min-width: 0; }
body.photo-mode .mf-mfr-row .mf-hint { padding-bottom: 0; }
/* 材料行：名称下拉占满剩余宽度，数量列固定窄列，删除按钮不换行 */
body.photo-mode .mf-items { width: 100%; table-layout: auto; }
body.photo-mode .mf-items select { width: 100%; max-width: 100%; }
body.photo-mode .mf-items .mf-qty,
body.photo-mode .mf-items .mf-th-qty { width: 72px; }
body.photo-mode .mf-items th,
body.photo-mode .mf-items td { padding: 6px 4px; }
body.photo-mode .mf-items-head { flex-wrap: wrap; gap: 6px; }
body.photo-mode .mf-items-title { font-size: 12.5px; color: var(--text-3); }
/* 拍照账号菜单只有 5 项：手机上换行显示，别让「发货登记」藏在横向滚动的最右边 */
body.photo-mode .nav { flex-wrap: wrap; overflow-x: visible; row-gap: 6px; }
/* 已发货记录列表：窄屏不要把多列压成竖排文字 —— 保底宽度 + 横向滑动，列看起来才正常 */
body.photo-mode #mfIList { overflow-x: auto; }
body.photo-mode #mfIList .mf-rec { min-width: 620px; }
body.photo-mode #mfIList .mf-rec th,
body.photo-mode #mfIList .mf-rec td { white-space: nowrap; }
body.photo-mode #mfIList .mf-sub { white-space: nowrap; }
/* 汇总表按内容定宽后，极小屏或材料名特别长时可横向滑动，不撑破卡片 */
#mfSummaryBody { overflow-x: auto; }
/* 2026-10-27（139）：三个板块——材料汇总 / 收货登记（.mf-form-card）/ 已登记收货单（.mf-list-card）
   统一成同一个宽度：一律撑满内容区，三张卡的左右边线对齐成一条直线。
   注意：卡片满宽、但里面的表格仍按内容贴左（.mf-sum-table/.mf-rec 保持 max-content），
   这样列与列之间不会被拉开成大片空白（那是 137 节刚去掉的毛病）。
   汇总卡片里有跑马灯（nowrap 一长串），不加 contain 会反过来把卡片顶爆，
   所以 ticker 声明 contain:inline-size + width:100%，尺寸由卡片决定。 */
.mf-summary, .mf-form-card, .mf-list-card { width: 100%; min-width: 0; max-width: 100%; }
.mf-summary .mf-ticker { width: 100%; contain: inline-size; }
/* 窄屏（笔记本 1366 以下 / 手机横屏）：内容比屏幕还宽的话，紧凑反而要横滑 ——
   这时退回「铺满 + 列内换行」的老行为 */
@media (max-width: 1120px) {
  .mf-sum-table, .mf-rec { width: 100%; }
}

/* ---------- 采集器（FSU）行：材料框本身染紫（2026-10-27） ----------
   原来是在材料框右侧再挂一个「采集器」小标签，位置飘、还多占一段宽度；
   现在直接把这一行的材料下拉涂上底色，一眼对上。
   2026-10-27（149）：底色跟着 .mf-fsu-li 一起加深（#F1ECFC → #E5DBFA），
   两处保持同一个紫；下拉框里的紫字同步压深一点，底色深了字也要跟上。 */
.mf-items tr.mf-is-fsu select[data-f="material"] {
  background: #E5DBFA; border-color: #8A63D6; color: #3F2478; font-weight: 600;
}
.mf-items tr.mf-is-fsu select[data-f="material"]:focus { border-color: #6B46C1; }

/* ---------- 手机端自定义下拉面板（2026-10-27） ----------
   原生 <select> 在手机上要「点名字 → 再点完成」才生效；换成贴着下拉框弹出的浮层，点哪项直接选中。
   2026-10-27（147）：由「底部抽屉」改为「跟随下拉框」——面板 fixed 定位到 select 正下方，
   宽度跟下拉框一致；下方空间不够就自动翻到下拉框上方。 */
body.mf-pick-open { overscroll-behavior: none; }
.mf-pick-mask {
  position: fixed; inset: 0; z-index: 9999;
  background: rgba(15, 23, 42, .14);
  /* 遮罩本身不参与滚动：手机上按住遮罩拖动不会把背景页面滚走
     （不能用 body{overflow:hidden} 锁滚动——那会重置滚动位置、把下面的下拉框顶得跳一下） */
  touch-action: none; overscroll-behavior: contain;
}
.mf-pick-panel {
  /* 文档绝对坐标（不是 fixed）：页面滚动时面板跟着下拉框一起走 */
  position: absolute; z-index: 10000;
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--panel);
  border: 1px solid var(--line-strong); border-radius: 12px;
  box-shadow: 0 14px 34px rgba(15, 23, 42, .24);
}
.mf-pick-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 10px 12px; margin: 0; background: var(--panel);
  border-bottom: 1px solid var(--line); font-size: 14px; flex: none;
}
.mf-pick-head b { font-weight: 600; color: var(--text); }
.mf-pick-x {
  font: inherit; font-size: 13px; color: var(--text-2); background: var(--panel);
  border: 1px solid var(--line-strong); border-radius: 999px; padding: 4px 14px;
}
.mf-pick-list {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch;
  background: var(--panel);
  /* 面板内部要能竖向滑动（遮罩是 touch-action:none，这里放开） */
  touch-action: pan-y; overscroll-behavior: contain;
}
.mf-pick-grp { padding: 8px 14px 4px; font-size: 12px; color: var(--text-3); background: #F6F8FB; }
.mf-pick-item {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; text-align: left; font: inherit; font-size: 14.5px; line-height: 1.45;
  padding: 13px 14px; background: var(--panel); color: var(--text);
  border: 0; border-bottom: 1px solid var(--line); cursor: pointer;
}
.mf-pick-item span { flex: 1 1 auto; word-break: break-word; }
.mf-pick-item i { font-style: normal; font-weight: 700; color: var(--accent); }
.mf-pick-item.on { color: var(--accent); font-weight: 600; background: var(--accent-soft); }
.mf-pick-item:active { background: var(--accent-soft); }

/* ---------- 首页顶部 7 张卡：永远一行，绝不换行（2026-10-27（第 148 节）） ----------
   问题：.home-stats 原来是 flex-wrap: wrap。7 张卡（施工日志 / 施工日历 / 材料收发 /
   400派单 / 外包单汇总 / 快捷导出 / 账单）各自带 min-width，加起来 1749px，比内容区
   （约 1617px）多出 132px，于是「账单」卡被挤到第二行、又被 flex-grow 拉成整行宽
   ——就是用户截图里那张横贯全屏的卡。

   改法（关键是 flex-basis 归零 + 按 grow 权重瓜分富余宽度）：
   1) 容器 flex-wrap: nowrap —— 结构上就不可能换行；
   2) 每张卡 flex: <权重> 1 0（basis=0）且 min-width:0 —— 宽度完全按权重瓜分，
      屏幕再窄也只是等比压缩，永远只占一行，也永远不会把页面撑出横向滚动条；
   3) 卡内文字补省略号（导出行名、日历标题、账单收支行），压窄了也不溢出边框；
   4) 只有手机端（≤900px）例外：7 张卡挤在 360px 里根本看不清，改成「横向滑动的一行」，
      卡片保持固定可读宽度 —— 依然不换行。 */
.home-stats {
  flex-wrap: nowrap;
  min-width: 0;
  align-items: stretch;
}
/* 卡内内容一律不糊到卡片外面（min-width 兜底后内容会溢出，统一裁掉） */
.home-stats > * { overflow: hidden; }

/* 宽度分配：每张卡的 width/min-width = 它自己内容真正需要的宽度（Edge 实测值）+ 余量，
   富余的宽度再按 flex-grow 权重瓜分（内容多的卡权重高）。
   这样 7 张卡在一行里既不换行，也不会把日历标题/材料收发数字挤没。
   合计 1133px + 6×12px 间隔 = 1205px，视口 ≥1520（内容区 1240）刚好排得下。 */
.home-stats > .home-stat-action { flex: 1.15 1 auto; width: 116px; min-width: 116px; }  /* 施工日志 */
.home-stats > .home-cal        { flex: 2.20 1 auto; width: 224px; min-width: 224px; }  /* 施工日历 */
.home-stats > .mf-home-box     { flex: 2.05 1 auto; width: 210px; min-width: 210px; }  /* 材料收发 */
.home-stats > .dispatch-stat   { flex: 1.20 1 auto; width: 165px; min-width: 165px; }  /* 400派单 */
.home-stats > .outsource-stat  { flex: 1.05 1 auto; width: 92px;  min-width: 92px;  }  /* 外包单汇总 */
.home-stats > .export-box      { flex: 1.75 1 auto; width: 176px; min-width: 176px; }  /* 快捷导出 */
.home-stats > .bill-stat       { flex: 1.60 1 auto; width: 150px; min-width: 150px; }  /* 账单 */

/* 卡内文字一律单行 + 省略号：宽度临界时宁可少显示几个字，也不要折行把卡撑高 */
.home-stats .home-stat-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* 卡内横向内边距收一点：7 张卡挤一行时，每张各省 8px */
.home-stats > .home-stat { padding: 12px; }
.home-stats > .home-cal { padding: 12px; }
/* 施工日志卡里的「＋ 点击添加」按钮：跟着卡片一起收窄（不折行） */
.home-stats > .home-stat-action .home-stat-add { padding: 5px 8px; font-size: 12.5px; white-space: nowrap; }
/* 日历标题过长省略（不换行、不换行地把标题挤成两行）；
   字号 14→13、按钮同步收小，1440 视口下标题也能完整显示 */
.home-cal-head { gap: 8px; }
.home-cal-head b {
  flex: 0 1 auto; min-width: 0; white-space: nowrap; font-size: 13px;
  overflow: hidden; text-overflow: ellipsis;
}
.home-cal-head .mini { flex: none; font-size: 11.5px; padding: 4px 6px; }
/* 400派单：三个小格压窄，数字字号略降 */
.dispatch-stat .dispatch-mini { gap: 5px; }
.dispatch-stat .dispatch-mini span { padding: 6px 1px; font-size: 10.5px; overflow: hidden; }
.dispatch-stat .dispatch-mini b { font-size: 18px; }
/* 材料收发：工程名可以省略（名字先让位），但「总/已发/余」的数字必须完整 ——
   所以数字不参与收缩、字号略降，工程名最少留 30px */
.mf-vticker-item .vt-name { flex: 1 1 30px; }
.mf-vticker-item .vt-nums { flex: 0 0 auto; font-size: 11.5px; }
.mf-vticker-item .vt-sep { margin: 0 3px; }
/* 快捷导出：行名省略号 + 引导线收窄 + 按钮收窄 */
.export-row { gap: 6px; padding: 6px 4px; min-width: 0; }
.export-name { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.export-dots { min-width: 10px; margin: 0 4px; }
.export-go-btn { padding: 5px 10px; }
/* 账单：净额不折行，收支小字允许折行（金额长时换到第二行，不撑破卡片） */
.bill-net { white-space: nowrap; }
.bill-sub { flex-wrap: wrap; row-gap: 2px; gap: 8px; min-width: 0; }
.bill-sub b { min-width: 0; }

/* 视口 <1520：内容区放不下 7 张卡的最小宽度合计（1205px），再等比压缩就会把
   日历标题、材料收发数字挤没 —— 改成「固定宽度 + 横向滑动的一行」：
   依然不换行，内容也不被裁，横向滑一下就能看全。
   高度固定 256px 是给横向滚动条预留位置（Chrome 的滚动条占内容盒高度），
   否则最下面一行会被裁掉 10px。 */
@media (max-width: 1519px) {
  .home-stats {
    height: 256px;
    overflow-x: auto; overflow-y: hidden;
    padding-bottom: 12px;
    scrollbar-width: thin;
    scrollbar-color: #C2CAD6 transparent;
  }
  .home-stats::-webkit-scrollbar { height: 6px; }
  .home-stats::-webkit-scrollbar-thumb { background: #C2CAD6; border-radius: 3px; }
  .home-stats::-webkit-scrollbar-track { background: transparent; }
  .home-stats > * { flex: 0 0 auto; }
  /* 工程名多给一点，别只剩两个字 */
  .home-stats > .mf-home-box { width: 210px; min-width: 210px; }
}
/* 手机端：卡片再放宽一点，手指点得着（同样是一行，靠横滑查看） */
@media (max-width: 900px) {
  .home-stats > .home-stat-action { width: 132px; min-width: 132px; }
  .home-stats > .home-cal { width: 236px; min-width: 236px; }
  .home-stats > .mf-home-box { width: 200px; min-width: 200px; }
  .home-stats > .dispatch-stat { width: 150px; min-width: 150px; }
  .home-stats > .outsource-stat { width: 112px; min-width: 112px; }
  .home-stats > .export-box { width: 190px; min-width: 190px; }
  .home-stats > .bill-stat { width: 162px; min-width: 162px; }
}

/* ---------- 施工人员账号「收货信息」（2026-10-27（第 150 节）） ----------
   点左侧菜单「收货信息」→ 按工程（采购订单）分卡片展示我签收的材料：
   材料名（+规格）一行、数量右对齐一行值，采集器（FSU）行沿用 149 节的紫底。
   服务端 /api/material-flow/my-issues 已聚合好数量，这里纯展示。 */
.mm-page { gap: 12px; }
.mm-card {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 12px 14px;
}
/* 已结算的订单整组沉底，卡片淡一点免得误以为还有新料 */
.mm-card.mm-done { opacity: .68; }
.mm-card-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.mm-card-head b { font-size: 15px; }
.mm-po-no { font-size: 12px; color: var(--text-3); }
.mm-rows { margin-top: 6px; display: flex; flex-direction: column; }
.mm-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding: 6px 0; border-bottom: 1px dashed var(--line); font-size: 13.5px; min-width: 0;
}
.mm-row:last-child { border-bottom: 0; }
.mm-name { min-width: 0; overflow-wrap: anywhere; }
.mm-spec { font-style: normal; font-size: 12px; color: var(--text-3); }
.mm-n { font-weight: 600; white-space: nowrap; }
/* 采集器行：紫底由 .mf-fsu-li 提供（149 节加深过的 #E5DBFA），整行上下贴一点 */
.mm-row.mm-fsu .mm-name, .mm-row.mm-fsu .mm-n { padding-top: 3px; padding-bottom: 3px; }
.mm-foot { margin-top: 8px; font-size: 12px; color: var(--text-3); }
/* 「已安装 N 台」数字：主题色加粗，和卡片里紫底 FSU 行呼应（2026-10-27（155）） */
.mm-foot .mm-inst { color: var(--accent); font-weight: 700; font-style: normal; }
@media (max-width: 900px) {
  .mm-card { padding: 10px 12px; }
  .mm-card-head b { font-size: 14.5px; }
}

/* ---------- 跑马灯去重后的垫行（2026-10-27（第 151 节）） ----------
   条数不够视口行数时，轨道里用空行把半份垫足（无缝循环要求半份 ≥ 视口行数），
   不再整段复制同一条信息。空行不显示内容、不画分隔线，就是一段透明的高度。 */
.vt-pad { height: 32px; flex: none; }

/* ---------- 「仓库直取」领料标签（2026-10-27（第 152 节）；165 节由「仓库同步」改名） ----------
   仓库人员随走随拿、不走发货记录；汇总表里他名下自动记入的那条采集器领料
   打上这个标签，和真实发货单区分开（数量照常参与剩余计算）。 */
.mf-sync-tag {
  font-style: normal; font-size: 10.5px; line-height: 1.5;
  color: #1F5FA5; background: #FFF; border: 1px solid #B9D3EE;
  border-radius: 3px; padding: 0 4px; margin-left: 3px; white-space: nowrap;
}

/* 横向跑马灯垫白（152 节）：一套 chip 窄于视口时垫在两半之间，同一条信息不同框两次 */
.mf-ticker-pad { display: inline-block; flex: none; }

/* ---------- 发货/收货登记：材料名与数量两列之间不再拉开（第 156 节，2026-10-27） ---------- */
/* 以前材料名下拉 width:100% 把整行吃满，数量输入被顶到屏幕最右边，中间一大片空白。
   改成固定列宽布局：材料名列 52%，数量列 130px 紧跟着（大致落在屏幕中间），
   剩下的宽度全给右边的删除列，✕ 仍然贴最右边（和以前位置一致）。 */
.mf-items { table-layout: fixed; }
.mf-items thead th:first-child { width: 52%; }
.mf-items .mf-th-qty { width: 130px; }
.mf-items .mf-td-del { text-align: right; padding-right: 10px; }
/* 手机（拍照账号）窄屏：还原成「下拉占满剩余、数量 72px」的老布局，别把材料名压太窄 */
body.photo-mode .mf-items thead th:first-child { width: auto; }

/* ---------- 材料清单行首「设备类别」标签（第 157 节，2026-10-27） ---------- */
/* 收货明细 / 发货明细 / 汇总清单共用：类别做成浅灰小标签，跟在材料名前面，
   行高跟着 .mf-li 的 1.6 走，不会把清单和数量两列的行对齐撑歪 */
.mf-cat {
  display: inline-block; font-style: normal; vertical-align: 1px;
  font-size: 10.5px; line-height: 1.45; color: #4A5568;
  background: #EEF1F6; border: 1px solid #DDE3EC; border-radius: 3px;
  padding: 0 5px; margin-right: 5px; white-space: nowrap;
}
/* 采集器那一行是紫底，类别标签跟着换成紫调，别在紫底上贴一块冷灰 */
.mf-fsu-li .mf-cat { color: #3F2478; background: #DCCDF8; border-color: #C4AEF0; }

/* ---------- 材料汇总：订单外框 + 施工人员分组框（第 158 节，2026-10-27） ---------- */
/* 一屏几十行，原来只靠一条浅灰横线分隔，分不清「哪几行是同一个订单、哪几行是同一个施工人员」。
   现在做两层框：
     ① 订单框（2px 蓝 #365EA1）：整条订单四周，含左边 rowspan 合并的工程/收货几列
     ② 施工人员框（1px 浅蓝 #94ABCE）：订单里每个领料人一行，围住「领料人 → 已安装数量」这几列
   border-collapse: collapse 下 tr 的边框不生效，只能逐格画 td 的边框，所以用类名标首末行。 */
.mf-os tr.mf-os-ord-f > td { border-top: 2px solid #365EA1; }
.mf-os tr.mf-os-ord-l > td { border-bottom: 2px solid #365EA1; }
/* 左边 4 列是 rowspan 跨整单的合并单元格，不在末行里，底边得自己画 */
.mf-os .mf-os-side { border-bottom: 2px solid #365EA1; }
.mf-os tr.mf-os-ord > td.mf-os-proj { border-left: 2px solid #365EA1; }
/* 施工人员框：每行一个领料人，上下边横跨「领料人 → 已安装数量」整段（右边界和订单框共用） */
.mf-os tr.mf-os-ord > td.mf-os-g {
  border-top: 1px solid #94ABCE;
  border-bottom: 1px solid #94ABCE;
}
.mf-os tr.mf-os-ord > td.mf-os-gm { border-left: 1px solid #94ABCE; }
.mf-os tr.mf-os-ord > td:last-child { border-right: 2px solid #365EA1; }

/* ---------- 汇总表左侧 4 列上下居中（第 159 节，2026-10-27） ---------- */
/* 166：领料人也跟着居中 —— 159 节只把左边 rowspan 那四列改成 middle，
   领料人还是跟着全局 .mf-os td 顶部对齐；一个人领了三四样材料时，名字贴在格顶、
   跟旁边「领料清单」的中间那行对不上，看着散。整格上下居中即可。 */
.mf-os td.mf-os-man { vertical-align: middle; }
/* 工程名称 / 收货清单 / 收货数量 / 剩余数量 是 rowspan 跨整条订单的合并单元格，
   原来跟着全局 .mf-os td 顶部对齐，订单里领料人一多，这几列的字就贴在最上面、
   显得偏；改成垂直居中（领料人那几列仍按内容自然排，不受影响）。 */
.mf-os td.mf-os-side { vertical-align: middle; }

/* ---------- 汇总表八列等宽：左右各占一半 + 全部左对齐（第 162 节，2026-10-27） ---------- */
/* 161 节只把左边四列做成四等分，结果左边合计 ~62%、右边领料四列被挤在右端一小块，
   而且数量列是右对齐、数字贴着格线，跟左边材料名的起点对不上。
   山叔要求：左边四列（工程名称/收货清单/收货数量/剩余数量）占界面一半，
   右边四列（领料人/领料清单/领料数量/已安装数量）也占一半，每列文字一律左对齐。
   八列同宽 = 每列 12.5%，天然就是「左半 50% / 右半 50%」。
   仍不给 table-layout:fixed（清单列 nowrap、要与数量列逐行对齐，定死会把长材料名挤出格子）。 */
/* 八列统一按类型定宽，合计 100%：左半 = 11+17+11+11 = 50%，右半 = 11+17+11+11 = 50%
   （清单列给了 17%，因为它要装「类别标签 + 厂家·型号」；数量列 11% 足够放「14 个」） */
.mf-os thead th.mf-c-proj { width: 11%; }
.mf-os thead th.mf-c-list { width: 17%; }
.mf-os thead th.mf-c-qty,
.mf-os thead th.mf-c-rem,
.mf-os thead th.mf-c-man,
.mf-os thead th.mf-c-inst { width: 11%; }
.mf-os thead th,
.mf-os td { text-align: left; }
/* 数量列原来右对齐（数字贴格线），改成左对齐后与材料名同一视觉起点；
   特异性要比 .mf-sum-table .num / .mf-os .mf-os-qty-td 高，所以把 td/th 带上 */
.mf-os th.num,
.mf-os td.num,
.mf-os .mf-os-qty-td { text-align: left; }
/* 161 节给数量列加的右内边距一并撤掉 —— 左对齐不需要，留着数字会离格线一截 */
.mf-os thead th:nth-child(3),
.mf-os thead th:nth-child(4),
.mf-os td.mf-os-qty-td { padding-right: 0; }

/* 164：已安装数量改成「领料清单逐行、数字落在采集器那一行」—— 行高字号必须和
   领料清单（.mf-li 12px/1.6）、领料数量（.mf-os-qty-td > span 12px/1.6）完全一致，
   否则同一行的三个格子会错开半行 */
.mf-os td.mf-os-inst > span { display: block; font-size: 12px; line-height: 1.6; }

/* ---------- 左上角徽标：城市名首字母缩写（第 168 节，2026-10-27） ---------- */
/* 原来是固定的「台」字，看不出当前在哪个城市；现在由 app.js 的 renderBrandMark()
   换成城市缩写（南通 NT / 淮安 HA / 扬州 YZ）。两个大写字母比单个汉字窄，
   字号略收、字重加粗，在 32px 的圆角方块里更稳。 */
/* ---------- 400维修单：勾选列（第 172 节，2026-10-28） ----------
   列表最前面一列勾选框，配合顶栏「🗑 删除选中」批量清掉导入多的维修单 */
th.pick-col, td.pick-col { width: 34px; text-align: center; padding-left: 4px; padding-right: 4px; }
th.pick-col input, td.pick-col input { width: 15px; height: 15px; cursor: pointer; vertical-align: middle; }

.logo { font-size: 14px; font-weight: 700; }

/* ---------- 城市选择页：城市账号只显示自己那一个框体（第 169 节，2026-10-27） ---------- */
/* .city-grid 是 auto-fill minmax(180px,1fr)：只剩一张卡片时会被 1fr 拉成整行宽、很难看。
   单卡片（.city-solo）时把列宽收成固定 240px 并居中；管理员（多城市）保持原来的铺满排布。 */
.city-wrap.city-solo .city-grid {
  grid-template-columns: minmax(180px, 240px);
  justify-content: center;
}
@media (max-width: 600px) {
  .city-wrap.city-solo .city-grid { grid-template-columns: minmax(140px, 200px); }
}

/* 山叔截图反馈的五点：① 右侧（领料那半边）最上/最下的框线比左边细；② 数量后面
   「个 / 台」这些单位参差不齐；③ 「已安装数量」没有底色；④ 工程名称要黑字；
   ⑤ 采集器紫底在「收货数量 / 剩余数量」两列连成一片，且右边溢出到框外。 */

/* ① 框线一致：158 节的「施工人员内框」规则 .mf-os tr.mf-os-ord > td.mf-os-g（0,3,2）
   特异性高于「订单外框」的 .mf-os tr.mf-os-ord-f > td（0,2,2），于是订单首/末行的
   右半边被内框的 1px 浅蓝盖掉，看起来右边上下两条线比左边细。这里把订单框的
   首/末行规则提到同级（带上 .mf-os-ord）并写在后面，右半边也回到 2px #365EA1。 */
.mf-os tr.mf-os-ord.mf-os-ord-f > td { border-top: 2px solid #365EA1; }
.mf-os tr.mf-os-ord.mf-os-ord-l > td { border-bottom: 2px solid #365EA1; }

/* ② 单位对齐：数值放进 .mf-qv（定宽 3ch，够放三位数的量），单位 .mf-qu 跟在后面，
   无论「8 个」还是「14 台」，单位都落在同一个横坐标上 */
/*   170 节：已安装数量后面也带单位了，选择器一并带上 td.mf-os-inst */
.mf-os .mf-os-qty-td > span > .mf-qv,
.mf-rec .mf-os-qty-td > span > .mf-qv,
.mf-os td.mf-os-inst > span > .mf-qv {
  display: inline-block; min-width: 3ch; font-weight: inherit;
}
.mf-os .mf-os-qty-td > span > .mf-qu,
.mf-rec .mf-os-qty-td > span > .mf-qu,
.mf-os td.mf-os-inst > span > .mf-qu {
  font-style: normal; margin-left: 5px; font-weight: inherit;
}

/* ③ 已安装数量的底色（170 节改过）：163 节那版是**整列**铺 #E5DBFA，太重、跟别的列
   不是一个逻辑；现在改成只给采集器那一行加 .mf-fsu-li（和「领料清单 / 领料数量」同款），
   由下面的 .mf-fsu-li 规则统一供色。这里不再给整格上底色。 */
/* .mf-os td.mf-os-inst { background: #E5DBFA; } —— 170 节停用（整列底色取消） */

/* ④ 工程名称：整列文字用黑色（订单号加粗黑，工程名副标题从灰 #8A94A6 也提黑）；
   「订单已结算」小标保留橙色，它是状态提示，跟着变黑就看不出来了 */
.mf-os td.mf-os-proj,
.mf-os td.mf-os-proj b { color: #000; }
.mf-os td.mf-os-proj .mf-sub { color: #1F2328; }

/* ⑤ 紫底不再连成一片、也不再溢出框外：原来 .mf-fsu-li 左右都是 padding 6px +
   负 margin -6px（色块有呼吸感但文字不动），在汇总表里这几个 span 是 display:block、
   宽度撑满整格，负 margin 就等于左右各往邻列探 6px —— 于是「收货数量 / 剩余数量」
   两格的紫底贴上变成一条通带，最右边那格更是探出了订单框。
   改法：左边仍用 -6px（文字起点不变），右边改成正 margin 6px（色块收进来 6px），
   相邻两列之间就留出 8px 空隙，右边界也缩回框内。 */
.mf-os .mf-fsu-li { margin: 0 6px 0 -6px; padding: 0 0 0 6px; }


/* ============ 182 · 首页：待办清单 / 遗留问题 撑到视口底部（2026-10-29） ============
   原来两块卡片高度按内容走，内容不多时屏幕下方留一大片空白。
   做法：只在首页（body.home-mode）把 .main 变成纵向 flex 容器，
   内容区吃满剩余高度 → 网格被拉高 → 两张卡片跟着拉伸，列表在卡片内部自己滚。
   列表页 / 详情页布局完全不受影响（没有 home-mode 这个 class）。 */
body.home-mode .main { display: flex; flex-direction: column; padding-bottom: 0; }
/* 185：把整页钉死在视口高度内——.app 默认是 min-height:100vh（可被内容撑高），
   会让下方 flex 链失去确定高度、网格被内容（遗留列表 15 行）撑高 → 整页出现外层滚动条。
   首页改成「.app 固定 100vh + overflow:hidden」，内部卡片各自滚动，外层永不滚动。
   （弹窗 #modalRoot / 提示 #toastRoot 都在 .app 之外，不会被裁切。） */
body.home-mode .app { height: 100vh; overflow: hidden; }
body.home-mode #homeView { flex: 1 1 auto; min-height: 0; }
body.home-mode .home-view .home-grid { flex: 1 1 auto; align-items: stretch; min-height: 0; }
body.home-mode .home-view .home-grid > .home-card { height: 100%; }
/* 卡片内部：头部/快速添加固定，列表吃掉剩下的高度并自己滚动。
   注意：遗留问题列表 .legacy-list 默认有 max-height:460px（见第 994 行），
   首页要撑满时必须在此覆盖成 none，否则右侧卡片下会留一大截空白。 */
body.home-mode .home-view .home-grid > .home-card > .todo-list { flex: 1 1 auto; min-height: 0; max-height: none; }
/* 185 · 遗留问题列表不再锁行数：原 capHomeLegacyList 用内联 maxHeight 限制 15 行，
   会导致卡片拉伸后列表下方留白。现由 JS 改为清空限制，此处 flex:1 + max-height:none
   让列表随卡片撑满、多余条目在卡内滚动；卡片 height:100% + .app{overflow:hidden}
   已保证整页不出现外层滚动条。 */

/* 窄屏（≤1000px）是单列，两块卡片按内容高度排下来更好用，不拉伸 */
@media (max-width: 1000px) {
  body.home-mode .home-view .home-grid { flex: 0 0 auto; align-items: start; }
  body.home-mode .home-view .home-grid > .home-card { height: auto; }
  body.home-mode .main { padding-bottom: 32px; }
  /* 单列时不再拉伸，但遗留问题最多 30 条，给个视口上限让它内部滚，免得整页太长 */
  body.home-mode .home-view .home-grid > .home-card > .todo-list.legacy-list { max-height: 55vh; }
}

/* 遗留问题板块：灰青底色（参考色 #778287）+ 卡片拉伸铺满、列表填满不留白 */
.home-card-legacy {
  align-self: stretch; display: flex; flex-direction: column;
  background: #778287; border-color: #6A767B;
}
.home-card-legacy .home-card-head { border-bottom-color: rgba(255,255,255,.18); }
.home-card-legacy .home-card-head h3 { color: #fff; }
.home-card-legacy .home-count { color: rgba(255,255,255,.82); }
.home-card-legacy .home-card-head .btn { color: #fff; border-color: rgba(255,255,255,.5); }
.home-card-legacy .legacy-list { flex: 1 1 auto; min-height: 0; max-height: none; }

/* 外包清单·重点关注：顶部一排的外包清单卡（2026-11-03）
   卡内直接列出重点关注的外包单：项目编号(可点跳编辑) + 项目名称 + 状态 + 服务对象 */
.home-stats > .outsource-stat.focus-card {
  flex: 1.7 1 auto; width: 250px; min-width: 250px;
  display: flex; flex-direction: column; gap: 6px;
  padding: 10px 12px;
}
.focus-card .home-stat-label { font-size: 14px; font-weight: 700; color: var(--accent); }
.focus-card .focus-list {
  display: flex; flex-direction: column; gap: 4px;
  min-height: 0; overflow: hidden;
}
.focus-card .focus-empty {
  font-size: 11.5px; color: var(--text-3); line-height: 1.5; text-align: center;
  padding: 8px 4px;
}
.focus-row {
  display: flex; align-items: center; gap: 6px;
  padding: 4px 8px; border: 1px solid #DDE3EC; border-radius: 6px; background: #F7F9FC;
}
.focus-row:hover { background: #EFF3F9; }
.focus-no {
  flex: none; border: 0; background: none; padding: 0; cursor: pointer;
  font: inherit; font-size: 12px; font-weight: 600; color: var(--accent);
  text-decoration: underline; text-underline-offset: 2px; white-space: nowrap;
}
.focus-no:hover { color: #0A5CC0; }
.focus-name {
  flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; font-size: 11.5px; color: var(--text-2);
}
.focus-row > .tag, .focus-row > .scope-tag, .focus-row > .focus-so { flex: none; }
.focus-so { flex: none; font-size: 11px; font-weight: 500; color: #1A5FB4;
  background: #E8F0FB; border: 1px solid #C9DDF5; border-radius: 4px; padding: 0 5px;
  line-height: 1.6; white-space: nowrap; }

/* ---------- 照片归档到 OSS（2026-10-31） ---------- */
.modal.arch-box { max-width: 560px; }
.arch-stat {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin: 2px 0 14px;
}
.arch-stat > div {
  background: #F5F7FB; border: 1px solid #E3E8F2; border-radius: 8px;
  padding: 10px 6px; text-align: center;
}
.arch-stat b { display: block; font-size: 17px; color: #365EA1; line-height: 1.35; }
.arch-stat span { font-size: 12px; color: #76839A; }
.arch-opt {
  display: flex; align-items: flex-start; gap: 7px; font-size: 13px; color: #3D4A5E;
  margin: 4px 0 10px; line-height: 1.55; cursor: pointer;
}
.arch-opt input { margin-top: 3px; flex: 0 0 auto; }
.arch-box .hint { font-size: 12.5px; color: #76839A; line-height: 1.6; margin: 6px 0; }
.arch-box .hint.warn { color: #A9721B; }
.arch-box .hint.err { color: #B23A3A; }
.arch-box .hint.acc { color: #2C6B45; }
.arch-box .hint code {
  background: #F0F3F9; border-radius: 3px; padding: 0 4px; font-size: 11.5px;
}
/* 列表里已归档的按钮：淡绿底，一眼区分 */
.mini.arch-done { background: #CDEBD8; border-color: #A8D8BD; color: #1E5B3A; }
.mini.arch-done:hover { background: #BFE3CC; }
@media (max-width: 620px) {
  .arch-stat { grid-template-columns: repeat(2, 1fr); }
}
