/* ===== 基础 & 变量 ===== */
* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

:root {
  --gold: #C9A227;
  --gold-light: #E8D9A8;
  --gold-dark: #A8851A;
}

/* 浅色模式（默认） */
body[data-theme="light"] {
  --bg: #F7F5F0;
  --card: #FFFFFF;
  --card-hover: #FAFAF8;
  --text: #2D3142;
  --text-secondary: #7E8294;
  --text-tertiary: #A0A3B1;
  --border: rgba(0,0,0,0.05);
  --shadow: 0 4px 16px rgba(0,0,0,0.06);
  --gold: #C9A227;
  --gold-soft: #F5EFDC;
}

/* 深色模式 */
body[data-theme="dark"] {
  --bg: #0E1626;
  --card: #162033;
  --card-hover: #1B2840;
  --text: #F4F6FA;
  --text-secondary: #9BA3B4;
  --text-tertiary: #6B7488;
  --border: rgba(255,255,255,0.06);
  --shadow: 0 4px 20px rgba(0,0,0,0.35);
  --gold: #D4AF37;
  --gold-soft: rgba(212,175,55,0.12);
}

html, body {
  height: 100%;
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", "Segoe UI", sans-serif;
  background: var(--bg);
  color: var(--text);
  transition: background .25s ease, color .25s ease;
}

#app {
  max-width: 560px;
  min-height: 100vh;
  margin: 0 auto;
  background: var(--bg);
  position: relative;
  overflow-x: hidden;
  transition: background .25s ease;
}

.page {
  display: none;
  min-height: 100vh;
  flex-direction: column;
}
.page.active { display: flex; }

/* ===== 顶部栏 ===== */
.home-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 20px 10px;
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--bg);
  transition: background .25s ease;
}

.brand {
  display: flex;
  align-items: center;
  gap: 14px;
}

.brand-logo {
  width: 78px;
  height: 40px;
  flex-shrink: 0;
  color: var(--gold);
  display: flex;
  align-items: center;
  justify-content: center;
}
.brand-logo svg {
  width: 100%;
  height: 100%;
  filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.12));
}

.brand-text {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
}

.brand-title {
  font-size: 19px;
  font-weight: 700;
  letter-spacing: 0.3px;
  line-height: 1.25;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.brand-sub {
  font-size: 13px;
  color: var(--gold);
  font-weight: 500;
  line-height: 1.3;
  margin-top: 2px;
  white-space: nowrap;
}

.icon-btn {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: none;
  background: var(--card);
  color: var(--gold);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: var(--shadow);
  transition: transform .12s ease, background .2s ease, color .2s ease;
}
.icon-btn:active { transform: scale(0.94); }
.icon-btn svg { width: 22px; height: 22px; }

/* 设置齿轮：点击转动效果 */
.settings-trigger svg { transform-origin: center; }
.settings-trigger.spin-cw svg { animation: gear-cw .55s cubic-bezier(.45,.05,.25,1); }
.settings-trigger.spin-ccw svg { animation: gear-ccw .55s cubic-bezier(.45,.05,.25,1); }
@keyframes gear-cw { from { transform: rotate(0); } to { transform: rotate(360deg); } }
@keyframes gear-ccw { from { transform: rotate(0); } to { transform: rotate(-360deg); } }

/* ===== 首页主体 ===== */
.home-main {
  flex: 1;
  padding: 10px 20px calc(24px + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* 统计卡 */
.stats-row {
  display: grid;
  /* minmax(0, 1fr) 而不是 1fr：1fr 的最小宽度是 auto，会被卡里的长金额
     （如 ¥202,230.00）撑破，导致两张卡一宽一窄、窄的那张更挤 */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

/* 领班视角：工程款卡被 applyRoleToHome 收起后只剩一张卡，让它独占整行，
   否则右边会空出半块、看着像坏掉 */
.stats-row.single {
  grid-template-columns: 1fr;
}

.stat-card {
  background: var(--card);
  border-radius: 18px;
  padding: 16px;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  gap: 6px;
  position: relative;
  min-width: 0;
  transition: background .25s ease, box-shadow .25s ease;
}

.stat-label {
  font-size: 13px;
  color: var(--text-secondary);
  font-weight: 500;
}

/* 统计卡右上角工程筛选下拉 */
.stat-filter {
  position: absolute;
  top: 12px;
  right: 12px;
}
.proj-filter {
  appearance: none;
  -webkit-appearance: none;
  background: var(--bg);
  border: 1px solid var(--border-soft, var(--card-border));
  border-radius: 999px;
  padding: 4px 22px 4px 10px;
  font-size: 12px;
  font-weight: 600;
  color: var(--gold);
  cursor: pointer;
  outline: none;
  max-width: 96px;
  text-overflow: ellipsis;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%23C9A227' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><polyline points='3 5 6 8 9 5'/></svg>");
  background-repeat: no-repeat;
  background-position: right 6px center;
  background-size: 10px;
  transition: border-color .2s;
}
.proj-filter:hover { border-color: var(--gold); }
.proj-filter:focus { border-color: var(--gold); }
.proj-filter option {
  color: var(--text);
  background: var(--bg);
  font-weight: 500;
}

.stat-value {
  font-size: 24px;
  font-weight: 700;
  color: var(--gold);
  letter-spacing: -0.3px;
}

.stat-meta {
  font-size: 12px;
  color: var(--text-tertiary);
}

/* 统计卡金额统一金色（继承 .stat-value） */
.stat-in,
.stat-out {
  color: var(--gold);
}

/* 功能宫格 */
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}

.grid-item {
  background: var(--card);
  border: none;
  border-radius: 18px;
  padding: 16px 8px 14px;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  transition: transform .12s ease, background .2s ease, box-shadow .2s ease;
}
.grid-item:active { transform: scale(0.96); }
.grid-item:hover { background: var(--card-hover); }

.grid-item.primary {
  background: linear-gradient(135deg, var(--gold) 0%, var(--gold-dark) 100%);
  color: #fff;
}
.grid-item.primary .grid-icon { color: #fff; }
.grid-item.primary .grid-title { color: #fff; }
.grid-item.primary .grid-desc { color: rgba(255,255,255,0.85); }

.grid-icon {
  width: 32px;
  height: 32px;
  color: var(--gold);
  display: flex;
  align-items: center;
  justify-content: center;
}
.grid-icon svg { width: 100%; height: 100%; }

.grid-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}

.grid-desc {
  font-size: 11px;
  color: var(--text-secondary);
  line-height: 1.35;
  text-align: center;
  min-height: 30px;
}

/* 最新一笔 */
.latest-card {
  background: var(--card);
  border-radius: 18px;
  padding: 14px 16px;
  box-shadow: var(--shadow);
  transition: background .25s ease, box-shadow .25s ease;
}

.latest-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}

.latest-label {
  font-size: 13px;
  color: var(--text-secondary);
}

.latest-tag {
  font-size: 11px;
  color: var(--gold);
  background: var(--gold-soft);
  padding: 3px 10px;
  border-radius: 999px;
  font-weight: 500;
}

.latest-body {
  display: block;
}
.latest-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}
.latest-left {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.latest-amount {
  font-size: 22px;
  font-weight: 800;
  color: var(--gold);
  line-height: 1.2;
}
.latest-project {
  font-size: 12px;
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.latest-item {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 19px;
  font-weight: 700;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ===== 首页 PC 补充区（移动端隐藏） ===== */
.home-below {
  display: none;
}

.panel {
  background: var(--card);
  border-radius: 18px;
  padding: 18px 20px;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  gap: 10px;
  transition: background .25s ease, box-shadow .25s ease;
}

.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.panel-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
}

.panel-more {
  font-size: 12px;
  color: var(--text-tertiary);
  display: flex;
  align-items: center;
  gap: 8px;
}

.panel-empty {
  font-size: 13px;
  color: var(--text-tertiary);
  text-align: center;
  padding: 26px 0;
}

/* 最近记录列表 */
.recent-list {
  display: flex;
  flex-direction: column;
}

.recent-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 0;
  border-bottom: 1px solid var(--border);
}
.recent-row:last-child { border-bottom: none; }

.recent-date {
  font-size: 12px;
  color: var(--text-tertiary);
  width: 44px;
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}

.recent-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.recent-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 6px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.recent-sub {
  font-size: 12px;
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.recent-amt {
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}

/* 本月收支柱状图 */
.trend-chart {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: flex-end;
  gap: 3px;
  padding-bottom: 2px;
}

.trend-col {
  flex: 1;
  height: 100%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  gap: 3px;
}

.trend-col-track {
  width: 100%;
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 1px;
  border-radius: 4px 4px 1px 1px;
  background: rgba(0, 0, 0, 0.04);
}

.trend-bar {
  width: 5px;
  border-radius: 2px 2px 1px 1px;
  transition: height .3s ease;
  flex-shrink: 0;
}
.trend-in { background: #C43B3B; }
.trend-out { background: #2E8B57; }

.trend-label {
  font-size: 10px;
  color: var(--text-tertiary);
  height: 14px;
  line-height: 14px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.trend-label.empty {
  color: transparent;
}

.dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
.dot-in { background: #C43B3B; }
.dot-out { background: #2E8B57; }

/* ===== 子页面 ===== */
.sub-header {
  display: grid;
  grid-template-columns: 56px 1fr auto;
  align-items: center;
  padding: 14px 16px;
  background: var(--bg);
  position: sticky;
  top: 0;
  z-index: 10;
  border-bottom: 1px solid var(--border);
}
.sub-header .back-btn { justify-self: start; }
.sub-header h2 {
  font-size: 17px;
  font-weight: 600;
  text-align: center;
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sub-header .header-actions { justify-self: end; }

.sub-main {
  flex: 1;
  padding: 16px;
  overflow-y: auto;
}

/* ===== 设置面板 ===== */
.mask {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.35);
  opacity: 0;
  visibility: hidden;
  transition: opacity .25s ease, visibility .25s ease;
  z-index: 50;
}
.mask.show { opacity: 1; visibility: visible; }

.settings-panel {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  background: var(--card);
  border-radius: 24px 24px 0 0;
  padding: 20px 20px calc(28px + env(safe-area-inset-bottom));
  box-shadow: 0 -8px 30px rgba(0,0,0,0.18);
  transform: translateY(110%);
  transition: transform .3s cubic-bezier(.25,.8,.25,1), background .25s ease;
  z-index: 60;
  max-width: 560px;
  margin: 0 auto;
  /* 🔴 这里以前只有 bottom、没有高度上限，也没有滚动 ——
     面板于是按内容向上生长：内容 925px、屏幕 667px 时，顶部跑到 -258px，
     右上角那个叉号跟着长到屏幕**外面**，而且因为一个滚动条都没有，滚也滚不回来。
     天阁 2026-09-23「设置界面没有叉号，我要原本右上角那个叉号」就是这个成因。
     下面四行 + .settings-body 让它变成：头部钉住、中间内部滚动。
     （同款正确写法项目里早有：.ai-drawer / .ai-head / .ai-body，这里对齐它。）*/
  max-height: 86vh;
  max-height: 86dvh;       /* 手机上 vh 把地址栏也算进去，dvh 才是真实可视高 */
  display: flex;           /* 竖向两段：头部固定 / 内容区滚动 */
  flex-direction: column;
}
.settings-panel.show { transform: translateY(0); }

/* ===== AI 助手抽屉 ===== */
.header-actions {
  display: flex;
  align-items: center;
  gap: 10px;
}
.ai-trigger {
  color: var(--text-secondary);
  transition: color .2s ease, transform .15s ease;
}
.ai-trigger:hover { color: var(--gold); }
.ai-trigger:active { transform: scale(.92); }

.ai-drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(420px, 86vw);
  background: var(--card);
  box-shadow: -6px 0 30px rgba(0,0,0,0.15);
  transform: translateX(110%);
  transition: transform .3s cubic-bezier(.25,.8,.25,1), background .25s ease;
  z-index: 60;
  display: flex;
  flex-direction: column;
}
.ai-drawer.show { transform: translateX(0); }

.ai-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 18px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.ai-head h3 {
  font-size: 17px;
  font-weight: 600;
  color: var(--text-primary);
  flex: 1;
}
.ai-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  object-fit: cover;
  margin-right: 10px;
  border: 2px solid var(--gold, #C9A227);
  flex-shrink: 0;
}

.ai-body {
  flex: 1;
  overflow-y: auto;
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.ai-quick {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 8px;
}
.ai-chip {
  border: 1px solid var(--gold);
  background: transparent;
  color: var(--gold);
  border-radius: 999px;
  padding: 6px 12px;
  font-size: 12px;
  cursor: pointer;
  transition: background .2s ease, color .2s ease;
}
.ai-chip:hover { background: var(--gold); color: #fff; }

.ai-msg {
  display: flex;
  max-width: 88%;
}
.ai-msg.ai-user {
  align-self: flex-end;
  justify-content: flex-end;
}
.ai-msg.ai-ai {
  align-self: flex-start;
}
.ai-bubble {
  padding: 10px 13px;
  border-radius: 14px;
  font-size: 14px;
  line-height: 1.5;
  word-break: break-word;
}
.ai-user .ai-bubble {
  background: var(--gold);
  color: #fff;
  border-bottom-right-radius: 4px;
}
.ai-ai .ai-bubble {
  background: var(--bg);
  color: var(--text-primary);
  border: 1px solid var(--border);
  border-bottom-left-radius: 4px;
}
.ai-ai.ai-refuse .ai-bubble {
  background: rgba(201,162,39,0.08);
  border: 1px dashed var(--gold);
  color: var(--text-secondary);
}

.ai-foot {
  padding: 12px 18px calc(16px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}
.ai-input-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 5px 5px 5px 14px;
}
.ai-input-wrap input {
  flex: 1;
  border: none;
  background: transparent;
  color: var(--text-primary);
  font-size: 14px;
  outline: none;
}
.ai-input-wrap input::placeholder { color: var(--text-hint); }
.ai-send {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: none;
  background: var(--gold);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: opacity .2s ease, transform .15s ease;
}
.ai-send:hover { opacity: .9; }
.ai-send:active { transform: scale(.94); }
.ai-send svg { width: 16px; height: 16px; }

.ai-mode-hint {
  text-align: center;
  font-size: 11px;
  color: var(--gold);
  margin-top: 8px;
  min-height: 15px;
  opacity: 0;
  transition: opacity .2s ease;
}
.ai-mode-hint.show { opacity: 1; }

@media (max-width: 560px) {
  .ai-drawer { width: 100%; }
}

/* 窄屏适配：防止首页标题被图标挤压成竖排 */
@media (max-width: 400px) {
  .home-header { padding: 14px 12px 8px; gap: 8px; }
  .brand { gap: 8px; min-width: 0; }
  .brand-text { min-width: 0; }
  .brand-logo { width: 52px; height: 30px; }
  .brand-title { font-size: 16px; }
  .brand-sub { font-size: 11px; }
  /* 图标组不许被压缩变形，空间不够时让标题去省略号 */
  .home-header .header-actions { gap: 4px; flex-shrink: 0; }
  .home-header .icon-btn { width: 34px; height: 34px; }
}

.settings-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
  flex: 0 0 auto;          /* 🔴 头部不参与收缩：滚的只有下面那块，叉号永远钉在右上角 */
}
.settings-head h3 {
  font-size: 18px;
  font-weight: 600;
}

/* 🔴 设置内容区：滚动发生在这里（以前这个元素根本没有样式，是普通块，
   整块面板一起向上溢出 → 叉号出屏且无法滚动）。 */
.settings-body {
  flex: 1 1 auto;          /* 吃掉头部之外的剩余高度 */
  min-height: 0;           /* 🔴 flex 子项默认 min-height:auto，不写这行它不肯收缩，也就滚不起来 */
  overflow-y: auto;        /* 天阁要的「中间太多了就做滑动」 */
  overscroll-behavior: contain;   /* 手机上滚到底别再带着背景页面一起动 */
}

.settings-group {
  margin-bottom: 22px;
}
.settings-label {
  display: block;
  font-size: 13px;
  color: var(--text-secondary);
  margin-bottom: 10px;
  font-weight: 500;
}

.settings-options {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.option-btn {
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text);
  border-radius: 12px;
  padding: 12px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all .2s ease;
}
.option-btn.active {
  border-color: var(--gold);
  background: var(--gold-soft);
  color: var(--gold);
}

.creator-card {
  border: 1px solid var(--gold);
  border-radius: 14px;
  padding: 16px;
  text-align: center;
  background: var(--gold-soft);
}
.creator-slogan {
  font-size: 14px;
  font-weight: 600;
  color: var(--gold);
  line-height: 1.5;
}
.install-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  padding: 12px 16px;
  border: 1px solid var(--gold);
  border-radius: 14px;
  background: var(--gold-soft);
  color: var(--gold);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.install-btn:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(201, 162, 39, 0.25); }
.install-btn:disabled,
.install-btn.disabled {
  opacity: 0.7;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}
.install-btn svg { width: 17px; height: 17px; flex-shrink: 0; }
.install-hint {
  margin: 8px 0 0;
  font-size: 12px;
  color: var(--text-tertiary, #999);
  line-height: 1.6;
  text-align: center;
}
.install-desc {
  margin: 6px 0 0;
  font-size: 11.5px;
  color: var(--text-tertiary, #999);
  line-height: 1.5;
  text-align: center;
}
.install-btn-secondary {
  margin-top: 14px;
  background: var(--gold);
  color: #12203a;
  border-color: var(--gold);
}
.install-btn-secondary:hover:not(:disabled) { box-shadow: 0 4px 14px rgba(201, 162, 39, 0.32); }
.install-btn-secondary:active { opacity: .85; }

/* 账号 + 主动登出 */
.account-card {
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 12px 14px;
  background: var(--card);
  margin-bottom: 12px;
}
.account-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
}
.logout-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  margin-top: 10px;
  padding: 12px 16px;
  border: 1px solid var(--gold);
  border-radius: 14px;
  background: var(--card);
  color: var(--gold);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background .2s ease, color .2s ease;
}
.logout-btn:hover { background: var(--gold); color: #fff; }
.logout-btn svg { width: 17px; height: 17px; flex-shrink: 0; }
.change-pwd-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  margin-top: 10px;
  padding: 12px 16px;
  border: 1px solid var(--gold);
  border-radius: 14px;
  background: var(--gold);
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: filter .2s ease;
}
.change-pwd-btn:hover { filter: brightness(1.06); }
.change-pwd-btn svg { width: 17px; height: 17px; flex-shrink: 0; }

/* AI 反馈列表 */
.ai-fb-list { width: 100%; }
.ai-fb-title { font-weight: 600; margin-bottom: 8px; }
.ai-fb-list ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.ai-fb-item { border-top: 1px dashed var(--border); padding-top: 6px; }
.ai-fb-item:first-child { border-top: none; padding-top: 0; }
.ai-fb-meta { font-size: 11px; color: var(--text-secondary); margin-bottom: 3px; word-break: break-all; }
.ai-fb-content { font-size: 13px; line-height: 1.5; word-break: break-word; white-space: pre-wrap; }
.ai-fb-sec { margin-top: 10px; font-weight: 600; font-size: 13px; padding-left: 8px; border-left: 3px solid var(--gold, #C9A227); }
.ai-fb-sec:first-of-type { margin-top: 6px; }
.ai-fb-sec-q { border-left-color: #4A90D9; }
.ai-fb-sec-f { border-left-color: #D97B4A; }
.ai-fb-sec ul { margin-top: 6px; }
.ai-fb-none { color: var(--text-secondary); font-size: 12px; }

/* ===== 文本框基线（2026-10-04）=====
   为什么要有这一段：补名弹窗里那几个文本框当时**一行样式都没写**，
   于是直接露出浏览器的默认长相 —— 方角 + 内凹灰边 + 纯白底，
   跟全站的金色胶囊完全不是一套。天阁截图指出「还是一样的问题」。
   —— 只靠"记得给每个新输入框补样式"是靠不住的（就是漏了才出这事），
   所以这里反过来做：给文字类输入框定一份**兜底基线**，裸框自动穿衣服。

   🔴 关键：必须用 `:where(...)` 包起来。`:where()` 的**优先级恒为 0**，
      任何已有的 class / 容器规则都稳压它一头 —— 只有"谁都没管过"的裸框才吃到这里。
      （踩过的坑：一开始写成 `input[type="text"]`，属性选择器优先级 (0,1,1)，
        反而盖过了 `.assign-row-input`(0,1,0)、`.ai-input-wrap input`(0,1,1) ——
        `.ai-input-wrap` 是**透明无边框**设计，会被硬穿上一圈边框，改坏本来好的东西。）
   ⚠️ 只圈文字类 + textarea + select。**不碰** checkbox / radio / file /
      range / color / hidden；也不对 date 设 appearance（要保留原生日历按钮）。
   ⚠️ login.html 自带独立样式、不引本文件，不受此处影响。 */
:where(input[type="text"],
       input[type="number"],
       input[type="search"],
       input[type="tel"],
       input[type="password"],
       input[type="date"],
       textarea,
       select) {
  font-family: inherit;
  font-size: 15px;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 10px 12px;
  outline: none;
  transition: border-color .2s ease, box-shadow .2s ease;
}
/* 去掉数字框的上下小箭头（原生控件，跟主题不搭）。这一类是"修饰"不是"基线"，
   单独写（优先级高于 :where），但只在没被更具体的规则管过时才生效不了 —— 无妨。 */
:where(input[type="number"]) { appearance: textfield; -moz-appearance: textfield; }
:where(input[type="number"])::-webkit-outer-spin-button,
:where(input[type="number"])::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
:where(input[type="search"]) { appearance: none; -webkit-appearance: none; }
:where(input[type="text"], input[type="number"], input[type="search"],
       input[type="tel"], input[type="password"], input[type="date"],
       textarea)::placeholder { color: var(--text-tertiary); }
:where(input[type="text"], input[type="number"], input[type="search"],
       input[type="tel"], input[type="password"], input[type="date"],
       textarea, select):focus {
  border-color: var(--gold);
  box-shadow: 0 0 0 2px rgba(201, 162, 39, 0.18);
}

/* ===== 表单与通用组件 ===== */
.form-card {
  background: var(--card);
  border-radius: 18px;
  padding: 16px;
  box-shadow: var(--shadow);
  margin-bottom: 14px;
}

.form-group {
  margin-bottom: 14px;
}
.form-group:last-child { margin-bottom: 0; }
.form-group label {
  display: block;
  font-size: 13px;
  color: var(--text-secondary);
  margin-bottom: 6px;
  font-weight: 500;
}
.form-group input,
.form-group select,
.form-group textarea {
  width: 100%;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  border-radius: 12px;
  padding: 12px;
  font-size: 15px;
  outline: none;
  font-family: inherit;
}
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
  border-color: var(--gold);
}

/* ===== 查询页工程名称自定义下拉组合框 ===== */
.combo-wrap {
  position: relative;
  width: 100%;
}
.combo-wrap input {
  width: 100%;
  padding-right: 44px;
}
.combo-arrow {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  width: 34px;
  height: 34px;
  border: none;
  border-radius: 50%;
  background: var(--gold);
  color: #fff;
  font-size: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: opacity .15s ease, transform .12s ease;
}
.combo-arrow:active { transform: translateY(-50%) scale(0.94); }
.combo-list {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  min-width: 100%;
  width: max-content;
  max-width: min(420px, 90vw);
  z-index: 100;
  max-height: 240px;
  overflow-y: auto;
  margin: 0;
  padding: 6px 0;
  list-style: none;
  background: var(--card);
  border: 1px solid var(--gold);
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0,0,0,.12);
  white-space: nowrap;
}
.combo-list.hidden { display: none; }
.combo-list li {
  padding: 10px 14px;
  cursor: pointer;
  color: var(--text);
  font-size: 15px;
  transition: background .12s ease;
}
.combo-list li:hover,
.combo-list li.active {
  background: rgba(201,162,39,.15);
  color: var(--gold);
}
.combo-list .combo-empty {
  padding: 12px 14px;
  color: var(--text-tertiary);
  cursor: default;
}
body[data-theme="dark"] .combo-list {
  background: var(--card);
  box-shadow: 0 8px 24px rgba(0,0,0,.35);
}
body[data-theme="dark"] .combo-list li:hover,
body[data-theme="dark"] .combo-list li.active {
  background: rgba(201,162,39,.22);
}
.global-combo-list { z-index: 10000; }
/* 表格内工程名称组合框：输入框撑满单元格，避免被 .cell-in 固定宽度压窄 */
.data-table .combo-wrap .cell-in { width: 100%; padding-right: 30px; }

/* 工程名称列加宽（2026-10-04 天阁反馈：框太窄＋金色大圆饼挡着，看不清「填了没填」）。
   表格本来就支持横向滚动（.data-table-wrap / .pan-table-wrap），加宽只把表拉长、
   不会挤压别的列 —— 宁可多拖一下，也别让客户认不出这里填没填。 */
.data-table td > .cell-in[data-f="project"],
.data-table .combo-wrap { min-width: 220px; }

/* 表格内的下拉箭头：34px 金色实心圆 → 角落里的安静小箭头，不与框里的字抢视线 */
.data-table .combo-wrap .combo-arrow {
  width: 22px;
  height: 22px;
  right: 5px;
  background: transparent;
  color: var(--text-tertiary);
  font-size: 10px;
}
.data-table .combo-wrap .combo-arrow:active { transform: translateY(-50%) scale(0.88); }

.btn-row {
  display: flex;
  gap: 10px;
  margin-top: 6px;
}
.btn {
  flex: 1;
  border: none;
  border-radius: 12px;
  padding: 12px;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  transition: opacity .15s ease, transform .12s ease;
}
.btn:active { transform: scale(0.98); }
/* 防连点：提交期间置灰。⚠️ .btn 带 transition: opacity .15s →
   截图/断言要**等样式落定**再判，否则会拍到"还没变灰"的中间态（2026-10-02 栽过）。 */
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn:disabled:active { transform: none; }
.btn-primary {
  background: var(--gold);
  color: #fff;
}
.btn-secondary {
  background: var(--card);
  color: var(--text);
  border: 1px solid var(--border);
}

/* 手动录入区块 */
.manual-entry {
  background: var(--card);
  border-radius: 18px;
  padding: 16px;
  box-shadow: var(--shadow);
  margin: 14px 0;
}
.manual-head { margin-bottom: 10px; }
/* 「横屏填写」按钮那一行（2026-10-05）。
   ⚠️ .manual-head 还被人工成本录入页（labor.js）用着，所以这里只加修饰类，
      不动 .manual-head 本身 —— 改基础类会把那边一起改掉（见 MEMORY 34 条）。 */
.manual-head-flex {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 10px;
}
.manual-head-flex .manual-head-text { flex: 1; min-width: 0; }
.btn-rotate {
  flex: none;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 7px 11px;
  border: 1px solid var(--border); border-radius: 999px;
  background: var(--card); color: var(--text-secondary);
  font-family: inherit; font-size: 12px; font-weight: 600; line-height: 1;
  cursor: pointer;
  transition: border-color .18s ease, background .18s ease, color .18s ease;
}
.btn-rotate svg { width: 15px; height: 15px; }
.btn-rotate:hover { border-color: var(--gold); color: var(--gold); }
.btn-rotate.active { border-color: var(--gold); background: var(--gold-soft); color: var(--gold); }
.manual-title {
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
}
.manual-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 12px;
}
.btn-add-row {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  flex: none;
  width: 100%;
  background: transparent;
  color: var(--gold);
  border: 1.5px dashed var(--gold);
  border-radius: 12px;
  padding: 10px;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s ease, transform .12s ease;
}
.btn-add-row svg { width: 18px; height: 18px; }
.btn-add-row:active { transform: scale(0.98); }
.btn-add-row:hover { background: rgba(201,162,39,0.08); }

/* 结果展示 */
.result-section {
  background: var(--card);
  border-radius: 18px;
  padding: 16px;
  box-shadow: var(--shadow);
  margin-bottom: 14px;
}
.result-title {
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 10px;
  color: var(--text);
}
.empty-state {
  text-align: center;
  padding: 40px 20px;
  color: var(--text-secondary);
}
.empty-state svg {
  width: 56px;
  height: 56px;
  margin-bottom: 14px;
  color: var(--text-tertiary);
}

/* 列表 */
.record-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.record-item {
  background: var(--card);
  border-radius: 14px;
  padding: 14px;
  box-shadow: var(--shadow);
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
}
.record-main {
  flex: 1;
  min-width: 0;
}
.record-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 3px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.record-badge {
  font-size: 10px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 999px;
  flex-shrink: 0;
}
.badge-cost {
  color: var(--gold);
  background: var(--gold-soft);
}
.badge-flow {
  color: var(--blue, #3b82f6);
  background: rgba(59, 130, 246, .12);
}
.record-sub {
  font-size: 13px;
  color: var(--text);
  margin-bottom: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.record-meta {
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.4;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.record-remark {
  font-size: 12px;
  color: var(--text-tertiary);
  line-height: 1.4;
  margin-top: 3px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.record-amount {
  font-size: 16px;
  font-weight: 700;
  color: var(--gold);
  white-space: nowrap;
}

/* 收支徽章 & 收入金额（中国习惯：收入红色） */
.dir-badge {
  font-size: 10px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 999px;
  flex-shrink: 0;
  line-height: 1.4;
}
.dir-in {
  color: #C43B3B;
  background: rgba(196, 59, 59, .12);
}
.dir-out {
  color: #2E8B57;
  background: rgba(46, 139, 87, .12);
}
.amount-in {
  color: #C43B3B !important;
}

/* 修改台账：记录右侧操作区 */
.record-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.record-side {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: space-between;
  gap: 8px;
  flex-shrink: 0;
}
.record-actions {
  display: flex;
  gap: 6px;
}
.btn-edit {
  background: var(--blue, #3b82f6);
  color: #fff;
}
.btn-danger {
  background: rgba(196, 59, 59, .12);
  color: #C43B3B;
}
.btn-danger.solid {
  background: #C43B3B;
  color: #fff;
}

/* 编辑 / 删除弹窗 */
.modal-mask {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, .45);
  z-index: 100;
  display: flex;
  /* 🔴 刻意不用 align-items:center 做垂直居中：flex 居中一旦内容比视口高，
     溢出的那截会被推到视口**上方**，而那截既滚不到也点不到 ——
     天阁 2026-09-23「叉号被顶到最上面点不了了」正是这个成因（不是没渲染，是够不着）。
     改用卡片 margin:auto 居中（规范里对溢出友好的写法）。 */
  justify-content: center;
  padding: 20px;
  overflow-y: auto;        /* 卡片万一还是比视口高，遮罩自己也能滚，顶部内容不丢 */
  animation: fadeIn .18s ease;
}
.modal-card {
  margin: auto;            /* 配合遮罩的 justify-content 完成居中，见上方注释 */
  display: flex;           /* 🔴 竖向三段：头部 / 内容 / 底部 */
  flex-direction: column;
  background: var(--card);
  border-radius: 18px;
  width: 100%;
  max-width: 440px;
  max-height: 86vh;
  max-height: 86dvh;       /* 🔴 手机上 vh 把地址栏也算进去，dvh 才是真实可视高 ——
                              没有这行，卡片会被地址栏顶出屏幕，叉号就够不着了 */
  overflow-y: auto;        /* 兜底：个别弹窗没有 .modal-body，那就整块滚（有 body 时用不到） */
  padding: 18px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, .25);
  animation: slideUp .2s ease;
}
.modal-card-sm {
  max-width: 360px;
}
.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
  flex: 0 0 auto;          /* 🔴 头部不收缩：滚的只有下面那块，叉号永远钉在原位 */
}
.modal-head h3 {
  font-size: 17px;
  color: var(--text);
}
.modal-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 10px;
  flex: 1 1 auto;          /* 🔴 内容区吃掉剩余高度 */
  min-height: 0;           /* 🔴 flex 子项默认 min-height:auto，不写这行它不肯收缩，也就滚不起来 */
  overflow-y: auto;        /* 🔴 滚动发生在这里 —— 天阁要的「内部滚动」 */
  overscroll-behavior: contain;   /* 手机上滚到底别再带着背景页面一起动 */
}
.modal-body > * {
  flex-shrink: 0;          /* 🔴 内容项不许被压扁；溢出交给滚动条，不是把行挤在一起 */
}
.modal-foot {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  margin-top: 16px;
  flex: 0 0 auto;          /* 🔴 底部按钮同理，固定不动 */
}
.modal-tip {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.6;
  margin: 0;
}

/* ===== 系统信息弹窗（设置页 → 查看运行状态 / 备份明细）=====
   两屏共用这一个样式块：信息屏是「标签 — 值」，体检三项收在一个浅色块里。 */
.sysinfo-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  font-size: 14px;
  line-height: 1.5;
}
.sysinfo-key { color: var(--text-secondary); flex-shrink: 0; }
.sysinfo-val { color: var(--text); text-align: right; word-break: break-word; }
.sysinfo-section { font-size: 13px; color: var(--text-secondary); margin-top: 2px; }
.sysinfo-sub {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 11px 12px;
  border-radius: 12px;
  background: rgba(127, 127, 127, .1);
}
.sysinfo-subrow {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  font-size: 13px;
  line-height: 1.5;
}
.sysinfo-bad { color: var(--danger, #c0392b); }
.sysinfo-link {
  background: none;
  border: none;
  padding: 0;
  margin-left: 6px;
  color: var(--gold);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  text-decoration: underline;
}
.sysinfo-export { width: 100%; margin-top: 4px; }
.sysinfo-bk {
  display: flex;
  flex-direction: column;
  gap: 9px;
  /* 这里**不再自己滚动**：上一版给了 max-height+overflow，结果在内容区里面又套了一根滚动条
     （手指在里层滑，外层不动，手机上很难受）。现在 .modal-body 是唯一滚动区，这里摊开铺着。 */
}
.sysinfo-bk-item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  font-size: 13px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}
.sysinfo-bk-ts { color: var(--text); }
.sysinfo-bk-meta { display: flex; align-items: baseline; gap: 8px; flex-shrink: 0; }
.sysinfo-bk-size { color: var(--text-secondary); }
.sysinfo-tag { color: var(--gold); font-weight: 600; }
.profit-export-opt {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: var(--text-primary);
  cursor: pointer;
  user-select: none;
}
.profit-export-opt input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: #C9A227;
  cursor: pointer;
}
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes slideUp {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: translateY(0); }
}
/* 报价表保存冲突弹窗 */
.qc-count { font-size: 13px; color: var(--text-secondary); margin: 0; line-height: 1.5; }
.qc-row {
  border: 1px solid var(--border);
  border-left: 3px solid var(--gold);
  border-radius: 12px;
  padding: 10px 12px;
  background: var(--bg);
}
.qc-row-title { font-size: 13px; font-weight: 600; color: var(--text); margin-bottom: 4px; }
.qc-diff { padding: 5px 0; border-top: 1px dashed var(--border); font-size: 13px; }
.qc-diff:first-child { border-top: none; }
.qc-field { color: var(--text-secondary); margin-bottom: 2px; }
.qc-vals { display: flex; justify-content: space-between; gap: 12px; }
.qc-mine { color: var(--gold); font-weight: 600; font-variant-numeric: tabular-nums; }
.qc-their { color: var(--text); font-variant-numeric: tabular-nums; }

/* ===== 重复录入提示弹窗（2026-10-02） =====
   同一笔被录两次时，把「撞上的那一条」和新录入的并排摆出来，让用户自己判断。
   三个选项默认选「两条都录入」——那是最不动历史数据的一档。 */
.dup-sub { font-size: 13px; color: var(--text-secondary); line-height: 1.6; margin: 0; }
.dup-apply-all {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 12px; color: var(--text-secondary);
  background: var(--gold-soft); border-radius: 10px; padding: 8px 10px;
}
.dup-apply-btn {
  font-size: 12px; padding: 3px 10px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--card); color: var(--text);
  cursor: pointer; font-family: inherit;
}
.dup-item { border: 1px solid var(--border); border-radius: 12px; padding: 10px 12px; }
.dup-item + .dup-item { margin-top: 10px; }
.dup-item-title { font-size: 13px; font-weight: 600; color: var(--text); margin-bottom: 8px; }
.dup-cmp { background: var(--card-hover); border-radius: 10px; padding: 8px 10px; }
.dup-cmp + .dup-cmp { margin-top: 6px; }
.dup-cmp.is-old { border-left: 3px solid var(--gold); }
.dup-cmp-label { font-size: 11px; color: var(--text-tertiary); margin-bottom: 3px; }
.dup-cmp-text { font-size: 13px; color: var(--text); line-height: 1.6; word-break: break-all; }
.dup-amt { color: var(--gold); font-weight: 600; font-variant-numeric: tabular-nums; }
.dup-ask { font-size: 12px; color: var(--text-secondary); margin: 10px 0 6px; }
.dup-opts { display: flex; flex-direction: column; gap: 6px; }
.dup-opt {
  display: flex; gap: 9px; align-items: flex-start;
  border: 1px solid var(--border); border-radius: 10px;
  padding: 8px 10px; cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.dup-opt.sel { border-color: var(--gold); background: var(--gold-soft); }
.dup-opt.off { opacity: .45; cursor: not-allowed; }
.dup-radio {
  width: 15px; height: 15px; border-radius: 50%;
  border: 1.5px solid var(--text-tertiary);
  flex: 0 0 auto; margin-top: 2px; position: relative;
}
.dup-opt.sel .dup-radio { border-color: var(--gold); }
.dup-opt.sel .dup-radio::after {
  content: ''; position: absolute; inset: 3px; border-radius: 50%; background: var(--gold);
}
.dup-opt-body { min-width: 0; }
.dup-opt-title { font-size: 13px; font-weight: 600; color: var(--text); }
.dup-opt-hint { font-size: 12px; color: var(--text-secondary); line-height: 1.5; margin-top: 1px; }

/* 应收提醒弹窗 */
.pay-reminder-card { max-width: 460px; }
.pay-reminder-tip {
  font-size: 13px;
  color: var(--text-secondary);
  margin: 0 0 10px;
  line-height: 1.5;
}
.pay-reminder-head {
  display: flex;
  align-items: center;
  padding: 6px 10px;
  font-size: 12px;
  color: var(--text-secondary);
  border-bottom: 1px solid var(--border);
}
.pay-reminder-head span { flex: 1; text-align: left; }
.pay-reminder-head span:nth-child(2) { text-align: center; }
.pay-reminder-head span:nth-child(3) { text-align: right; }
.pay-reminder-body {
  /* 这个元素同时挂着 .modal-body，滚动区已经由 .modal-body 统一提供；
     这里再限一层 max-height 会让它的内容区比别的弹窗矮一截（同样的问题、同样的视觉）。
     只留下给滚动条让位的右侧内边距。 */
  padding-right: 4px;
}
.pay-reminder-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
}
.pay-reminder-row:last-child { border-bottom: none; }
.pay-r-project {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
}
.pay-r-date {
  flex: 1;
  text-align: center;
  color: var(--gold);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.pay-r-amt {
  flex: 1;
  text-align: right;
  color: var(--text);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* 所属工程批量设置条 */
.batch-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--bg);
  border: 1px dashed var(--border);
  border-radius: 12px;
  padding: 8px 10px;
  margin: 10px 0;
  flex-wrap: wrap;
}
.batch-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}
.batch-bar input {
  flex: 1;
  min-width: 110px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 7px 10px;
  font-size: 14px;
  color: var(--text);
  outline: none;
}
.batch-bar input:focus {
  border-color: var(--gold);
}
/* 批量栏「清空本列」：危险动作，红色胶囊与金色覆盖按钮区分 */
.btn-clear-col {
  border: 1px solid rgba(226,75,74,0.7);
  color: #C83C3C;
  border-radius: 999px;
}
.btn-clear-col:hover { background: rgba(226,75,74,0.08); }
body[data-theme="dark"] .btn-clear-col { color: #E08A85; }
.btn-sm {
  padding: 7px 14px;
  font-size: 13px;
  white-space: nowrap;
}
/* 预览确认表里的「＋ 添加一行」：沿用全站「添加一行」的金虚线风格（.btn-add-row），
   但它是按钮行里的一员 —— 只占自身宽度，不能把「确认写入」挤走。
   ⚠️ 绝不要另写一条 `.btn-add-row { ... }`：那个类是工程款/工时/手动录入三处共用的
      （整行宽 + 金虚线），同名规则会连带改掉它们 —— 这里只用修饰类收窄自己。 */
.btn-add-row.compact {
  width: auto;
  flex: 0 0 auto;
}
/* 批量设置条「选择已有」下拉：金色胶囊，与首页工程筛选同风格 */
.batch-select {
  appearance: none;
  -webkit-appearance: none;
  background: var(--card);
  border: 1px solid var(--gold);
  border-radius: 999px;
  padding: 6px 24px 6px 12px;
  font-size: 12px;
  font-weight: 600;
  color: var(--gold);
  cursor: pointer;
  outline: none;
  max-width: 110px;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex-shrink: 0;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%23C9A227' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><polyline points='3 5 6 8 9 5'/></svg>");
  background-repeat: no-repeat;
  background-position: right 7px center;
  background-size: 10px;
  transition: border-color .2s;
}
.batch-select:hover { border-color: var(--gold); }
.batch-select:focus { border-color: var(--gold); }
.batch-select option {
  color: var(--text);
  background: var(--bg);
  font-weight: 500;
}

/* 表格 */
.data-table-wrap {
  overflow-x: auto;
  border-radius: 12px;
  background: var(--bg);
}
/* 报价分析表：固定高度，支持横向 + 纵向滚动（配合鼠标拖拽平移） */
.quote-table-wrap {
  max-height: 62vh;
  overflow: auto;
  cursor: grab;
}
.quote-table-wrap.panning { cursor: grabbing; user-select: none; }
.quote-table-wrap ::selection { background: transparent; }

/* 记账录入/识别预览表格：鼠标左键拖拽平移 */
.pan-table-wrap { cursor: grab; }
.pan-table-wrap.panning { cursor: grabbing; user-select: none; }
.pan-table-wrap.panning ::selection { background: transparent; }
.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  min-width: 560px;
}
.data-table th,
.data-table td {
  padding: 10px 12px;
  text-align: left;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
/* 日期格下方的「→ 2026-09-23」（2026-10-03）：
   客户写 0923 / 9月23日 时，让他在预览里一眼看到系统认成了哪天 —— 不替他改写法。 */
.date-norm-hint {
  display: block;
  margin-top: 2px;
  font-size: 11px;
  line-height: 1.3;
  white-space: nowrap;
  color: var(--text-secondary);
}
.data-table th {
  color: var(--text-secondary);
  font-weight: 600;
  background: var(--bg);
  position: sticky;
  top: 0;
}
.data-table td { color: var(--text); }

/* 图表 */
.chart-box {
  width: 100%;
  height: 260px;
  background: var(--card);
  border-radius: 16px;
  margin-bottom: 14px;
}

/* 拍照记账 */
.upload-area {
  background: var(--card);
  border: 2px dashed var(--gold);
  border-radius: 20px;
  padding: 40px 20px;
  text-align: center;
  color: var(--gold);
  cursor: pointer;
  transition: background .2s ease;
  margin-bottom: 14px;
}
.upload-area:active { background: var(--gold-soft); }
.upload-area svg {
  width: 48px;
  height: 48px;
  margin-bottom: 12px;
}
.upload-area p {
  font-size: 14px;
  color: var(--text-secondary);
}
.upload-area input { display: none; }

/* ===== 录入入口（拍照 / 选图 / Excel） ===== */
.entry-row {
  display: grid;
  /* 2026-10-02：加了第三张卡「人工成本录入」→ 两列改三列。
     模块没开通时 capture.js 会给整行加 .two-col 退回两列（否则留一个空洞）。 */
  grid-template-columns: 1fr 1fr 1fr;
  gap: 10px;
  margin-bottom: 14px;
}
.entry-row.two-col { grid-template-columns: 1fr 1fr; }
.entry-btn {
  background: var(--card);
  border: none;
  border-radius: 18px;
  padding: 18px 8px 14px;   /* 三列后每张只剩 1/3 宽，内距收紧一点才不挤 */
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  cursor: pointer;
  color: var(--gold);
  transition: transform .12s ease, background .2s ease, opacity .25s ease;
}
.entry-btn:active { transform: scale(0.96); }
/* 处理中置灰（2026-10-03）：识别期间「拍照 / 相册」两张卡按住不动，
   让人看得见"它真的在忙"，而不是只等一个会自己消失的气泡。
   ⚠️ 判据是透明度，不是颜色 —— 深浅主题下都成立。 */
.entry-btn:disabled,
.entry-btn.is-busy {
  opacity: .5;
  cursor: progress;
  pointer-events: none;
}
.entry-btn:disabled:active,
.entry-btn.is-busy:active { transform: none; }
/* Excel 导入区同一套：忙时一起变淡（拖进去会被排队，但先让人看出"这会儿在忙"） */
.excel-zone.is-busy { opacity: .5; cursor: progress; }
.entry-btn svg { width: 28px; height: 28px; }
.entry-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}
.entry-desc {
  font-size: 11px;
  color: var(--text-secondary);
  line-height: 1.3;
  text-align: center;
}
.entry-btn.primary {
  background: linear-gradient(135deg, var(--gold) 0%, var(--gold-dark) 100%);
  color: #fff;
}
.entry-btn.primary .entry-title { color: #fff; }
.entry-btn.primary .entry-desc { color: rgba(255,255,255,0.85); }

/* Excel 拖拽区 */
.excel-zone {
  padding: 26px 20px;
  /* 透明度必须进过渡列表：置灰是"状态切换"，不写过渡就是一帧之内 1→0.5，
     整块区域（约占首屏 12%）瞬间变暗 = 肉眼看到的"屏闪"（2026-10-03 实测 26ms 内跳变）。 */
  transition: opacity .25s ease;
}
.excel-zone svg { width: 36px; height: 36px; margin-bottom: 8px; }
.excel-zone.drag {
  background: var(--gold-soft);
  border-color: var(--gold-dark);
  transform: scale(1.01);
}

/* ===== 低置信度字段高亮（智能确认） ===== */
.form-group.uncertain-group { position: relative; }
.uncertain-badge {
  display: inline-block;
  font-size: 11px;
  color: #fff;
  background: var(--gold);
  border-radius: 999px;
  padding: 2px 10px;
  margin-left: 8px;
  font-weight: 500;
  vertical-align: 1px;
}
input.uncertain,
.form-group.uncertain-group input {
  border: 1.5px dashed var(--gold);
  background: var(--gold-soft);
}

/* ===== 可编辑预览表格 ===== */
.data-table.editable { min-width: 920px; }
.data-table.editable th,
.data-table.editable td { white-space: nowrap; padding: 6px 6px; }
.data-table.editable.manual-table { min-width: 1160px; }
.data-table.editable.manual-table th:nth-child(4),
.data-table.editable.manual-table td:nth-child(4) { min-width: 200px; }
.data-table .cell-in {
  width: 110px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text);
  border-radius: 8px;
  padding: 7px 8px;
  font-size: 13px;
  font-family: inherit;
  outline: none;
}
.data-table .cell-in:focus { border-color: var(--gold); }
.data-table .cell-in.num { width: 84px; }
.data-table .uncertain-cell .cell-in,
.data-table .cell-in.uncertain {
  border: 1.5px dashed var(--gold);
  background: var(--gold-soft);
}
/* 行删除叉号：与内容拉开距离（左间距 + 虚线分隔），圆形底更醒目防误触 */
.row-del-cell {
  padding-left: 22px !important;
  padding-right: 10px !important;
  border-left: 1px dashed var(--border);
}
.row-del {
  border: none;
  background: rgba(226,75,74,0.12);
  color: #E24B4A;
  font-size: 17px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: background .15s ease, transform .12s ease;
}
.row-del:hover { background: rgba(226,75,74,0.22); }
.row-del:active { transform: scale(0.9); }
body[data-theme="dark"] .row-del { background: rgba(226,75,74,0.22); color: #F0807F; }
body[data-theme="dark"] .row-del:hover { background: rgba(226,75,74,0.34); }

/* ===== 表头字段映射确认 ===== */
.map-table { min-width: 560px; }
.map-table td { padding: 6px 8px; }
.map-table .cell-in { width: 200px; }
.map-sel.map-guessed {
  border: 1.5px dashed var(--gold);
  background: var(--gold-soft);
}
.map-status { font-size: 12px; white-space: nowrap; }
.map-guess-badge {
  display: inline-block;
  font-size: 11px;
  color: #fff;
  background: var(--gold);
  border-radius: 999px;
  padding: 2px 10px;
  font-weight: 500;
}
.map-ok-badge {
  display: inline-block;
  font-size: 11px;
  color: #2E9E6B;
  background: rgba(46,158,107,0.12);
  border-radius: 999px;
  padding: 2px 10px;
  font-weight: 500;
}
.map-missing-tip { color: var(--text-secondary); margin-top: 6px; }
.missing-chip {
  display: inline-block;
  font-size: 11px;
  color: var(--gold-dark);
  background: var(--gold-soft);
  border: 1px dashed var(--gold);
  border-radius: 6px;
  padding: 1px 8px;
  margin: 0 3px;
}

/* ===== 缺列留空提示（可自行补充） ===== */
.col-missing {
  display: inline-block;
  font-size: 10px;
  color: var(--gold-dark);
  background: var(--gold-soft);
  border-radius: 999px;
  padding: 1px 8px;
  margin-left: 4px;
  font-weight: 500;
  vertical-align: 1px;
}
.data-table .cell-in.cell-missing {
  border-style: dashed;
  border-color: var(--gold);
  background: var(--gold-soft);
  opacity: 0.85;
}
.data-table .cell-in.cell-missing::placeholder { color: var(--gold-dark); opacity: 0.75; }

.table-hint {
  font-size: 12px;
  color: var(--text-tertiary);
  line-height: 1.5;
  margin-bottom: 10px;
}

/* ===== 数据看板筛选栏（Excel 式） ===== */
.filter-bar {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  padding: 14px 12px;
  -webkit-overflow-scrolling: touch;
}
.filter-item {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 96px;
  flex-shrink: 0;
}
.filter-item label {
  font-size: 11px;
  color: var(--text-secondary);
  font-weight: 500;
}
.filter-item select {
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  border-radius: 10px;
  padding: 8px 10px;
  font-size: 13px;
  font-family: inherit;
  outline: none;
  cursor: pointer;
}
.filter-item select:focus { border-color: var(--gold); }

.chart-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--text-tertiary);
  font-size: 13px;
}

.preview-image {
  width: 100%;
  max-height: 52vh;          /* 手机竖拍大图会顶掉整屏，限高后仍能上下看全 */
  object-fit: contain;
  border-radius: 14px;
  margin-bottom: 14px;
  box-shadow: var(--shadow);
}

/* Toast */
.toast {
  position: fixed;
  left: 50%;
  bottom: 90px;
  transform: translateX(-50%) translateY(20px);
  background: rgba(30,35,48,0.92);
  color: #fff;
  padding: 10px 18px;
  border-radius: 999px;
  font-size: 14px;
  opacity: 0;
  visibility: hidden;
  transition: all .25s ease;
  z-index: 100;
  /* 🔴 2026-10-03：原来是 white-space:nowrap —— 长文案在 390px 手机上
     **两头被切**（实测 HEIC 提示宽 831px、超大照片 395px），用户看到的
     是半句话。改成可折行 + 左右留边。
     ⚠️ 必须同时给 `width: max-content`：本元素是 `left:50%` 的 fixed 元素，
        做 shrink-to-fit 时"可用宽度"只剩 390−195＝195px，光加 max-width
        会被压成一根 195px 宽的窄柱（实测高 419px，比原来更糟）。
        写死 width:max-content 再让 max-width 封顶、translateX(-50%) 居中，
        才是真正的"一行胶囊/多行气泡"。 */
  width: max-content;
  max-width: min(560px, calc(100vw - 32px));
  white-space: normal;
  overflow-wrap: anywhere;
  line-height: 1.5;
  text-align: center;
}
.toast.show { opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); }

/* ===== 可选栏目切换（金色胶囊 chips） ===== */
.col-chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 14px; }
.col-chip {
  border: 1px solid var(--gold);
  background: var(--gold-soft);
  color: var(--gold);
  border-radius: 999px;
  padding: 5px 14px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: all .2s ease;
  font-family: inherit;
  outline: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.col-chip:active { transform: scale(0.94); }
.col-chip:not(.active) {
  border-color: var(--border);
  background: var(--bg);
  color: var(--text-tertiary);
}
.col-chip-add {
  min-width: 30px;
  padding: 5px 12px;
  background: linear-gradient(135deg, var(--gold) 0%, var(--gold-dark) 100%);
  color: #fff;
  border-color: transparent;
}
.col-chip-add:not(.active) {
  background: linear-gradient(135deg, var(--gold) 0%, var(--gold-dark) 100%);
  color: #fff;
  border-color: transparent;
  opacity: 0.85;
}

/* ===== 对比分析 ===== */
/* 查询页行尾「保存」小按钮 */
.btn-save-compare {
  border: 1px solid var(--gold);
  background: var(--gold-soft);
  color: var(--gold);
  border-radius: 999px;
  padding: 4px 14px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: all .2s ease;
  font-family: inherit;
  outline: none;
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}
.btn-save-compare:active { transform: scale(0.94); }
.btn-save-compare.saved {
  border-color: var(--border);
  background: var(--bg);
  color: var(--text-tertiary);
  cursor: default;
  opacity: 0.7;
}
.op-th { white-space: nowrap; }
.op-cell { white-space: nowrap; }

/* 对比分析页 */
.compare-card { padding: 16px 18px; }
.compare-hint {
  font-size: 13px;
  color: var(--text-secondary);
  margin-bottom: 12px;
}
.compare-chip-row { display: flex; flex-wrap: wrap; gap: 8px; }
.compare-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--gold);
  background: var(--gold-soft);
  color: var(--gold);
  border-radius: 999px;
  padding: 5px 6px 5px 14px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: all .2s ease;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.compare-chip:active { transform: scale(0.95); }
.compare-chip:not(.active) {
  border-color: var(--border);
  background: var(--bg);
  color: var(--text-tertiary);
}
.compare-chip-name { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.compare-chip-x {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border: none;
  border-radius: 50%;
  background: rgba(0,0,0,0.08);
  color: inherit;
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
  font-family: inherit;
}
.compare-chip-x:hover { background: rgba(201,162,39,0.25); }
body[data-theme="dark"] .compare-chip-x { background: rgba(255,255,255,0.12); }

.compare-no-dim {
  font-size: 13px;
  color: var(--text-tertiary);
  padding: 10px 2px;
}
.compare-chart { height: 340px; }
@media (max-width: 768px) {
  .compare-chart { height: 280px; }
  .compare-chip-name { max-width: 140px; }
}

/* ===== 误删找回（回收站） ===== */
.trash-src-badge {
  display: inline-block;
  font-size: 11px;
  color: var(--gold-dark);
  background: var(--gold-soft);
  border: 1px dashed var(--gold);
  border-radius: 6px;
  padding: 1px 8px;
  font-weight: 500;
}
.trash-meta {
  font-size: 12px;
  color: var(--text-tertiary);
  margin-top: 3px;
}
.trash-item .record-actions { justify-content: flex-end; }

/* ===== 工程名单 ===== */
.project-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  text-align: left;
  font-family: inherit;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 14px 16px;
  box-shadow: var(--shadow);
  cursor: pointer;
  transition: border-color .2s, transform .15s;
}
.project-card:active { transform: scale(.985); }
.project-card:hover { border-color: var(--gold); }
.project-card-main { flex: 1; min-width: 0; }
/* 卡片从 <button> 改成 <div>（2026-10-04）：卡里要放「⋯」按钮 ——
   button 里套 button 是非法 HTML，浏览器会把内层拆出去，那样「⋯」根本点不到。
   补上 button 有、div 没有的两点：文字不被框选、点击不闪蓝框。 */
.project-card { user-select: none; -webkit-tap-highlight-color: transparent; }
.project-card:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
/* 卡片右侧「⋯」：点开工程操作（改名 / 删除到回收站） */
.pc-more {
  flex: none;
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: transparent;
  color: var(--text-secondary);
  font-size: 17px;
  line-height: 1;
  padding: 0;
  cursor: pointer;
  transition: border-color .2s, color .2s;
}
.pc-more:hover, .pc-more:focus-visible { border-color: var(--gold); color: var(--gold); }
/* ===== 「未填写工程」这个筐 ≠ 真工程（2026-10-04 天阁：长得一样会误导）=====
   它只是「没填工程名的散记录」临时归的一堆。用**虚线框 + 淡底 + 灰调 + 「待归类」小标**
   把它和真工程区分开；金额也调淡（它不是一个工程的业绩）。
   ⚠️ 虚线框和 :hover 的特异性一样（都是 0,2,0），靠源码顺序压过去 ——
      所以必须显式补一条 :hover，否则这个卡片点上去一点反馈都没有。 */
.project-card.is-virtual {
  border: 1.5px dashed var(--text-tertiary);
  background: var(--card-hover);
  box-shadow: none;
}
.project-card.is-virtual:hover { border-color: var(--gold); }
/* 🔴 名字**不调灰**（2026-10-04 实测）：把标题改成 --text-secondary 后，
   与卡片底的对比度只有 3.5:1，低于正文可读性下限 4.5:1 ——
   名字是给人读的，为了「弱化」把它调灰是拿可读性换视觉效果，不划算。
   区分「这不是工程」靠的是虚线框 + 「待归类」小标 + 副文案，已经够了。 */
.project-card.is-virtual .pc-out { color: var(--text-secondary); font-weight: 500; }
.pc-badge {
  display: inline-block;
  flex: none;
  padding: 1px 8px 2px;
  border: 1px solid var(--text-tertiary);
  border-radius: 999px;
  font-size: 11px;
  font-weight: 500;
  line-height: 1.35;
  color: var(--text);
  white-space: nowrap;
}
/* 名字 + 徽标 一行。🔴 徽标**不能塞进 .project-card-name 里面** ——
   那个元素的文字必须**就是工程名本身**（名字原样显示是全站约定）。
   所以这里多一层 flex 行，让徽标当兄弟；名字给 min-width:0 才能继续省略号截断。 */
.project-card-name-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
.project-card-name-row .project-card-name { min-width: 0; }
/* 详情页里这个筐的说明条：先把「这里不是工程」讲清楚，再给「批量填工程名」按钮 */
.proj-virtual-note {
  margin: 0 4px 10px;
  padding: 12px 14px;
  border: 1.5px dashed var(--text-tertiary);
  border-radius: 12px;
  background: var(--card-hover);
}
.pvn-title { font-size: 14px; font-weight: 600; color: var(--text); margin-bottom: 4px; }
.pvn-text { font-size: 12.5px; line-height: 1.65; color: var(--text-secondary); }
/* 工程详情页顶部的操作行：改名 / 删除到回收站 */
.proj-actions { display: flex; gap: 8px; margin: 0 4px 10px; }
.proj-actions .btn { flex: 1; }
.proj-act-danger { color: #D93025; border-color: rgba(217, 48, 37, .35); }
.proj-act-danger:hover { border-color: #D93025; }
/* 工程操作弹窗里的两个按钮（竖排、占满宽） */
.proj-act-body { display: flex; flex-direction: column; gap: 10px; }
.proj-act-body .proj-act-btn { width: 100%; }
/* 回收站里的「工程」条目：左侧一道金线 + 金色徽标，与普通记录一眼区分 */
.trash-project { border-left: 3px solid var(--gold); }
.trash-proj-badge { background: var(--gold); color: #fff; }
.project-card-name {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.project-card-meta {
  font-size: 12px;
  color: var(--text-secondary);
  margin-top: 3px;
}
.project-card-amount {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}
.project-card-amount .pc-out {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
}
.project-card-amount .pc-in {
  font-size: 12px;
  font-weight: 500;
  color: var(--gold-dark);
}
.project-card-arrow {
  font-size: 22px;
  line-height: 1;
  color: var(--gold);
}
#project-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 2px 0 10px;
}

/* ===== 版本台账（仅开发者账号 owner 可见，2026-09-25）=====
   公司卡片**直接复用**上面 .project-card 那套 —— 同一个结构
   （名字 + 一行小字 + 右侧 + 箭头），所以这里一行卡片样式都不用重写；
   服务清单复用「系统信息」的 .sysinfo-sub / .sysinfo-subrow（同为「左标签 + 右值」行）。
   这里只补三样：列表容器、状态小标签、详情页头部卡。
   🔴 颜色一律走主题变量：深色模式下「浅底深字」会糊成一片，
      所以标签用 currentColor 边框 + 半透明底，两种主题都成立。 */
#vledger-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 2px 0 10px;
}
.vl-tag {
  flex-shrink: 0;
  font-size: 11px;
  line-height: 1.6;
  padding: 1px 8px;
  border-radius: 999px;
  border: 1px solid currentColor;
  white-space: nowrap;
}
.vl-tag-self,
.vl-tag-ok { color: var(--gold-dark, #A8851A); background: var(--gold-soft); }
.vl-tag-trial { color: var(--warn, #E65100); background: rgba(230, 81, 0, .10); }
.vl-tag-expired { color: var(--danger, #c0392b); background: rgba(192, 57, 43, .10); }
.vl-tag-readonly,
.vl-tag-provisioning { color: var(--text-secondary); background: rgba(127, 127, 127, .12); }
.vl-head {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 14px 16px;
  box-shadow: var(--shadow);
  margin-bottom: 10px;
}
.vl-head-top { display: flex; align-items: center; gap: 8px; }
.vl-head-name {
  flex: 1;
  min-width: 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vl-head-meta {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-top: 8px;
  font-size: 12px;
  color: var(--text-secondary);
}
.vl-svc-title { font-size: 13px; color: var(--text-secondary); margin: 2px 0 8px; }
/* 详情页有两组清单（功能模块 / 档位服务）：第二组的标题紧跟上一组清单时留出间隔，
   否则两组会粘成一片、看起来像同一组的两截 */
.sysinfo-sub + .vl-svc-title { margin-top: 18px; }
.vl-on { color: var(--gold-dark, #A8851A); }
.vl-off { color: var(--text-tertiary); }

body[data-theme="dark"] .toast { background: rgba(245,246,250,0.92); color: #1e2330; }

/* ===== 手机端适配（≤767px） =====
   真机反馈：统计卡的标题被右上角「全部」下拉压住、金额顶到卡片边缘、宫格描述贴边。
   根因三条：
     ① 下拉 <select> 的宽度由最长的 option（工程名）撑到 max-width 上限，实际只显示
        「全部」两个字，左侧几十像素空白把标题挤掉；
     ② 金额 24px 在窄卡上占满整行，右侧只剩内边距；
     ③ 宫格卡片左右内边距只有 8px，描述文字几乎顶到卡片边缘。
   对策：缩小下拉 → 给标题预留等宽避让位 → 金额与描述字号下调、让出呼吸空间。 */
@media (max-width: 767px) {
  .home-main { padding: 10px 16px calc(24px + env(safe-area-inset-bottom)); gap: 14px; }

  /* 标题给下拉让位：padding-right = 下拉 66 + 右间距 10，视觉上还会多出 16px 间隙
     （卡片自身内边距），标题不会贴住胶囊。必须 nowrap，折行更难看 */
  .stat-label {
    font-size: 12px;
    padding-right: 76px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .stat-filter { top: 10px; right: 10px; }
  .proj-filter {
    max-width: 66px;
    font-size: 11px;
    padding: 3px 16px 3px 8px;
    background-position: right 4px center;
    background-size: 9px;
  }
  .stat-value { font-size: 20px; }
  .stat-meta { font-size: 11px; line-height: 1.4; }

  /* 宫格：把文字可用宽度抢回来（收窄卡片内边距与网格间距），描述收成一行 */
  .grid { gap: 10px; }
  .grid-item { padding: 14px 7px 12px; gap: 7px; }
  .grid-icon { width: 30px; height: 30px; }
  .grid-title { font-size: 13.5px; }
  /* text-wrap: balance —— 万一某条描述还是折了行，也让两行字数均衡，
     不会出现「……回 / 库」这种末字孤零零掉下去的难看断法（老内核忽略该属性） */
  .grid-desc { font-size: 10.5px; line-height: 1.4; min-height: 15px; text-wrap: balance; }
}

/* 极窄屏（<380px）：两张统计卡改上下单列，各占整行。
   双列时「待收工程款」(约 60px) 与下拉 (约 66px) 实在排不下，单列后宽度充裕反而更好读 */
@media (max-width: 379px) {
  .stats-row { grid-template-columns: 1fr; }
  /* 三列时每列只有约 102px，描述再收一点才守得住一行 */
  .grid-item { padding: 14px 6px 12px; }
  .grid-desc { font-size: 10px; }
}

/* ===== PC 适配 ===== */
/* 桌面/平板布局（2026-10-05 加 min-height 限制）
   ⚠️ 原来只判宽度 768px —— 手机横过来（如 844×390）宽度够了、高度却只有 390，
      于是整个掉进这套「给电脑用」的布局：首页宫格 6 列被撑成细长条、
      12 个功能一个都看不全、设置面板要滚 4 屏（实测见 MEMORY 横屏那条）。
      加上 min-height 后，矮而宽的屏幕不再误入，继续走手机布局。 */
@media (min-width: 768px) and (min-height: 521px) {
  #app { max-width: 1080px; }
  .home-main { padding: 16px 32px 44px; gap: 18px; }

  .stats-row { gap: 18px; }
  .stat-card { padding: 22px 24px; gap: 8px; }
  .stat-label { font-size: 14px; }
  .stat-value { font-size: 34px; }
  .stat-meta { font-size: 13px; }
  .proj-filter { font-size: 13px; padding: 5px 24px 5px 12px; max-width: 130px; }
  .stat-filter { top: 16px; right: 16px; }

  .grid { grid-template-columns: repeat(6, 1fr); gap: 16px; }
  .grid-item { padding: 26px 12px 20px; gap: 10px; }
  .grid-icon { width: 44px; height: 44px; }
  .grid-title { font-size: 15px; }
  .grid-desc { font-size: 12px; min-height: 32px; }
  .chart-box { height: 300px; }

  /* 首页补充区：最近记录 + 本月收支 */
  .home-below {
    display: grid;
    grid-template-columns: 1.15fr 1fr;
    gap: 18px;
    margin-top: 4px;
  }
  .trend-bar { width: 8px; }
}

/* 手机横屏（宽而矮）专用（2026-10-05）。
   容器放开到整屏宽，但**不套用**上面那套桌面布局（宫格还是 3 列、不并两栏）。
   价值在录入表：最小宽 1160px，可视宽度从竖屏的 326px 变成约 780px ——
   一张表从「要横着拖 3.3 个屏幕」降到「不到 1 屏」，且打开就能同时看见 4 列。 */
@media (orientation: landscape) and (max-height: 520px) {
  #app { max-width: 100%; }
  /* 横屏高度金贵：底部两个按钮并排，别占两行 */
  .manual-actions { flex-direction: row; }
  .manual-actions .btn { width: auto; flex: 1; }
}

/* ===== 报价分析 ===== */
.quote-upload { margin-bottom: 14px; }
.quote-header {
  background: var(--card); border-radius: 16px; padding: 14px 16px;
  box-shadow: var(--shadow); margin-bottom: 14px;
  display: grid; grid-template-columns: 1fr 1fr; gap: 8px 16px;
}
.quote-header .qh-item { display: flex; flex-direction: column; gap: 2px; }
.quote-header .qh-label { font-size: 11px; color: var(--text-tertiary); }
.quote-header .qh-value { font-size: 14px; color: var(--text); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.quote-summary { background: var(--card); border-radius: 16px; padding: 12px 14px; box-shadow: var(--shadow); margin: 12px 0; }
.quote-summary-title { font-size: 13px; color: var(--text-secondary); margin-bottom: 8px; font-weight: 600; }
.quote-sum-row { display: flex; justify-content: space-between; align-items: center; padding: 6px 0; border-bottom: 1px solid var(--border); font-size: 13px; }
.quote-sum-row:last-child { border-bottom: none; }
/* label 吃掉剩余空间 → 后面的「展开 +」紧贴金额左边，金额仍然右对齐（加了按钮也不跑位） */
.quote-sum-row .qsr-label { flex: 1 1 auto; min-width: 0; color: var(--text); }
.quote-sum-row.labor .qsr-label { color: var(--gold-dark); font-weight: 600; }
.quote-sum-row.material .qsr-label { color: #3b82f6; font-weight: 600; }
.quote-sum-row .qsr-val { color: var(--text); font-variant-numeric: tabular-nums; }
/* 「展开 +」（2026-10-09 客户要的）：点开看这一类的明细。小胶囊，跟全站金色一致；
   配色全部走变量（--gold-soft 在浅色/深色两套主题下都有定义），不硬编码色值。 */
.qsr-expand {
  flex: none; display: inline-flex; align-items: center; gap: 3px; margin: 0 8px;
  padding: 2px 9px; border-radius: 999px; border: 1px solid var(--gold-light);
  background: var(--gold-soft); color: var(--gold);
  font-size: 12px; line-height: 1.5; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.qsr-expand:active { background: var(--gold-light); }
.qsr-expand .qsr-plus { font-size: 13px; line-height: 1; }
.quote-charts { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin: 14px 0; }
.quote-ca-hint {
  background: var(--card); border: 1px dashed var(--border); border-radius: 16px;
  padding: 22px 16px; margin: 12px 0; text-align: center; font-size: 13px;
  color: var(--text-tertiary); line-height: 1.6;
}
.quote-chart { width: 100%; height: 240px; background: var(--card); border-radius: 16px; box-shadow: var(--shadow); }
.quote-chart-title { text-align: center; font-size: 13px; color: var(--text-secondary); font-weight: 600; padding: 8px 0 4px; }
.quote-advice {
  background: var(--gold-soft); border: 1px solid var(--gold); border-radius: 16px;
  padding: 14px 16px; margin: 14px 0; font-size: 13px; line-height: 1.7; color: var(--text);
}
.quote-advice .qa-head { font-weight: 700; color: var(--gold); margin-bottom: 6px; }
.quote-cat-sel {
  appearance: none; -webkit-appearance: none;
  background: var(--card); border: 1px solid var(--gold); border-radius: 999px;
  padding: 5px 22px 5px 10px; font-size: 12px; font-weight: 600; color: var(--gold);
  cursor: pointer; outline: none; max-width: 120px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%23C9A227' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><polyline points='3 5 6 8 9 5'/></svg>");
  background-repeat: no-repeat; background-position: right 6px center; background-size: 10px;
}
.quote-cat-sel:focus { border-color: var(--gold-dark); }
.quote-cat-sel option { color: var(--text); background: var(--bg); }
.quote-summary-cell { color: var(--text-tertiary); font-size: 14px; }
/* 报价行类型标记：普通 / 增项 / 后加 */
.qtag-cell { width: 66px; text-align: center; background: var(--bg); }
.qtag-sel { font-size: 12px; padding: 2px 4px; border: 1px solid var(--border); border-radius: 8px; background: var(--card); color: var(--text); max-width: 66px; }
.quote-row-extra td { background: rgba(46, 204, 113, 0.10); }
.quote-row-extra .qtag-cell { background: rgba(46, 204, 113, 0.20); }
.quote-row-added td { background: rgba(201, 162, 39, 0.10); }
.quote-row-added .qtag-cell { background: rgba(201, 162, 39, 0.20); }
.quote-summary-row td { font-weight: 600; background: var(--bg); }
.quote-grand-row td { background: rgba(201, 162, 39, 0.14); color: var(--gold, #C9A227); }
.quote-grand-row .quote-summary-cell { color: var(--gold, #C9A227); font-weight: 700; }
.quote-extra-sum { background: rgba(46, 204, 113, 0.14); }
.quote-extra-sum .qes-label { font-weight: 600; color: #1e8e4f; }
.quote-extra-sum .qes-amt { font-weight: 700; color: #1e8e4f; font-variant-numeric: tabular-nums; text-align: right; padding-right: 10px; }
.quote-sum-row.extra .qsr-label { color: #1e8e4f; font-weight: 600; }
.quote-sum-row.extra .qsr-val { color: #1e8e4f; font-weight: 600; }
.quote-sum-row.total { margin-top: 4px; padding-top: 10px; border-top: 2px solid var(--gold-light); border-bottom: none; font-weight: 700; font-size: 14px; }
.quote-sum-row.total .qsr-label { color: var(--gold-dark); }
.quote-sum-row.total .qsr-val { color: var(--gold); font-size: 15px; }

/* ===== 成本品类的「归类」下拉 + 「待确认」（2026-10-04）=====
   客户在录入预览页 / 修改台账页就地改某个品类的归类；改一次即写进记忆表，
   全公司所有同品类的记录都按新分类算 —— 所以领班看到的这个框是置灰的。
   「待确认」= 这个品类既不像买料也不像付人工，系统不硬塞进任何一个桶。 */
.cat-picker {
  display: block; width: 100%; max-width: 150px; margin-top: 4px;
  padding: 3px 6px; font-size: 11px; line-height: 1.6;
  color: var(--text-secondary); background: var(--bg);
  border: 1px solid var(--border); border-radius: 8px; outline: none;
  transition: border-color .2s ease, box-shadow .2s ease;
}
.cat-picker:not(:disabled):hover { border-color: var(--gold); }
.cat-picker:focus { border-color: var(--gold); box-shadow: 0 0 0 2px rgba(201, 162, 39, .18); }
.cat-picker:disabled { opacity: .6; cursor: not-allowed; }
.quote-sum-row.pending .qsr-label { color: #d97706; font-weight: 600; }
.quote-sum-row.pending .qsr-val { color: #d97706; font-weight: 600; }
.cat-pending-tip { font-size: 11.5px; line-height: 1.6; color: var(--text-tertiary); padding: 2px 0 8px; }
.cat-hint { display: inline-block; margin-top: 4px; color: var(--text-tertiary); }
.profit-table tr.p-pending td { color: #d97706; }
.p-pending-tip {
  background: rgba(217, 119, 6, .08); border-left: 3px solid #d97706;
  border-radius: 8px; padding: 8px 10px; margin: 10px 4px;
}
.quote-export-bar { display: flex; gap: 10px; margin-top: 14px; }
.quote-export-opt {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 8px; text-align: center;
  border: 1px solid var(--gold); background: var(--gold-soft); color: var(--gold);
  border-radius: 12px; padding: 12px 14px; font-size: 13px; font-weight: 600; cursor: pointer;
  transition: all .2s ease; user-select: none;
}
.quote-export-opt.off { border-color: var(--border); background: var(--bg); color: var(--text-tertiary); }

/* 参考报价弹窗：工程分组 + 报价表卡片 */
.quote-ref-group { margin-bottom: 12px; }
.quote-ref-proj {
  font-size: 12px; font-weight: 600; color: var(--gold);
  background: var(--gold-soft); border: 1px dashed var(--gold);
  border-radius: 999px; padding: 3px 10px; display: inline-block; margin-bottom: 8px;
}
.quote-ref-list { display: flex; flex-direction: column; gap: 8px; }
.quote-ref-item {
  background: var(--card); border: 1px solid var(--border); border-radius: 12px;
  padding: 12px 14px; cursor: pointer; transition: all .2s ease;
}
.quote-ref-item:hover { border-color: var(--gold); background: var(--gold-soft); }
.qri-name { font-size: 14px; font-weight: 600; color: var(--text); }
.qri-meta { font-size: 11px; color: var(--text-tertiary); margin-top: 3px; }

/* 报价分析表格：可编辑单元格 */
.data-table .quote-cell-in {
  width: 100%; min-width: 60px; border: 1px solid var(--border); background: var(--card);
  color: var(--text); border-radius: 8px; padding: 6px 7px; font-size: 13px; font-family: inherit;
  outline: none; transition: border-color .2s;
}
.data-table .quote-cell-in:focus { border-color: var(--gold); }
.data-table .quote-cell-in.num { min-width: 70px; text-align: right; }
/* 文本列（项目内容等）加宽，避免长内容被挤窄 */
.data-table .quote-cell-in.txt { min-width: 200px; }
/* 备注列：多行文本框，自动换行、高度自适应 */
.data-table .quote-cell-ta {
  width: 240px; min-width: 220px; min-height: 46px; resize: none; overflow: hidden;
  border: 1px solid var(--border); background: var(--card); color: var(--text);
  border-radius: 8px; padding: 6px 7px; font-size: 13px; font-family: inherit; line-height: 1.45;
  outline: none; transition: border-color .2s;
}
.data-table .quote-cell-ta:focus { border-color: var(--gold); }

/* 工程名单详情：成本 / 报价 / 利润 三标签 */
.proj-tabs { display: flex; gap: 8px; margin: 0 4px 14px; }
.proj-tab { flex: 1; padding: 10px 0; border-radius: 12px; border: 1px solid var(--border); background: var(--bg); color: var(--text-secondary); font-size: 14px; font-weight: 600; cursor: pointer; transition: all .2s ease; }
.proj-tab.active { border-color: var(--gold); background: var(--gold-soft); color: var(--gold); }

/* 「未填写工程」补工程名弹窗：统一填一个 / 逐条分开填（2026-10-04）
   ⚠️ transition 只列会变的属性（写 all 会把不相关的属性也带上，容易出一帧跳变）。 */
.assign-modes { display: flex; gap: 8px; margin: 2px 0 2px; }
.assign-mode {
  flex: 1; padding: 9px 0; border-radius: 10px; border: 1px solid var(--border);
  background: var(--bg); color: var(--text-secondary); font-size: 13px; font-weight: 600;
  cursor: pointer; transition: border-color .2s ease, background .2s ease, color .2s ease;
}
.assign-mode.active { border-color: var(--gold); background: var(--gold-soft); color: var(--gold); }
.assign-quick { display: flex; gap: 8px; align-items: center; margin-bottom: 10px; }
.assign-quick input { flex: 1; min-width: 0; padding: 9px 12px; font-size: 14px; }
/* 逐条列表：自己内部滚动，别把弹窗撑高（弹窗头/底本来就固定，见 .modal-* 那节） */
.assign-list {
  max-height: 40vh; max-height: 40dvh;
  overflow-y: auto; overscroll-behavior: contain;
  border: 1px solid var(--border); border-radius: 12px; padding: 2px 4px;
}
.assign-row { display: flex; align-items: center; gap: 10px; padding: 9px 4px; border-bottom: 1px solid var(--border); }
.assign-row:last-child { border-bottom: none; }
.assign-row-info { flex: 1; min-width: 0; }
.assign-row-label { font-size: 13px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.assign-row-sub { font-size: 11px; color: var(--text-secondary); margin-top: 2px; }
.assign-row-input { width: 150px; flex: 0 0 auto; padding: 8px 10px; font-size: 13px; border-radius: 10px; }
@media (max-width: 400px) { .assign-row-input { width: 116px; } }

/* 工程名单 → 报价：已保存报价表卡片 */
.quote-saved-card { display: flex; align-items: stretch; gap: 8px; margin: 0 4px 10px; }
.quote-saved-card-btn { flex: 1; text-align: left; border: 1px solid var(--border); background: var(--card); border-radius: 12px; padding: 12px 14px; cursor: pointer; transition: border-color .2s ease; }
.quote-saved-card-btn:hover { border-color: var(--gold); }
.qsc-name { font-size: 14px; font-weight: 600; color: var(--text); }
.qsc-meta { font-size: 12px; color: var(--text-tertiary); margin-top: 4px; }
.qsc-del { width: 44px; border: 1px solid var(--border); background: var(--card); border-radius: 12px; cursor: pointer; font-size: 16px; color: var(--text-tertiary); transition: all .2s ease; }
.qsc-del:hover { border-color: #e74c3c; color: #e74c3c; }

@media (max-width: 560px) { .quote-charts { grid-template-columns: 1fr; } .quote-chart { height: 220px; } }

/* ===== 利润表（工程名单 → 某工程 → 利润标签） ===== */
.profit-table {
  width: 100%; border-collapse: collapse; margin: 8px 0 4px;
  background: var(--card); border-radius: 16px; overflow: hidden; box-shadow: var(--shadow);
}
.profit-table td { padding: 11px 14px; border-bottom: 1px solid var(--border); font-size: 14px; color: var(--text); }
.profit-table tr:last-child td { border-bottom: none; }
.profit-table td.p-amt {
  text-align: right; font-weight: 600; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.profit-table td.p-sub { font-size: 12px; font-weight: 400; color: var(--text-tertiary); padding-left: 0; }
.profit-table tr.p-total td { font-weight: 700; }
.profit-table tr.p-gross td { font-weight: 700; }
.profit-table tr.p-final td { font-weight: 800; font-size: 15px; }
.profit-table tr.p-final td:first-child { color: var(--gold); }
.profit-table tr.p-final { background: var(--gold-soft); }
.profit-table.profit-detail-table thead tr { background: var(--gold-soft); }
.profit-table.profit-detail-table th {
  padding: 11px 14px; font-size: 13px; font-weight: 700; color: var(--text);
  text-align: left; border-bottom: 1px solid var(--border);
}
.profit-table.profit-detail-table th:not(:first-child) { text-align: right; }
.profit-table.profit-detail-table tbody td:first-child { font-weight: 600; }
.p-craft-row td:first-child { display: flex; align-items: center; gap: 8px; }
.p-craft-name { font-weight: 600; }
.p-type-tag {
  display: inline-block; font-size: 11px; font-weight: 600;
  padding: 2px 8px; border-radius: 999px; line-height: 1.3;
}
.p-tag-labor { background: #FFF3E0; color: #E65100; }
.p-tag-material { background: #E3F2FD; color: #1565C0; }
@media (max-width: 560px) {
  .profit-table.profit-detail-table th { padding: 9px 10px; font-size: 12px; }
}
.p-share-input {
  width: 118px; text-align: right; appearance: none; -webkit-appearance: none;
  background: var(--card-hover); border: 1px solid var(--gold); border-radius: 999px;
  padding: 6px 14px; font-size: 14px; font-weight: 600; color: var(--text);
}
.p-share-input:focus { outline: none; box-shadow: 0 0 0 2px rgba(201, 162, 39, 0.18); }
@media (max-width: 560px) {
  .profit-table td { padding: 9px 10px; font-size: 13px; }
  .profit-table td.p-sub { display: none; }
  .p-share-input { width: 100px; }
}

/* ===== 报价单分项标题行（Excel 原始分项：一 / 二 / 三 …） ===== */
.quote-section-row td {
  background: var(--gold-soft);
  color: var(--gold);
  font-weight: 700;
  padding: 10px 12px !important;
  text-align: left;
}
.quote-section-row .qsr-name { font-size: 14px; letter-spacing: .5px; }
.quote-section-add {
  float: right;
  width: 26px; height: 26px; line-height: 1;
  border: 1px solid var(--gold); background: var(--card);
  border-radius: 50%; color: var(--gold);
  font-size: 16px; font-weight: 700; cursor: pointer;
  transition: all .18s ease;
}
.quote-section-add:hover { background: var(--gold); color: #fff; }
.quote-section-add:active { transform: scale(.92); }

/* ===== 报价表新增交互：隐藏列 / 折叠 / 行高亮 / 序号 / 表头编辑 ===== */

/* 表头单元格：承载隐藏按钮；拖拽平移时整体可被抓取 */
.data-table.quote-tbl thead th {
  position: relative;
  user-select: none;
}
/* 列隐藏按钮：hover 表头时显示，点击隐藏该列 */
.col-hide-btn {
  position: absolute;
  top: 2px; right: 2px;
  width: 16px; height: 16px; line-height: 14px;
  border: none; border-radius: 4px;
  background: var(--border); color: var(--text-secondary);
  font-size: 11px; cursor: pointer; opacity: 0;
  transition: opacity .15s ease;
}
.data-table.quote-tbl thead th:hover .col-hide-btn { opacity: .85; }
.col-hide-btn:hover { background: #e74c3c; color: #fff; opacity: 1 !important; }

/* 被隐藏列留下的「黑线」痕迹：点击恢复该列 */
.col-seam {
  min-width: 10px !important; width: 10px !important; padding: 0 !important;
  background: repeating-linear-gradient(45deg, var(--border) 0 3px, transparent 3px 6px);
  cursor: pointer; position: relative;
}
.col-seam:hover { background: var(--gold); }
.col-seam .col-seam-tip {
  display: none;
  position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
  margin-top: 4px; padding: 3px 8px; z-index: 30;
  background: #2b2b2b; color: #fff; font-size: 11px; border-radius: 6px;
  white-space: nowrap; pointer-events: none;
}
.col-seam:hover .col-seam-tip { display: block; }

/* 点击单元格 → 整行高亮 */
.data-table.quote-tbl tbody tr.row-active > td {
  background: var(--gold-soft);
}
.data-table.quote-tbl tbody tr.row-active > td:first-child {
  box-shadow: inset 3px 0 0 var(--gold);
}

/* 分项标题行：可折叠 + 汉字序号可编辑 */
.quote-section-row { cursor: pointer; }
.quote-section-row .qsr-inner { display: flex; align-items: center; gap: 8px; }
.quote-section-row .qsec-toggle {
  flex: 0 0 auto;
  width: 18px; height: 18px; line-height: 16px; text-align: center;
  border: 1px solid var(--gold); border-radius: 4px; color: var(--gold);
  font-size: 11px; cursor: pointer; background: var(--card);
  transition: transform .15s ease;
}
.quote-section-row.collapsed .qsec-toggle { transform: rotate(-90deg); }
.quote-section-row .qsec-seq-in {
  flex: 0 0 auto; width: 38px; text-align: center;
  border: 1px solid transparent; border-radius: 6px; background: rgba(255,255,255,.55);
  color: var(--gold); font-weight: 700; font-size: 14px; padding: 3px 2px;
}
.quote-section-row .qsec-seq-in:focus { outline: none; border-color: var(--gold); background: #fff; }
.quote-section-row .qsr-name-in {
  flex: 1 1 auto; min-width: 80px;
  border: 1px solid transparent; border-radius: 6px; background: rgba(255,255,255,.55);
  color: var(--gold); font-weight: 700; font-size: 14px; letter-spacing: .5px; padding: 3px 6px;
}
.quote-section-row .qsr-name-in:focus { outline: none; border-color: var(--gold); background: #fff; }
.quote-section-row .quote-section-add { margin-left: auto; }

/* 表头信息（工程名称 / 日期 / 面积 / 联系人）可编辑 */
.quote-header .qh-value-in {
  border: 1px solid transparent; border-radius: 8px; background: transparent;
  font-size: 14px; color: var(--text); font-weight: 600; padding: 3px 6px;
  width: 100%; box-sizing: border-box;
}
.quote-header .qh-value-in:focus { outline: none; border-color: var(--gold); background: var(--card); }

/* ===== 修改台账：修改成本 / 修改报价 ===== */
.el-card {
  background: var(--card); border-radius: 16px; box-shadow: var(--shadow);
  padding: 16px 18px; margin: 10px 4px;
}
.el-title { font-size: 14px; font-weight: 700; color: var(--text); margin-bottom: 12px; }
.el-btn-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.el-type-btn {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  padding: 16px 14px; cursor: pointer; text-align: left;
  background: var(--card-hover); border: 1px solid var(--border);
  border-radius: 16px; transition: all .2s ease;
}
.el-type-btn:hover { border-color: var(--gold); }
.el-type-btn.active { background: var(--gold-soft); border-color: var(--gold); }
.el-tb-name { font-size: 15px; font-weight: 700; color: var(--text); }
.el-type-btn.active .el-tb-name { color: var(--gold); }
.el-tb-desc { font-size: 12px; color: var(--text-tertiary); line-height: 1.5; }
@media (max-width: 560px) { .el-btn-row { grid-template-columns: 1fr; } }

/* 可编辑表格：行尾红色叉 / 成本表输入格 */
.qdel-th { width: 46px; }
.qrow-del-cell { text-align: center; }
.qrow-del {
  width: 26px; height: 26px; line-height: 1;
  border: none; background: rgba(231, 76, 60, 0.12); border-radius: 50%;
  color: #e74c3c; font-size: 17px; font-weight: 700; cursor: pointer;
  transition: all .18s ease;
}
.qrow-del:hover { background: #e74c3c; color: #fff; }
.qrow-del:active { transform: scale(.9); }
.cost-cell-in {
  width: 100%; box-sizing: border-box;
  background: var(--card-hover); border: 1px solid transparent;
  border-radius: 8px; padding: 6px 8px; font-size: 13px; color: var(--text);
}
.cost-cell-in:focus { outline: none; border-color: var(--gold); background: var(--card); }
.cost-cell-in.num { text-align: right; font-variant-numeric: tabular-nums; }
.cost-type-sel { min-width: 70px; appearance: none; -webkit-appearance: none; background: var(--card); border: 1px solid var(--gold); border-radius: 999px; padding: 4px 18px 4px 8px; font-size: 12px; font-weight: 600; color: var(--gold); cursor: pointer; background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%23C9A227' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><polyline points='3 5 6 8 9 5'/></svg>"); background-repeat: no-repeat; background-position: right 4px center; background-size: 10px; }
.cost-type-sel:disabled { opacity: 0.6; cursor: not-allowed; border-color: var(--border); color: var(--text-tertiary); background-image: none; }

/* ===== 只读成本表 + 悬浮「改」+ 底部抽屉（2026-10-08 第四轮）=====
   天阁拍板：不要每行都长一个「改」字 —— 改成一个**钉在屏幕右侧**的「改」，点一下改掉"点亮的那一行"。
   起因是卡顿：原来 336 行 × 11 个控件 = 3000+ 个「活的输入框」，手机上光养着它们就掉帧
   （实测滚动 60 帧累计卡顿 388ms → 只读后 0ms，见 measure_edit_mode.py）。
   🔴 只读格必须与原来的 .cost-cell-in **盒模型逐项一致**（同 padding / 同 1px 透明边框 / 同字号），
      否则行高就不是 45px 了 —— 量方案时专门锁过行高（不锁的话"表变短了"会被误当成"控件变少了"的功劳）。 */
.ro-td { padding: 0; }
.ro-val {
  display: block; box-sizing: border-box; width: 100%;
  border: 1px solid transparent; border-radius: 8px; padding: 6px 8px;
  font-size: 13px; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ro-num .ro-val { text-align: right; font-variant-numeric: tabular-nums; }
/* 「类型」列在只读表里保留原来的金胶囊长相（它是个分类标识，不该退化成裸文字） */
.ro-type .ro-val {
  display: inline-block; width: auto; min-width: 70px; text-align: center;
  background: var(--card); border: 1px solid var(--gold); border-radius: 999px;
  padding: 4px 12px; font-size: 12px; font-weight: 600; color: var(--gold);
}
/* 点亮的行：跟查找命中的 .tr-hit 用**同一套视觉** —— 用户眼里就是"这一行亮了"，
   两种来源（手指点的 / 搜到的）不该长得不一样。 */
.data-table tbody tr.tr-sel > td { background: var(--gold-soft); }
.data-table tbody tr.tr-sel > td:first-child { box-shadow: inset 3px 0 0 var(--gold); }
/* 改过但还没提交的行：格子文字变金色，一眼看出哪几行动过（不然改完还是一片黑字，以为没生效） */
.data-table tbody tr.tr-dirty .ro-val { color: var(--gold); font-weight: 600; }

/* 悬浮「改」：钉在**表格卡片的右边缘**（不是窗口最右）。
   2026-10-08 天阁看图：「电脑端这也太靠右了，正常情况下粘滞放这里就行」——宽屏下 #app 居中(1080px)、
   表格卡片更窄，死钉 right:10px 会离表格四百多像素。真正的 right 由 ledger.js 的 syncFabRight()
   按「表格右边→屏幕右边剩多少空白」算出并写进 inline style；这里的值是**兜底**（手机/表格铺满/还没布局完）。
   position:fixed 不能改成 sticky（祖先链上有假滚动容器，会被截住，同查找栏/底栏那条判据）。
   z-index 26 → 在钉住的查找栏(25)之上、底栏(30)之下；抽屉一开就被遮罩(90)盖住。 */
.el-row-edit {
  position: fixed; right: 10px; top: 50%; transform: translateY(-50%);
  z-index: 26;
  width: 46px; height: 46px; border-radius: 50%; border: none;
  background: var(--gold); color: #fff;
  font-size: 16px; font-weight: 700; line-height: 1;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .22);
  cursor: pointer; transition: transform .16s ease, background .16s ease;
}
.el-row-edit:hover:not(:disabled) { transform: translateY(-50%) scale(1.06); }
/* 没点亮任何行时它是暗的、按不动（不然它不知道该改哪一行） */
.el-row-edit:disabled { background: var(--border); color: var(--text-tertiary); box-shadow: none; cursor: default; }

/* 悬浮「删」（2026-10-10）：跟「改」成对，竖着叠在它正下方 56px（46 钮高 + 10 间距）。
   为什么用悬浮钮、而不是把行尾红叉挪个地方：
   红叉在**横向滚动的最右端**（手机要滑 562px 才到），而且滑到那儿它正好落在「改」所在
   的屏幕位置上被抢走点击（实测 elementFromPoint 打中的是「改」）。悬浮钮是 fixed 的、
   永远在屏幕上，客户抬眼就能看见，也不用横滑。
   top 写 calc(50% + 56px)、right 由 JS syncFabRight 与「改」同步（CSS 里这两个值是兜底）。 */
.el-row-del {
  position: fixed; right: 10px; top: calc(50% + 56px); transform: translateY(-50%);
  z-index: 26;
  width: 46px; height: 46px; border-radius: 50%; border: none;
  background: #C43B3B; color: #fff;
  font-size: 16px; font-weight: 700; line-height: 1;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .22);
  cursor: pointer; transition: transform .16s ease, background .16s ease;
}
.el-row-del:hover:not(:disabled) { transform: translateY(-50%) scale(1.06); }
.el-row-del:disabled { background: var(--border); color: var(--text-tertiary); box-shadow: none; cursor: default; }

/* 底部抽屉（点「改」升起）：**头部与底部按钮固定、只有中间 body 内部滚动** ——
   字段竖排比屏幕长时，按钮绝不能被顶出屏幕（modal-scroll-contained 的判据）。 */
.el-drawer-mask {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(0, 0, 0, .35);
  opacity: 0; pointer-events: none; transition: opacity .2s ease;
}
.el-drawer-mask.open { opacity: 1; pointer-events: auto; }
.el-drawer {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 95;
  display: flex; justify-content: center;
  transform: translateY(100%); pointer-events: none;
  transition: transform .24s ease;
}
.el-drawer.open { transform: translateY(0); pointer-events: auto; }
.el-drawer-panel {
  width: 100%; max-width: 560px;
  max-height: 78vh;                       /* 老浏览器兜底 */
  max-height: calc(100dvh - 56px);        /* 手机：别顶进状态栏；用 dvh 不用 vh（地址栏收起时会跳） */
  display: flex; flex-direction: column;
  background: var(--card);
  border-radius: 18px 18px 0 0;
  box-shadow: 0 -8px 28px rgba(0, 0, 0, .18);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.el-drawer-head {
  flex: none; display: flex; align-items: center; justify-content: space-between;
  padding: 12px 14px 8px; border-bottom: 1px solid var(--border);
}
.el-drawer-title { margin: 0; font-size: 15px; font-weight: 700; color: var(--text); }
.el-drawer-x {
  flex: none; width: 32px; height: 32px; border: none; background: transparent;
  font-size: 20px; line-height: 1; color: var(--text-tertiary); cursor: pointer;
}
.el-drawer-body {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  padding: 12px 14px; -webkit-overflow-scrolling: touch;
}
.el-drawer-foot {
  flex: none; display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
  padding: 10px 14px 12px; border-top: 1px solid var(--border);
}
/* 「删除这一行」独占一行（在「取消 / 确定」上面）：
   ① 手机窄，三个按钮挤一行每个只剩 ~110px，字会折；
   ② 更要紧的是**离「确定」远一点** —— 删除不可逆，别让它挨着「确定」造成误触。 */
.el-drawer-foot .el-drawer-del { grid-column: 1 / -1; }
.el-drawer-foot .el-drawer-del:hover { background: rgba(196, 59, 59, .2); }
/* 一格一行：左边字段名（62px 固定，标签列才对得齐），右边控件 */
.el-drawer-fld {
  display: grid; grid-template-columns: 62px 1fr; align-items: center;
  gap: 10px; margin-bottom: 10px;
}
.el-drawer-fld > span { font-size: 13px; color: var(--text-secondary); }
.el-drawer-note {
  margin: -2px 0 12px 72px; font-size: 12px; line-height: 1.5;
  color: var(--text-tertiary);
}
/* 抽屉里的控件要看得见边框（表格里是"融进底色"，抽屉里是唯一的输入区） */
.el-drawer .cost-cell-in { border-color: var(--border); background: var(--bg); }
.el-drawer .cost-cell-in:focus { border-color: var(--gold); background: var(--card); }
.el-drawer .cost-type-sel { width: 100%; min-width: 0; }

/* ===== 只读信息抽屉（2026-10-09：「展开 +」看明细）=====
   复用上面 .el-drawer* 那套：头部与底部固定、只有中间 body 内部滚动。这里只补三样。 */
/* 顶部一行灰色小字（共 N 笔 · 合计 ¥X）。不复用 .el-drawer-note —— 它左边留了 72px 折进字段列，
   而这一行要左对齐、贴着标题下面。 */
.el-drawer-sub { flex: none; padding: 8px 14px 0; font-size: 12.5px; color: var(--text-secondary); }
/* 这个抽屉底部只有一个「关闭」→ 底栏从两列改成一列（不然按钮只占左半边） */
.el-drawer-foot.is-single { grid-template-columns: 1fr; }
/* 明细行：上行「项目 —— 金额」，下行「日期 · 商家」。
   手机上分行显示比硬挤成一行好读（这一列本来就不宽）。 */
.el-detail-row { padding: 9px 0; border-bottom: 1px solid var(--border); }
.el-detail-row:last-child { border-bottom: none; }
.el-detail-main { display: flex; align-items: baseline; gap: 10px; }
.el-detail-name { flex: 1 1 auto; min-width: 0; font-size: 13.5px; color: var(--text); overflow-wrap: anywhere; }
.el-detail-amt { flex: none; font-size: 13.5px; font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
.el-detail-sub { display: flex; gap: 10px; margin-top: 2px; font-size: 12px; color: var(--text-tertiary); }
.el-detail-mer { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.el-detail-empty { padding: 12px 0; font-size: 13px; color: var(--text-tertiary); }

/* ===== 修改台账·表内查找定位（2026-10-08）=====
   成本/流水编辑表上方的「查找行」：按「搜索」/回车才找，找到就跳到命中行并整行点亮，
   再按一次搜索＝找下一个；↑↓ 循环、右侧显示第 n / 共 m 条。
   🔴 **不做边打边搜**（天阁 2026-10-08：「按搜索别实时搜呗…界面变得很卡」）——
      这张表几百行全是输入框，每敲一个字就全表扫描 + 滚到目标行 → 整屏重绘，打字一顿一顿的。
   🔴 **滚到顶端就钉住**（天阁第三轮：「一般还在原位，滚动到快看不见的时候到最顶部去」）——
      默认在原位，顶到 0 才挂 .is-stuck 切 position:fixed。**不能用 sticky**（祖先链上有假滚动容器，见下）。
   外观只调布局与按钮；输入框本身的美化交给全站兜底基线（:where(input[type=search])）——不重复写一套。 */
/* 查找栏本体。默认还**在原位**（跟以前一样），滚到顶才由 JS 挂 .is-stuck 切固定（见下）。
   🔴 两种状态**必须等高**，否则钉住的那一刻下方内容会跳一下：
      这里用同一个 --el-find-pad 打上下内边距，两态天然等高（不用 JS 去量）。
      顶部再叠一个安全区，钉在最上面时才不会被刘海/状态栏压住。 */
.el-find-bar {
  --el-find-pad: calc(6px + env(safe-area-inset-top, 0px));
  display: flex; align-items: center; gap: 6px;
  margin: 0 4px 8px;
  padding: var(--el-find-pad) 0;
  /* 透明下边框：钉住态那条 border-bottom 会让它高 1px，两态就不严格等高了（实测 52 vs 53）
     → 原位也留一条透明的占位，钉/取消钉时连 1px 都不跳 */
  border-bottom: 1px solid transparent;
}
.el-find-inner { display: flex; align-items: center; gap: 6px; flex: 1; min-width: 0; }
.el-find-bar .el-find-input { flex: 1; min-width: 0; padding: 9px 12px; font-size: 14px; }
/* 钉住态：贴视口最上沿（JS 顶到 0 时挂上；滚回顶部会自动摘掉） */
.el-find-bar.is-stuck {
  position: fixed; left: 0; right: 0; top: 0; z-index: 25;
  margin: 0;
  padding: var(--el-find-pad) 16px;
  background: var(--card); border-bottom: 1px solid var(--border);
  box-shadow: 0 4px 16px rgba(0, 0, 0, .07);
}
/* 钉住时铺满屏宽 → 内容限宽居中，桌面/平板才跟表格对齐（跟底栏同一套数字） */
.el-find-bar.is-stuck .el-find-inner { max-width: 528px; margin: 0 auto; }
/* 原位垫高：钉住后由它顶住那块空间，防止下方内容上跳（JS 按实际高度写入） */
.el-find-holder { height: 0; }
.el-find-btn {
  flex: none; width: 34px; height: 34px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg); color: var(--text-secondary);
  border: 1px solid var(--border); border-radius: 10px;
  font-size: 15px; font-weight: 700; line-height: 1; cursor: pointer;
  transition: border-color .2s ease, color .2s ease, background .2s ease;
}
.el-find-btn:hover:not(:disabled) { border-color: var(--gold); color: var(--gold); }
.el-find-btn:disabled { opacity: .45; cursor: default; }
/* 「搜索」是带字的按钮：比图标键宽一点；390px 手机上五个控件仍能挤在一行 */
.el-find-go { width: auto; min-width: 52px; padding: 0 10px; font-size: 13px; font-weight: 600; }
.el-find-clr { font-size: 17px; font-weight: 600; }
.el-find-count {
  margin: -2px 6px 8px 0; font-size: 12px; font-weight: 600;
  color: var(--text-secondary); text-align: right;
}
.el-find-count:empty { display: none; }
/* 命中的整行：浅金底 + 左侧金条（跟「修改成本」卡片的激活态同一套语言，深浅色自动适配） */
.data-table tbody tr.tr-hit > td { background: var(--gold-soft); }
.data-table tbody tr.tr-hit > td:first-child { box-shadow: inset 3px 0 0 var(--gold); }
/* 行内输入框在命中行里融进底色，整行才连成一体（输入框自己的底色会把它盖住） */
.data-table tbody tr.tr-hit .cost-cell-in { background: transparent; }
/* 具体命中的那一格再描一圈金边 —— 横向滚动后一眼看到词落在哪 */
.data-table tbody td.cell-hit .cost-cell-in,
.data-table tbody td.cell-hit .quote-cell-in { border-color: var(--gold); background: var(--card); }
/* 工程详情→成本 那张记录表是 .rec-table（另一种 class，2026-10-09 才给它加搜索栏）：
   命中行的视觉跟上面 .data-table 那套**保持一致**，只是选择器得照着它的 class 再写一份。
   （不像 .cost-cell-in 那两条是给行内输入框用的 —— .rec-table 是纯只读、没有输入框，不需要。） */
.rec-table tbody tr.tr-hit > td { background: var(--gold-soft); }
.rec-table tbody tr.tr-hit > td:first-child { box-shadow: inset 3px 0 0 var(--gold); }

/* ===== 页面底部固定底栏（2026-10-08）=====
   把「保存修改」锁在屏幕底边，不必滚到表尾才看得见（天阁要求）。
   做法与工程款项页的 .pay-add-btn 同一套：position:fixed 贴视口底边 + 安全区。
   🔴 **不用 sticky**：`.sub-main` 是 scroll container（写了 overflow-y:auto）但当前布局下
      不实际滚动 —— sticky 的包含块会是它，于是粘在它的底边（在页面很下面）＝等于没固定。
      同一个坑上轮在「搜索跳转」上已经踩过一次（见 _scrollHostOf 的注释）。
   🔴 `.el-dock-spacer` 负责垫高，否则表格最后几行会被这条底栏压住
      （工程款项页是用 .payments-page 的 padding-bottom:90px 兜的，这里页面是共用的 #sub-main，
        所以改用页内 spacer，影响范围更小）。
   🔴 z-index 取 30：低于设置面板遮罩(50)与弹窗遮罩(100) —— 抽屉/弹窗打开时底栏乖乖在下面。 */
.el-save-dock {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
  background: var(--card); border-top: 1px solid var(--border);
  box-shadow: 0 -4px 16px rgba(0, 0, 0, .07);
}
/* ⚠️ 试过给底栏加 `will-change: transform`（想消掉 fixed+阴影在长页面上滚动时的重绘）：
   同运行背靠背对比量出来 3030 / 3136 / 3404ms（底栏可见/隐藏/放回），**没看到收益**，
   跨运行波动比这个效应还大（±10%）→ 无法证明有效就不留（2026-10-08）。
   结论：这条底栏在滚动时的代价低于本测量台的噪声底，别再为它做微优化。 */
.el-save-dock .btn { display: block; width: 100%; max-width: 528px; margin: 0 auto; }
.el-dock-spacer { height: calc(88px + env(safe-area-inset-bottom, 0px)); }
/* 桌面/平板：#app 放宽到 1080px，底栏里的按钮跟着放宽，两边的视觉边距才对得上
   （钉住的查找栏同理，见 .el-find-bar.is-stuck .el-find-inner） */
@media (min-width: 768px) and (min-height: 521px) {
  .el-save-dock .btn { max-width: 1048px; }
  .el-find-bar.is-stuck .el-find-inner { max-width: 1048px; }
}

/* ===== 工程款项页面 ===== */
.payments-page { padding: 12px 0 90px; }
.pay-stats-row {
  display: grid; grid-template-columns: 1fr 1fr; gap: 12px;
  margin: 0 16px 16px;
}
.pay-stat-card {
  background: var(--card); border-radius: 18px; padding: 16px;
  box-shadow: var(--shadow); display: flex; flex-direction: column; gap: 8px;
  transition: background .25s ease, box-shadow .25s ease;
}
.pay-stat-un { background: linear-gradient(135deg, var(--card) 0%, var(--gold-soft) 100%); border: 1px solid var(--gold-light); }
.pay-stat-got { background: var(--card); border: 1px solid var(--border); }
.pay-stat-label { font-size: 13px; color: var(--text-secondary); font-weight: 500; }
.pay-stat-val { font-size: 22px; font-weight: 700; color: var(--gold); letter-spacing: -0.5px; }

.pay-projects-panel { margin: 0 16px 16px; }
.pay-list { display: flex; flex-direction: column; gap: 10px; }
.pay-item {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  background: var(--card); border: 1px solid var(--border); border-radius: 14px;
  padding: 14px 16px; box-shadow: var(--shadow);
  cursor: pointer; transition: transform .15s ease, border-color .2s ease, box-shadow .2s ease;
}
.pay-item:hover { border-color: var(--gold-light); box-shadow: 0 6px 18px rgba(201,162,39,0.12); }
.pay-item:active { transform: scale(0.985); }
.pay-item-main { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.pay-item-name { font-size: 15px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pay-item-sub { font-size: 12px; color: var(--text-secondary); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pay-item-badge {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--gold-soft); color: var(--gold-dark); border: 1px solid var(--gold-light);
  border-radius: 999px; padding: 2px 8px; font-size: 11px; font-weight: 600;
}
.pay-item-arrow { width: 18px; height: 18px; color: var(--text-tertiary); flex: none; }

/* 工程款项列表页 - 表格风格 */
.pay-table-wrapper { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.pay-list-table {
  width: 100%; min-width: 520px; background: var(--card); border-radius: 18px;
  box-shadow: var(--shadow); overflow: hidden;
}
.pay-list-head, .pay-list-row {
  display: grid;
  grid-template-columns: 1.6fr 70px 1fr 1fr 1fr;
  align-items: center; gap: 8px; padding: 0 12px;
}
.pay-list-head {
  background: var(--gold-soft);
  border-bottom: 1px solid var(--gold-light);
  font-size: 12px; font-weight: 600; color: var(--gold-dark);
  padding: 12px; text-align: center;
}
.pay-list-head span { display: flex; align-items: center; justify-content: center; }
.pay-list-row {
  border-bottom: 1px solid var(--border);
  font-size: 13px; color: var(--text);
  cursor: pointer; transition: background .15s ease;
  min-height: 48px;
}
.pay-list-row:last-child { border-bottom: none; }
.pay-list-row:hover { background: var(--gold-soft); }
.pay-list-row:active { background: rgba(201,162,39,0.14); }
.pay-list-row span {
  display: flex; align-items: center; justify-content: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  padding: 10px 0;
}
.pay-list-row .col-project { justify-content: flex-start; font-weight: 600; }
.pay-list-row .col-un, .pay-list-row .col-got { justify-content: flex-end; font-variant-numeric: tabular-nums; }
.pay-list-row .col-next { color: var(--text-secondary); font-size: 12px; }

.pay-add-btn {
  position: fixed; bottom: 24px; left: 16px; right: 16px;
  border-radius: 999px; padding: 14px; font-size: 15px; font-weight: 600;
  box-shadow: 0 6px 18px rgba(201,162,39,0.28); z-index: 10;
}

/* 工程名单 → 工程 → 成本：Excel 表格风（标题已由外层 table-hint 给出，这里只做表头+内容） */
.rec-table-card {
  background: var(--card); border-radius: 18px; box-shadow: var(--shadow);
  overflow-x: auto; margin: 4px 0 12px;
}
.rec-table { width: 100%; min-width: 860px; border-collapse: collapse; }
.rec-table thead th {
  position: sticky; top: 0;
  background: var(--gold-soft); color: var(--gold-dark);
  font-size: 12px; font-weight: 600; padding: 12px 10px; text-align: left;
  border-bottom: 1px solid var(--gold-light); white-space: nowrap;
}
.rec-table thead th.r { text-align: right; }
.rec-table tbody td {
  padding: 11px 10px; border-bottom: 1px solid var(--border);
  font-size: 13px; color: var(--text); vertical-align: top; line-height: 1.5;
}
.rec-table tbody tr:last-child td { border-bottom: none; }
.rec-table tbody tr:hover { background: var(--gold-soft); }
.rec-table td.r { text-align: right; font-variant-numeric: tabular-nums; }
.rec-table td.rec-amount { font-weight: 700; white-space: nowrap; }
.rec-table td.rec-dir-in { color: #D93025; }
.rec-table td.rec-date, .rec-table td.rec-unit-price, .rec-table td.rec-quantity, .rec-table td.rec-unit, .rec-table td.rec-remark { color: var(--text-secondary); }
.rec-table td.rec-remark { max-width: 160px; }

/* 工程款项编辑页 */
.pay-edit { padding: 12px 16px 100px; }
.pay-table-card {
  background: var(--card); border-radius: 18px; padding: 12px 8px;
  box-shadow: var(--shadow); margin: 16px 0; overflow-x: auto;
}
.pay-table-head, .pay-row {
  display: grid;
  grid-template-columns: 58px 74px 58px 58px 1fr 64px 40px;
  align-items: center; gap: 6px;
  min-width: 520px;
}
.pay-table-head {
  font-size: 12px; font-weight: 600; color: var(--text-secondary);
  padding: 0 6px 8px; border-bottom: 1px solid var(--border);
  text-align: center;
}
.pay-row { padding: 8px 6px; border-bottom: 1px solid var(--border); }
.pay-row:last-child { border-bottom: none; }
.pay-table-head span, .pay-row > span { display: flex; align-items: center; justify-content: center; }
.pay-table-head .col-amount, .pay-row .col-amount { justify-content: flex-end; }
.pay-period-badge {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--gold); color: #fff; border-radius: 999px;
  padding: 3px 9px; font-size: 12px; font-weight: 700; min-width: 44px;
}
.pay-cell {
  width: 100%; box-sizing: border-box;
  background: var(--bg); border: 1px solid var(--border);
  border-radius: 10px; padding: 8px 10px; font-size: 13px; color: var(--text);
  text-align: center; transition: border-color .2s, background .2s;
}
.pay-cell:focus { outline: none; border-color: var(--gold); background: var(--card); }
.pay-cell-num { font-variant-numeric: tabular-nums; }
.pay-cell-amt { text-align: right; font-variant-numeric: tabular-nums; }

.pay-switch {
  position: relative; display: inline-block; width: 42px; height: 24px; cursor: pointer;
}
.pay-switch input { opacity: 0; width: 0; height: 0; }
.pay-switch-slider {
  position: absolute; inset: 0; border-radius: 999px; background: var(--border);
  transition: background .25s ease; border: 1px solid transparent;
}
.pay-switch-slider::before {
  content: ""; position: absolute; height: 18px; width: 18px; left: 2px; top: 2px;
  border-radius: 50%; background: #fff; box-shadow: 0 2px 4px rgba(0,0,0,0.18);
  transition: transform .25s ease;
}
.pay-switch input:checked + .pay-switch-slider { background: var(--gold); }
.pay-switch input:checked + .pay-switch-slider::before { transform: translateX(18px); }

.pay-del-btn {
  width: 28px; height: 28px; border-radius: 50%; border: 1px solid var(--gold-light);
  background: var(--gold-soft); color: var(--gold-dark); font-size: 18px; line-height: 1;
  cursor: pointer; transition: all .18s ease; display: inline-flex; align-items: center; justify-content: center;
}
.pay-del-btn:hover { background: var(--gold); color: #fff; }
.pay-del-btn:active { transform: scale(0.9); }

.pay-total-card {
  display: flex; align-items: center; justify-content: space-between;
  background: var(--gold-soft); border: 1px solid var(--gold-light);
  border-radius: 14px; padding: 14px 18px; margin: 12px 0 18px;
}
.pay-total-label { font-size: 15px; font-weight: 600; color: var(--gold-dark); }
.pay-total-val { font-size: 18px; font-weight: 700; color: var(--gold); }

.pay-edit-actions { display: flex; flex-direction: column; gap: 12px; }
.pay-edit-actions .btn { width: 100%; border-radius: 999px; padding: 13px; font-size: 15px; font-weight: 600; }
.pay-edit-actions .btn-add-row { border-style: dashed; }

@media (min-width: 640px) {
  .pay-add-btn { left: 50%; right: auto; transform: translateX(-50%); width: calc(100% - 32px); max-width: 480px; }
  .pay-edit-actions { flex-direction: row; }
  .pay-edit-actions .btn { width: auto; flex: 1; }
  .pay-table-head, .pay-row { grid-template-columns: 72px 86px 68px 68px 1fr 74px 44px; gap: 8px; }
}

/* ===== 登录记录（安全审计） ===== */
.lh-wrap { padding: 0 0 24px; }
.lh-page { display: flex; flex-direction: column; gap: 12px; }
.lh-filter-row {
  display: flex; flex-wrap: wrap; gap: 10px;
  margin: 0 16px 4px;
}
.lh-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.lh-body { display: flex; flex-direction: column; gap: 12px; padding: 0 16px; }
.lh-stats-row {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px;
}
.lh-stat-card {
  background: var(--card); border: 1px solid var(--border); border-radius: 16px;
  padding: 12px 10px; box-shadow: var(--shadow);
  display: flex; flex-direction: column; gap: 6px; align-items: center;
  transition: background .25s ease, box-shadow .25s ease;
}
.lh-stat-ok { background: linear-gradient(135deg, var(--card) 0%, var(--gold-soft) 100%); border-color: var(--gold-light); }
.lh-stat-fail { border-color: rgba(192, 57, 43, 0.35); }
.lh-stat-ip { border-color: var(--border); }
.lh-stat-label { font-size: 12px; color: var(--text-secondary); font-weight: 500; }
.lh-stat-val { font-size: 20px; font-weight: 700; color: var(--gold); letter-spacing: -0.5px; }
.lh-stat-fail .lh-stat-val { color: #c0392b; }
.lh-last-fail {
  margin: 0; font-size: 12px; color: var(--text-secondary);
  padding: 10px 12px; background: var(--card); border: 1px solid var(--border);
  border-radius: 12px; word-break: break-all;
}
.lh-list { display: flex; flex-direction: column; gap: 8px; }
.lh-item {
  background: var(--card); border: 1px solid var(--border); border-radius: 14px;
  padding: 12px 14px; box-shadow: var(--shadow);
  display: flex; flex-direction: column; gap: 6px;
  transition: background .25s ease, border-color .2s ease;
}
.lh-item.lh-bad { border-left: 3px solid #c0392b; }
.lh-item.lh-ok { border-left: 3px solid var(--gold); }
.lh-item-top { display: flex; align-items: center; gap: 8px; }
.lh-badge {
  flex: none; font-size: 11px; font-weight: 700; border-radius: 999px;
  padding: 2px 9px; border: 1px solid transparent;
}
.lh-badge-ok { background: var(--gold-soft); color: var(--gold-dark); border-color: var(--gold-light); }
.lh-badge-bad { background: rgba(192, 57, 43, 0.1); color: #c0392b; border-color: rgba(192, 57, 43, 0.35); }
.lh-account { font-size: 14px; font-weight: 600; color: var(--text); }
.lh-time { margin-left: auto; font-size: 12px; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }
.lh-item-sub { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; font-size: 12px; color: var(--text-secondary); }
.lh-dot { color: var(--text-tertiary); }
.lh-reason { color: #c0392b; }
.lh-ip { font-variant-numeric: tabular-nums; }

@media (max-width: 360px) {
  .lh-stats-row { grid-template-columns: 1fr 1fr; }
  .lh-stat-ip { grid-column: span 2; }
}

/* ===== 登录记录：账号选择卡片（对齐统一工作台风格） ===== */
.lh-pick-tip {
  margin: 4px 16px 12px; font-size: 13px; color: var(--text-secondary);
}
.lh-acc-list { display: flex; flex-direction: column; gap: 10px; padding: 0 16px; }
.lh-acc-card {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 14px; border: 1px solid var(--border); border-radius: 14px;
  background: var(--card); cursor: pointer; text-align: left; font-family: inherit;
  box-shadow: var(--shadow);
  transition: background .18s ease, border-color .18s ease, transform .15s ease, box-shadow .18s ease;
  -webkit-tap-highlight-color: transparent;
}
.lh-acc-card:hover, .lh-acc-card:active {
  background: var(--gold-soft); border-color: var(--gold);
  transform: translateY(-1px); box-shadow: 0 4px 14px rgba(201,162,39,.15);
}
.lh-acc-avatar {
  width: 40px; height: 40px; border-radius: 12px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, var(--gold) 0%, var(--gold-dark) 100%);
  color: #fff; font-size: 16px; font-weight: 700;
}
.lh-acc-out .lh-acc-avatar { background: #c0392b; }
.lh-acc-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.lh-acc-name { font-size: 15px; font-weight: 600; color: var(--text); }
.lh-acc-sub {
  font-size: 12px; color: var(--text-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lh-acc-badge {
  flex-shrink: 0; font-size: 11px; font-weight: 700; border-radius: 999px;
  padding: 3px 9px; border: 1px solid transparent;
}
.lh-acc-badge-ok { background: var(--gold-soft); color: var(--gold-dark); border-color: var(--gold-light); }
.lh-acc-badge-bad { background: rgba(192, 57, 43, 0.1); color: #c0392b; border-color: rgba(192, 57, 43, 0.35); }
.lh-acc-go { flex-shrink: 0; font-size: 16px; color: var(--gold); font-weight: 600; }

/* ===== 操作审计（audit.js；骨架复用上方 .lh-* 类，这里只补审计特有部分） ===== */
.audit-filters { display: flex; flex-direction: column; gap: 10px; padding: 0 16px 4px; }
.audit-fline { display: flex; align-items: flex-start; gap: 8px; }
.audit-flabel {
  flex: none; min-width: 42px; font-size: 12px; color: var(--text-tertiary);
  line-height: 26px;
}
.audit-filters .lh-chips { flex: 1; min-width: 0; }
.audit-summary {
  margin: 0; font-size: 13px; line-height: 1.55; color: var(--text);
  word-break: break-word; white-space: pre-wrap;
}
.audit-changes {
  display: flex; flex-direction: column; gap: 4px;
  margin-top: 2px; padding: 8px 10px;
  background: var(--gold-soft); border-radius: 10px;
}
.audit-chg-title { font-size: 11px; font-weight: 600; color: var(--gold-dark); margin-bottom: 2px; }
.audit-chg-row { display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px; font-size: 12px; }
.audit-chg-key { flex: none; min-width: 42px; color: var(--text-secondary); font-weight: 500; }
.audit-chg-old { color: var(--text-tertiary); text-decoration: line-through; word-break: break-all; }
.audit-chg-arrow { flex: none; color: var(--gold); }
.audit-chg-new { color: var(--text); font-weight: 600; word-break: break-all; }

/* ===== 备案信息（页面底部：公安 + ICP） ===== */
.beian {
  display: flex; align-items: center; justify-content: center; gap: 5px;
  /* 窄屏（≤360px）两条备案号放不下时换行，不许溢出 */
  flex-wrap: wrap; row-gap: 6px;
  padding: 14px 16px calc(16px + env(safe-area-inset-bottom, 0px));
  font-size: 12px; color: var(--text-tertiary);
}
.beian a {
  display: inline-flex; align-items: center; gap: 5px;
  color: var(--text-tertiary); text-decoration: none;
  transition: color .2s ease;
}
.beian a:hover { color: var(--gold); }
.beian img { width: 16px; height: 16px; object-fit: contain; display: block; }

/* ===== 刘海屏 / 全面屏安全距离（viewport-fit=cover 后手动避让） ===== */
/* 顶部：两条 sticky 头部 + 小阁抽屉头部 */
.home-header { padding-top: calc(18px + env(safe-area-inset-top, 0px)); }
.sub-header { padding-top: calc(14px + env(safe-area-inset-top, 0px)); }
.ai-head { padding-top: calc(12px + env(safe-area-inset-top, 0px)); }

/* 底部：悬浮按钮、子页滚动内容、Toast */
.pay-add-btn { bottom: calc(24px + env(safe-area-inset-bottom, 0px)); }
.sub-main { padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px)); }
.toast { bottom: calc(90px + env(safe-area-inset-bottom, 0px)); }

/* ===== 人工成本（工数 → 工资）· 2026-10-02 ===== */
.labor-topbar {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 12px; flex-wrap: wrap;
}
/* 汇总页的日期胶囊（原来是裸 date 控件：方角、灰边、跟全站不搭） */
.labor-date-bar { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.labor-date-wrap {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--card); border: 1px solid var(--border);
  border-radius: 999px; padding: 7px 13px; cursor: pointer;
}
.labor-date-wrap svg { width: 15px; height: 15px; color: var(--gold); flex: none; }
.labor-date-wrap input[type="date"] {
  border: none; background: transparent; color: var(--text);
  font-size: 14px; font-family: inherit; outline: none;
  padding: 0; min-width: 116px; cursor: pointer;
}
.labor-date-wrap input[type="date"]::-webkit-calendar-picker-indicator {
  opacity: .45; cursor: pointer;
}
.labor-date-wrap:focus-within { border-color: var(--gold); }
.labor-back {
  background: var(--card); border: 1px solid var(--border);
  color: var(--text-secondary); border-radius: 999px;
  padding: 6px 12px; font-size: 12px; cursor: pointer;
}
.labor-back:active { transform: scale(0.97); }
.labor-project-name {
  font-size: 14px; font-weight: 600; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* 表上方的单价部署栏 */
.labor-rate-bar {
  /* 竖排两行：上行「工种 + 单价」，下行整条「一键部署」。
     原来一行 flex 排 —— .btn 自带 flex:1，把按钮拉成一整条金色大块，
     按钮文字被推到屏幕外，看着就是一块没有字的金砖（2026-10-02 天阁截图指出）。 */
  display: flex; flex-direction: column; gap: 10px;
  background: var(--gold-soft); border: 1px solid var(--gold-light);
  border-radius: 14px; padding: 12px; margin-bottom: 12px;
}
.labor-rate-fields { display: flex; align-items: center; gap: 8px; min-width: 0; }
.labor-rate-label { font-size: 12px; color: var(--text-secondary); white-space: nowrap; }
.labor-rate-fields select,
.labor-rate-fields input[type="number"] {
  border: 1px solid var(--gold-light);
  background: var(--card); color: var(--text);
  border-radius: 10px; padding: 9px 10px;
  font-size: 14px; font-family: inherit; outline: none;
}
.labor-rate-fields select { flex: 1 1 auto; min-width: 0; }
.labor-rate-fields input[type="number"] { flex: 0 0 104px; min-width: 0; }
.labor-rate-fields select:focus,
.labor-rate-fields input[type="number"]:focus { border-color: var(--gold); }
.labor-rate-bar .btn { flex: 0 0 auto; }   /* 竖排下必须收回 flex:1，否则会纵向拉伸 */
.labor-rate-bar input:disabled,
.labor-rate-bar select:disabled,
.labor-rate-bar button:disabled { opacity: .5; cursor: not-allowed; }
.labor-readonly-tag { font-size: 11px; color: var(--text-tertiary); }

/* 主表 */
.labor-table { white-space: nowrap; }
.labor-nm { font-weight: 500; }
.labor-craft-tag {
  display: inline-block; padding: 2px 8px; border-radius: 999px;
  background: var(--gold-soft); color: var(--gold-dark);
  font-size: 11px; white-space: nowrap;
}
.labor-qty-cell { display: flex; align-items: center; gap: 6px; }
.labor-qty { font-variant-numeric: tabular-nums; font-weight: 500; }
.labor-dim { color: var(--text-tertiary); font-size: 12px; }
.labor-last { color: var(--text-secondary); font-size: 12px; }

/* 🔴 操作列「吸附」在右边（2026-10-02 天阁选 B）
   主表 7 列在 390px 手机上装不下，横向拖的时候「＋今天」会滑出屏幕、够不着。
   把最后一列钉（sticky）在右边：无论怎么拖，主操作永远在手边。
   注意 td 必须保持 table-cell（按钮包一层 .labor-ops-in 做 flex），
   给 td 直接写 display:flex 会让它脱离表格布局，sticky 就失效了。 */
.labor-table th:last-child,
.labor-table td:last-child {
  position: sticky;
  right: 0;
  background: var(--bg);
  /* 🔴 常驻一道细线（金色，跟全站风格一致）：
     没有它，被钉子切掉一半的数字会被当成完整数字读错 ——
     实测「今日工资 ¥400」正好被切成「¥40」，一眼就是四十块。 */
  box-shadow: inset 1.5px 0 0 var(--gold-light);
}
.labor-table th:last-child { z-index: 3; }   /* 表头还要同时 sticky top，层级最高 */
.labor-table td:last-child { z-index: 2; }
/* 淡影只在**真的横向滚动过**之后才出现（没滚动时挂一道影子会看着像 bug） */
.labor-table.is-pinned th:last-child,
.labor-table.is-pinned td:last-child {
  box-shadow: inset 1.5px 0 0 var(--gold-light), -8px 0 8px -8px rgba(0, 0, 0, .25);
}
.labor-ops-in { display: flex; gap: 6px; justify-content: flex-end; }

.labor-mini-btn {
  border: 1px solid var(--gold-light); background: transparent;
  color: var(--gold-dark); border-radius: 999px;
  padding: 3px 10px; font-size: 11px; cursor: pointer; white-space: nowrap;
}
.labor-mini-btn:active { transform: scale(0.96); }
.labor-mini-btn.primary { background: var(--gold); border-color: var(--gold); color: #fff; }
.labor-mini-btn.danger { border-color: rgba(196, 59, 59, .35); color: #C43B3B; }
/* 防连点：请求飞行期间置灰 + 禁止光标 —— 用户马上知道"点到了，在处理"。
   没有这行的话点下去毫无反应，用户会以为没点上，于是更用力地连点。 */
.labor-mini-btn:disabled { opacity: .45; cursor: not-allowed; }
.labor-mini-btn:disabled:active { transform: none; }

.labor-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 12px; }

/* 选工程 */
.labor-proj-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
.labor-proj-item {
  display: flex; align-items: center; gap: 10px;
  background: var(--card); border: 1px solid var(--border);
  border-radius: 12px; padding: 12px 14px;
  color: var(--text); font-size: 14px; text-align: left; cursor: pointer;
}
.labor-proj-item:active { background: var(--card-hover); transform: scale(0.99); }
.labor-proj-item svg { width: 18px; height: 18px; color: var(--gold); flex: none; }
.labor-proj-item span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.labor-new-project {
  display: flex; gap: 8px; align-items: center;
  border-top: 1px solid var(--border); padding-top: 14px; margin-top: 4px;
}
.labor-new-project input {
  flex: 1 1 auto; min-width: 0;
  border: 1px solid var(--border);
  background: var(--card); color: var(--text);
  border-radius: 12px; padding: 11px 12px;
  font-size: 14px; font-family: inherit; outline: none;
}
.labor-new-project input::placeholder { color: var(--text-tertiary); }
.labor-new-project input:focus { border-color: var(--gold); }
.labor-new-project .btn { flex: 0 0 auto; padding: 11px 20px; font-size: 14px; }

/* 弹窗内的行 */
.labor-pick-line { font-size: 13px; color: var(--text); margin: 0 0 10px; }
.labor-warn { font-size: 13px; color: #C43B3B; line-height: 1.6; margin: 0; }
.labor-warn-inline {
  font-size: 12px; color: var(--gold-dark); background: var(--gold-soft);
  border-radius: 8px; padding: 8px 10px; margin: 10px 0 0; line-height: 1.5;
}
.labor-dt-row {
  /* 原来是 grid 96px 76px 1fr —— 操作区只剩 ~118px，而「输入框+保存+删」要 ~156px，
     于是「删」被挤出弹窗右边**点不到**（2026-10-02 界面截图抓到）。
     改弹性 + 允许换行：一行装不下时，操作区整体折到下一行并右对齐，任何屏宽都不截断。 */
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
  padding: 8px 0; border-bottom: 1px solid var(--border);
}
.labor-dt-row:last-child { border-bottom: none; }
.labor-dt-date { flex: 0 0 auto; min-width: 84px; font-size: 13px; color: var(--text); font-variant-numeric: tabular-nums; }
.labor-dt-qty { flex: 0 0 auto; min-width: 58px; font-size: 13px; color: var(--text-secondary); }
.labor-dt-ops { display: flex; align-items: center; gap: 6px; margin-left: auto; }
/* 工时明细里那个 56px 小格子：窄框吃不下 12px 大圆角，显式收小到 8px 才不显得像个胶囊 */
.labor-dt-input { width: 56px; padding: 4px 6px; font-size: 12px; border-radius: 8px; text-align: center; }

/* 工时汇总页 */
.labor-daily-pj {
  background: var(--card); border: 1px solid var(--border);
  border-radius: 14px; padding: 14px; margin-bottom: 12px;
}
.labor-daily-pj-name {
  display: flex; justify-content: space-between; align-items: baseline; gap: 10px;
  font-size: 14px; font-weight: 600; color: var(--text); margin-bottom: 10px;
}
.labor-daily-pj-sum { font-size: 12px; font-weight: 400; color: var(--text-secondary); }
.labor-daily-craft { margin-bottom: 10px; }
.labor-daily-craft:last-child { margin-bottom: 0; }
.labor-daily-craft-head {
  display: flex; justify-content: space-between; align-items: center;
  font-size: 12px; color: var(--text-secondary); margin-bottom: 4px;
}
.labor-daily-w {
  display: flex; justify-content: space-between;
  font-size: 13px; color: var(--text);
  padding: 4px 0 4px 12px; border-left: 2px solid var(--gold-light);
  margin-left: 2px;
}
.labor-daily-total {
  display: flex; justify-content: space-between;
  font-size: 14px; font-weight: 600; color: var(--text);
  padding: 12px 14px; border-radius: 12px; background: var(--gold-soft);
}

/* ===== 撤销回退（右上角圆形按钮 → 两步面板） =====
   警示红刻意用固定色：全站变量里没有 danger 色，而它在浅色/深色下都要读得清。 */
.undo-panel { width: min(520px, 100%); max-height: 84dvh; }
.undo-hint { font-size: 13px; color: var(--text-secondary); line-height: 1.6; }
.undo-hint-dim { color: var(--text-tertiary); font-size: 12px; }

.undo-step {
  display: flex; flex-direction: column; gap: 3px;
  width: 100%; text-align: left;
  border: 1px solid var(--border); background: var(--card);
  border-radius: 10px; padding: 10px 12px; cursor: pointer;
  transition: transform .12s ease, background .2s ease, border-color .2s ease;
}
.undo-step:active { transform: scale(0.99); }
.undo-step.is-disabled { opacity: .62; }
.undo-step-when { font-size: 12px; color: var(--text-tertiary); }
.undo-step-main { font-size: 14px; font-weight: 500; color: var(--text); }
.undo-step-count { font-size: 12px; font-weight: 400; color: var(--text-tertiary); margin-left: 6px; }
.undo-step-sub { font-size: 12px; color: var(--text-secondary); }
.undo-bad { color: #D9534F; }

.undo-item {
  display: flex; gap: 8px; font-size: 13px;
  padding: 5px 0; border-bottom: 1px dashed var(--border);
}
.undo-item-tag { flex: 0 0 auto; font-size: 12px; color: var(--gold); }
.undo-item-sum { min-width: 0; font-size: 12px; color: var(--text-secondary); word-break: break-all; }

.undo-conflict {
  margin-top: 10px; padding: 10px 12px; border-radius: 10px;
  border: 1px solid #D9534F; background: rgba(217, 83, 79, .07);
}
.undo-conflict-title { font-size: 13px; font-weight: 500; color: #D9534F; margin-bottom: 6px; }
.undo-conflict-row { font-size: 12px; color: var(--text); line-height: 1.7; }
.undo-conflict-tip { font-size: 12px; color: var(--text-secondary); line-height: 1.6; margin-top: 6px; }

.undo-effect-title { margin-top: 12px; font-size: 13px; font-weight: 500; color: var(--text); }
.undo-effect {
  margin-top: 6px; padding: 10px 12px;
  border: 1px solid var(--border); border-radius: 10px;
}
.undo-effect-row { font-size: 12px; color: var(--text-secondary); line-height: 1.8; }
.undo-foot-note { font-size: 12px; color: var(--text-tertiary); margin-right: auto; }
