/* ============================================================================
 * ERP 审批系统 · 网页端样式
 *
 * 设计原则：
 *   1. 零外部依赖（不引字体、不引图标库、不引 CSS 框架），内网也能正常显示。
 *   2. 一套 CSS 同时服务电脑宽屏和手机窄屏：
 *        宽度 > 900px  → 左侧边栏 + 顶部栏 + 宽表格
 *        宽度 ≤ 900px  → 底部标签栏 + 卡片式列表
 *   3. 颜色统一走 CSS 变量，改主题只改最上面那一段。
 * ==========================================================================*/

:root {
  --blue: #1e5eff;
  --blue-dark: #1749c9;
  --blue-soft: #eaf0ff;

  --red: #e0322b;
  --red-soft: #fdeceb;
  --orange: #e07b1a;
  --orange-soft: #fdf3e6;
  --green: #12a150;
  --green-soft: #e8f7ee;

  --text: #1c2333;
  --text-2: #5b6478;
  --text-3: #8d95a8;

  --line: #e5e8f0;
  --line-soft: #f0f2f7;
  --bg: #f4f6fb;
  --card: #ffffff;

  --radius: 12px;
  --radius-sm: 8px;
  --shadow: 0 1px 2px rgba(20, 30, 60, .05), 0 4px 16px rgba(20, 30, 60, .06);
  --shadow-lg: 0 8px 32px rgba(20, 30, 60, .16);

  --sidebar-w: 216px;
  --bottomnav-h: 58px;
}

* { box-sizing: border-box; }

/**
 * 必须显式声明这一条。
 *
 * 浏览器自带的 [hidden] { display: none } 属于「用户代理样式」，
 * 优先级低于作者写的任何样式。而下面的 .sidebar / .bottomnav 都写了
 * display: flex，于是 el.hidden = true 会完全失效 —— 表现就是登录页
 * 左侧还杵着一条导航栏。加 !important 才能压住。
 */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Microsoft YaHei",
               "PingFang SC", "Hiragino Sans GB", "Source Han Sans SC", sans-serif;
  font-size: 14px;
  line-height: 1.6;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--blue); text-decoration: none; }
button { font-family: inherit; font-size: inherit; }

/* ---------------------------------------------------------------------------
 * 首屏加载
 * ------------------------------------------------------------------------*/

.boot {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 22px;
  background: var(--bg);
  z-index: 100;
}
.boot-logo {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 17px;
  font-weight: 600;
  color: var(--text-2);
}
.boot[hidden] { display: none; }

.spinner {
  width: 30px;
  height: 30px;
  border: 3px solid var(--line);
  border-top-color: var(--blue);
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------------------------------------------------------------------------
 * 整体布局
 * ------------------------------------------------------------------------*/

.app { display: flex; min-height: 100vh; }
.app[hidden] { display: none; }

.sidebar {
  width: var(--sidebar-w);
  flex: 0 0 var(--sidebar-w);
  background: var(--card);
  border-right: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
}

.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 18px 18px 16px;
  font-weight: 700;
  font-size: 15px;
  letter-spacing: .2px;
  border-bottom: 1px solid var(--line-soft);
}

.nav { padding: 12px 10px; flex: 1; overflow-y: auto; }

.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  margin-bottom: 3px;
  border-radius: var(--radius-sm);
  color: var(--text-2);
  font-weight: 500;
  cursor: pointer;
  border: none;
  background: none;
  width: 100%;
  text-align: left;
  transition: background .12s, color .12s;
}
.nav-item:hover { background: var(--line-soft); color: var(--text); }
.nav-item.active { background: var(--blue-soft); color: var(--blue); font-weight: 600; }
.nav-item svg { flex: 0 0 18px; }
.nav-item .nav-label { flex: 1; }

.sidebar-user {
  padding: 12px 16px 16px;
  border-top: 1px solid var(--line-soft);
  font-size: 12.5px;
  color: var(--text-3);
}
.sidebar-user .su-name { color: var(--text); font-weight: 600; font-size: 13.5px; }
.sidebar-user .su-roles { margin-top: 2px; word-break: break-all; }
.sidebar-user .su-out {
  margin-top: 9px;
  width: 100%;
  padding: 7px;
  border: 1px solid var(--line);
  background: #fff;
  border-radius: var(--radius-sm);
  color: var(--text-2);
  cursor: pointer;
}
.sidebar-user .su-out:hover { border-color: var(--red); color: var(--red); }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 22px;
  background: rgba(255, 255, 255, .86);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 20;
}
.topbar[hidden] { display: none; }
.topbar h1 { margin: 0; font-size: 17px; font-weight: 650; flex: 1; min-width: 0; }
.topbar .sub { font-size: 12.5px; color: var(--text-3); font-weight: 400; margin-left: 8px; }
.topbar-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

.view { padding: 20px 22px 34px; flex: 1; }
/* 登录页要占满整屏，去掉外层的留白 */
.view.login-mode { padding: 0; }

/* 手机底部导航 */
.bottomnav {
  display: none;
  position: fixed;
  left: 0; right: 0; bottom: 0;
  height: var(--bottomnav-h);
  background: var(--card);
  border-top: 1px solid var(--line);
  z-index: 30;
  padding-bottom: env(safe-area-inset-bottom);
}
.bottomnav-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  border: none;
  background: none;
  color: var(--text-3);
  font-size: 11px;
  cursor: pointer;
  position: relative;
}
.bottomnav-item.active { color: var(--blue); }
.bottomnav-item .bn-badge {
  position: absolute;
  top: 4px;
  left: 50%;
  margin-left: 4px;
  min-width: 17px;
  height: 17px;
  padding: 0 4px;
  border-radius: 9px;
  background: var(--red);
  color: #fff;
  font-size: 10.5px;
  line-height: 17px;
  font-weight: 700;
  text-align: center;
}

/* ---------------------------------------------------------------------------
 * 通用组件
 * ------------------------------------------------------------------------*/

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 16px 18px;
  margin-bottom: 16px;
}
.card-title {
  margin: 0 0 12px;
  font-size: 14.5px;
  font-weight: 650;
  display: flex;
  align-items: center;
  gap: 8px;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 15px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: #fff;
  color: var(--text);
  cursor: pointer;
  font-weight: 500;
  transition: background .12s, border-color .12s, opacity .12s;
  white-space: nowrap;
}
.btn:hover:not(:disabled) { border-color: #cfd6e6; background: #fafbff; }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn-primary { background: var(--blue); border-color: var(--blue); color: #fff; }
.btn-primary:hover:not(:disabled) { background: var(--blue-dark); border-color: var(--blue-dark); }
.btn-danger { background: var(--red); border-color: var(--red); color: #fff; }
.btn-danger:hover:not(:disabled) { background: #c42822; border-color: #c42822; }
.btn-ghost { border-color: transparent; background: transparent; color: var(--text-2); }
.btn-ghost:hover:not(:disabled) { background: var(--line-soft); }
.btn-sm { padding: 5px 11px; font-size: 13px; }
.btn-block { width: 100%; }

input[type=text], input[type=password], input[type=date], input[type=search], textarea, select {
  font-family: inherit;
  font-size: 14px;
  padding: 8px 11px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: #fff;
  color: var(--text);
  outline: none;
  transition: border-color .12s, box-shadow .12s;
  width: 100%;
}
input:focus, textarea:focus, select:focus {
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(30, 94, 255, .12);
}
textarea { resize: vertical; min-height: 76px; }

.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}
.badge-blue   { background: var(--blue-soft);   color: var(--blue); }
.badge-red    { background: var(--red-soft);    color: var(--red); }
.badge-orange { background: var(--orange-soft); color: var(--orange); }
.badge-green  { background: var(--green-soft);  color: var(--green); }
.badge-gray   { background: var(--line-soft);   color: var(--text-3); }

.count-badge {
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 10px;
  background: var(--red);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  line-height: 20px;
  text-align: center;
}
.count-badge.zero { background: var(--line); color: var(--text-3); }

/* 提示条 */
.banner {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 11px 14px;
  margin: 0 22px 14px;
  border-radius: var(--radius-sm);
  font-size: 13.5px;
  line-height: 1.6;
}
.banner-warn  { background: var(--orange-soft); color: #8a4a06; border: 1px solid #f2d9b5; }
.banner-error { background: var(--red-soft);    color: #96211c; border: 1px solid #f5c9c6; }
.banner-info  { background: var(--blue-soft);   color: #1544b8; border: 1px solid #c9d8ff; }
.banner b { font-weight: 700; }

/* 统计卡片 */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px;
  margin-bottom: 16px;
}
.stat {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 15px 17px;
  box-shadow: var(--shadow);
}
.stat .label { color: var(--text-2); font-size: 13px; }
.stat .value {
  font-size: 25px;
  font-weight: 700;
  margin-top: 4px;
  letter-spacing: -.4px;
  font-variant-numeric: tabular-nums;
}
.stat .value .unit { font-size: 13px; font-weight: 500; color: var(--text-3); margin-left: 4px; }

/* 横向条形图（纯 CSS，不引图表库） */
.bar-row { display: flex; align-items: center; gap: 10px; margin-bottom: 11px; }
.bar-row .bar-label { width: 82px; flex: 0 0 82px; font-size: 13px; color: var(--text-2); }
.bar-row .bar-track {
  flex: 1;
  height: 20px;
  background: var(--line-soft);
  border-radius: 5px;
  overflow: hidden;
}
.bar-row .bar-fill {
  height: 100%;
  background: linear-gradient(90deg, #4b83ff, var(--blue));
  border-radius: 5px;
  min-width: 2px;
  transition: width .4s ease;
}
.bar-row .bar-value {
  width: 46px;
  flex: 0 0 46px;
  text-align: right;
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------------
 * 登录页
 * ------------------------------------------------------------------------*/

.login-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: linear-gradient(150deg, #eef3ff 0%, #f6f8fd 45%, #eaf3ff 100%);
}
.login-card {
  width: 100%;
  max-width: 384px;
  background: var(--card);
  border-radius: 16px;
  box-shadow: var(--shadow-lg);
  padding: 32px 30px 26px;
}
.login-head { text-align: center; margin-bottom: 22px; }
.login-head h1 { margin: 12px 0 4px; font-size: 20px; font-weight: 700; }
.login-head p { margin: 0; color: var(--text-3); font-size: 13px; }
.field { margin-bottom: 14px; }
.field label {
  display: block;
  margin-bottom: 6px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-2);
}
.login-err {
  background: var(--red-soft);
  color: #96211c;
  border: 1px solid #f5c9c6;
  border-radius: var(--radius-sm);
  padding: 9px 12px;
  font-size: 13px;
  margin-bottom: 14px;
}
.login-hint {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px dashed var(--line);
  font-size: 12.5px;
  color: var(--text-3);
  line-height: 1.75;
}
.login-hint code {
  background: var(--line-soft);
  padding: 1px 5px;
  border-radius: 4px;
  font-size: 12px;
  color: var(--text-2);
}

/* ---------------------------------------------------------------------------
 * 首页流程卡片
 * ------------------------------------------------------------------------*/

.hero {
  display: flex;
  align-items: center;
  gap: 20px;
  background: linear-gradient(120deg, var(--blue) 0%, #3f7bff 100%);
  color: #fff;
  border-radius: var(--radius);
  padding: 22px 24px;
  margin-bottom: 18px;
  box-shadow: 0 6px 22px rgba(30, 94, 255, .28);
}
.hero .hero-num {
  font-size: 46px;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -2px;
  font-variant-numeric: tabular-nums;
}
.hero .hero-text { flex: 1; min-width: 0; }
.hero .hero-title { font-size: 16px; font-weight: 650; }
.hero .hero-sub { font-size: 13px; opacity: .85; margin-top: 3px; }

.flow-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 14px;
}
.flow-card {
  background: var(--card);
  border: 1px solid var(--line);
  border-left: 4px solid var(--blue);
  border-radius: var(--radius);
  padding: 17px 18px;
  cursor: pointer;
  box-shadow: var(--shadow);
  transition: transform .14s, box-shadow .14s;
  text-align: left;
  width: 100%;
  font-family: inherit;
}
.flow-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }
.flow-card .fc-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 8px;
}
.flow-card .fc-name { font-size: 16px; font-weight: 700; }
.flow-card .fc-full { font-size: 12.5px; color: var(--text-3); margin-bottom: 12px; min-height: 19px; }
.flow-card .fc-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding-top: 11px;
  border-top: 1px solid var(--line-soft);
}
.flow-card .fc-pending { display: flex; align-items: baseline; gap: 5px; }
.flow-card .fc-pending .n {
  font-size: 23px;
  font-weight: 800;
  color: var(--blue);
  font-variant-numeric: tabular-nums;
}
.flow-card .fc-pending .u { font-size: 12.5px; color: var(--text-3); }
.flow-card.readonly { border-left-color: var(--text-3); }
.flow-card.readonly .fc-pending .n { color: var(--text-3); }

/* ---------------------------------------------------------------------------
 * 工具条（搜索 / 筛选）
 * ------------------------------------------------------------------------*/

.toolbar {
  display: flex;
  align-items: center;
  gap: 9px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}
.toolbar .grow { flex: 1; min-width: 150px; }
.segmented {
  display: inline-flex;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: #fff;
}
.segmented button {
  padding: 7px 13px;
  border: none;
  background: none;
  color: var(--text-2);
  cursor: pointer;
  font-weight: 500;
}
.segmented button + button { border-left: 1px solid var(--line); }
.segmented button.active { background: var(--blue); color: #fff; font-weight: 600; }

/* ---------------------------------------------------------------------------
 * 表格（宽屏）
 * ------------------------------------------------------------------------*/

.table-wrap {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow-x: auto;
}
table.data {
  border-collapse: collapse;
  width: 100%;
  min-width: 1420px;   /* 字段多，窄屏靠横向滚动，不挤成一团 */
  font-size: 13px;
}
table.data th, table.data td {
  padding: 10px 12px;
  text-align: left;
  border-bottom: 1px solid var(--line-soft);
  white-space: nowrap;
}
table.data thead th {
  background: #f8faff;
  color: var(--text-2);
  font-weight: 650;
  font-size: 12.5px;
  position: sticky;
  top: 0;
  border-bottom: 1px solid var(--line);
  z-index: 1;
}
table.data tbody tr:hover { background: #fafbff; }
table.data tbody tr { cursor: pointer; }
table.data td.num { text-align: right; font-variant-numeric: tabular-nums; }
table.data .col-billno { font-weight: 650; color: var(--blue); }
table.data .sticky-right {
  position: sticky;
  right: 0;
  background: var(--card);
  box-shadow: -6px 0 8px -6px rgba(20, 30, 60, .14);
}
table.data tbody tr:hover .sticky-right { background: #fafbff; }

.text-red { color: var(--red); font-weight: 650; }
.text-orange { color: var(--orange); font-weight: 650; }
.text-primary { color: var(--blue); }
.text-muted { color: var(--text-3); }
.text-right { text-align: right; }
.nowrap { white-space: nowrap; }

/* 手机卡片式列表 */
.bill-cards { display: none; }
.bill-card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 13px 15px;
  margin-bottom: 11px;
  box-shadow: var(--shadow);
  cursor: pointer;
}
.bill-card .bc-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 7px;
}
.bill-card .bc-no { font-weight: 700; color: var(--blue); font-size: 14.5px; }
.bill-card .bc-cust { font-size: 13.5px; margin-bottom: 8px; }
.bill-card .bc-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 5px 12px;
  font-size: 12.5px;
  padding-top: 8px;
  border-top: 1px solid var(--line-soft);
}
.bill-card .bc-grid .k { color: var(--text-3); }
.bill-card .bc-grid .v { font-weight: 600; font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------------------
 * 分页
 * ------------------------------------------------------------------------*/

.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: 12px 2px 0;
  font-size: 13px;
  color: var(--text-2);
}
.pager .pager-btns { display: flex; align-items: center; gap: 7px; }

/* ---------------------------------------------------------------------------
 * 详情页
 * ------------------------------------------------------------------------*/

.detail-head { display: flex; align-items: flex-start; gap: 14px; flex-wrap: wrap; }
.detail-head .dh-main { flex: 1; min-width: 220px; }
.detail-head .dh-no { font-size: 19px; font-weight: 700; }
.detail-head .dh-sub { color: var(--text-3); font-size: 13px; margin-top: 2px; }

.field-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.field-cell { background: var(--card); padding: 10px 13px; }
.field-cell .fk { font-size: 12px; color: var(--text-3); margin-bottom: 2px; }
.field-cell .fv {
  font-size: 14px;
  font-weight: 600;
  word-break: break-all;
  font-variant-numeric: tabular-nums;
}

/**
 * 底部操作条。
 *
 * 布局拆成「提示文字」+「按钮组」两块，并且提示文字不存在时不留空占位 ——
 * 之前的写法给提示元素固定了 min-width:160px，在 390px 的手机上会把
 * 「审核通过」按钮直接顶出屏幕外，用户只看得见「驳回」。
 */
.detail-actions {
  position: sticky;
  bottom: 0;
  background: rgba(255, 255, 255, .94);
  backdrop-filter: blur(8px);
  border-top: 1px solid var(--line);
  padding: 12px 22px;
  margin: 20px -22px -34px;
  display: flex;
  align-items: center;
  gap: 10px;
  z-index: 15;
}
.detail-actions .da-hint { flex: 1; min-width: 0; font-size: 13px; }
.detail-actions .da-btns { display: flex; gap: 9px; margin-left: auto; }

/* 弹窗 */
.modal-mask {
  position: fixed;
  inset: 0;
  background: rgba(18, 24, 40, .45);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px;
  z-index: 50;
}
.modal {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  width: 100%;
  max-width: 440px;
  padding: 22px;
}
.modal h3 { margin: 0 0 6px; font-size: 16.5px; }
.modal .modal-sub { color: var(--text-3); font-size: 13px; margin-bottom: 14px; }
.modal-btns { display: flex; justify-content: flex-end; gap: 9px; margin-top: 16px; }

/* Toast */
.toasts {
  position: fixed;
  top: 16px;
  right: 16px;
  display: flex;
  flex-direction: column;
  gap: 9px;
  z-index: 80;
  pointer-events: none;
}
.toast {
  background: #232b3d;
  color: #fff;
  padding: 10px 15px;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  font-size: 13.5px;
  max-width: 340px;
  animation: toast-in .2s ease;
}
.toast.ok { background: #0f8a45; }
.toast.err { background: #c42822; }
@keyframes toast-in { from { opacity: 0; transform: translateX(18px); } }

/* 空状态 / 加载 */
.empty {
  text-align: center;
  padding: 48px 20px;
  color: var(--text-3);
}
.empty svg { opacity: .32; margin-bottom: 10px; }
.empty .e-title { font-size: 15px; color: var(--text-2); font-weight: 600; margin-bottom: 4px; }
.empty .e-sub { font-size: 13px; }

.skeleton {
  background: linear-gradient(90deg, #eef1f7 25%, #f6f8fc 50%, #eef1f7 75%);
  background-size: 200% 100%;
  animation: sk 1.2s ease-in-out infinite;
  border-radius: 6px;
}
@keyframes sk { to { background-position: -200% 0; } }
.sk-line { height: 14px; margin-bottom: 10px; }

/* ---------------------------------------------------------------------------
 * 响应式：窄屏（手机）
 * ------------------------------------------------------------------------*/

@media (max-width: 900px) {
  .sidebar { display: none; }
  .bottomnav { display: flex; }

  .main { padding-bottom: calc(var(--bottomnav-h) + 8px); }
  .view { padding: 14px 13px 20px; }
  .banner { margin: 0 13px 12px; }

  .topbar { padding: 11px 13px; }
  .topbar h1 { font-size: 15.5px; }
  .topbar .sub { display: none; }

  /*
   * ★ 表格换成卡片 —— 但【只对待审列表页】★
   *
   * 这条原来是全局的 `.table-wrap { display:none }`，后果是：
   * 手机上【所有】用 .table-wrap 的表格全部消失。
   * 单据详情页的「单据明细」就是这么中招的 ——
   * 标题明明写着「单据明细（1 行）」，下面却是一片空白，
   * 看起来像这条单没有明细，其实是表格被隐藏了。
   *
   * 现在收窄到待审列表页内部的 .list-scroll 里；
   * 其它页面的表格照常显示（窄屏靠 .table-wrap 自己的横向滚动）。
   */
  .flow-page .list-scroll .table-wrap { display: none; }
  .bill-cards { display: block; }

  .hero { padding: 18px; gap: 14px; }
  .hero .hero-num { font-size: 38px; }

  .flow-grid { grid-template-columns: 1fr; }

  .field-grid { grid-template-columns: 1fr 1fr; }
  .field-cell { padding: 9px 11px; }
  .field-cell .fv { font-size: 13.5px; }

  .detail-actions {
    margin: 16px -13px -20px;
    padding: 11px 13px;
    flex-wrap: wrap;
    /**
     * ★ 手机端必须把吸附位置抬高到「底部导航之上」。
     *
     * position:sticky 的 bottom 是相对【滚动视口】算的，不是相对父元素，
     * 所以父容器上那点 padding-bottom 根本挡不住它 —— 不抬的话
     * 整个操作条会正好压在底部导航下面，用户完全点不到「审核通过」。
     */
    bottom: calc(var(--bottomnav-h) + env(safe-area-inset-bottom, 0px));
  }
  /* 手机端：提示占一整行，两个按钮平分下一行，谁都不会被挤出屏幕 */
  .detail-actions .da-hint { flex: 1 1 100%; }
  .detail-actions .da-btns { flex: 1 1 100%; }
  .detail-actions .da-btns .btn { flex: 1; }

  .stat-grid { grid-template-columns: 1fr 1fr; gap: 10px; }
  .stat { padding: 12px 13px; }
  .stat .value { font-size: 21px; }

  .toasts { left: 13px; right: 13px; top: 10px; }
  .toast { max-width: none; }
}

@media (max-width: 420px) {
  .stat-grid { grid-template-columns: 1fr; }
}

/* 只有到非常窄的屏幕才把字段改成单列；390px 的常见手机保持两列，页面短一半 */
@media (max-width: 360px) {
  .field-grid { grid-template-columns: 1fr; }
}

/* 打印：把侧边栏和按钮藏掉，只留内容 */
@media print {
  .sidebar, .bottomnav, .topbar-actions, .detail-actions, .toasts { display: none !important; }
  .main { padding: 0; }
  .card, .table-wrap { box-shadow: none; }
}

/* ===========================================================================
 * 待审列表：主从布局（列表 + 下方明细面板）+ 批量审核
 *
 * 这一段的类名统一用 dp- 前缀（detail panel），
 * 和详情页那套 .card / .field-grid 区分开 —— 详情页是独立页面，样式不要互相影响。
 * ========================================================================*/

/* 页面头：返回按钮 + 流程名 */
.page-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}
.page-head .page-title { font-size: 17px; font-weight: 700; }

/* 工具条右侧的「已选 N 条 / 进度」提示区 */
.toolbar-status {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  font-size: 13px;
}
.toolbar-status .sel-count { font-weight: 600; color: var(--text-2); }
.toolbar-status .sel-count.on { color: var(--blue); }
.toolbar-status .bulk-progress {
  color: var(--blue);
  font-weight: 650;
  animation: pulse-soft 1.1s ease-in-out infinite;
}
@keyframes pulse-soft { 50% { opacity: .45; } }

/* 勾选框（表格行 / 表头 / 手机卡片共用） */
.ck-wrap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 4px;
  cursor: pointer;
}
.ck-wrap input[type=checkbox] {
  width: 16px;
  height: 16px;
  margin: 0;
  accent-color: var(--blue);
  cursor: pointer;
}
/* 勾选列窄一点，居中放勾选框 */
table.data th.col-check,
table.data td.col-check {
  width: 42px;
  text-align: center;
  padding-left: 10px;
  padding-right: 6px;
}

/**
 * 当前正在查看明细的那一行。
 *
 * 背景色要和 hover 区分开，否则鼠标一移开用户就找不到自己在看哪张单了。
 */
table.data tbody tr.row-active,
table.data tbody tr.row-active:hover { background: var(--blue-soft); }
table.data tbody tr.row-active .sticky-right { background: var(--blue-soft); }
.bill-card.row-active {
  border-color: var(--blue);
  box-shadow: 0 0 0 2px rgba(30, 94, 255, .16), var(--shadow);
}
.bill-card .bc-top .ck-wrap { margin-left: -4px; }

/* 明细面板 */
.detail-panel {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 14px 16px 16px;
  margin-top: 18px;
}
/* 还没选单据时的占位：虚线框，明确表示「这里以后会有东西」 */
.detail-panel-idle { border-style: dashed; box-shadow: none; }
.dp-idle {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 22px;
  color: var(--text-3);
  font-size: 13.5px;
}
.dp-idle svg { opacity: .5; }

.dp-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.dp-head .dp-main { min-width: 180px; }
.dp-head .dp-no { font-size: 16.5px; font-weight: 700; color: var(--text); }
.dp-head .dp-sub { font-size: 13px; color: var(--text-2); margin-top: 2px; }
.dp-head .dp-meta {
  display: flex;
  align-items: center;
  gap: 9px;
  flex-wrap: wrap;
}
.dp-head .dp-amt { font-size: 13.5px; }
.dp-head .dp-amt .k { color: var(--text-3); }
.dp-head .dp-amt .v { font-weight: 700; font-variant-numeric: tabular-nums; }

/* 明细面板里的两个标签页 */
.dp-tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--line);
  margin: 12px 0 12px;
}
.dp-tab {
  border: none;
  background: none;
  padding: 8px 12px;
  margin-bottom: -1px;
  cursor: pointer;
  color: var(--text-2);
  font-weight: 600;
  border-bottom: 2px solid transparent;
}
.dp-tab:hover { color: var(--text); }
.dp-tab.active { color: var(--blue); border-bottom-color: var(--blue); }

/**
 * 明细表格的滚动容器。
 *
 * 面板必须能独立滚动，不能把整页撑长 —— 所以在面板内部限制高度再 overflow。
 * 注意这里没有复用 .table-wrap：那个类在 ≤900px 会被整体隐藏（列表要换成卡片），
 * 明细面板里的表格在手机上仍然要能横向滚动，所以用独立的类。
 */
.dp-scroll {
  max-height: 320px;
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: #fff;
}
table.data.dp-table { min-width: 0; }
table.data.dp-table-goods { min-width: 1180px; }
table.data.dp-table-debt { min-width: 980px; }
.dp-summary {
  font-size: 13.5px;
  color: var(--text-2);
  margin-bottom: 10px;
  line-height: 1.7;
}
.dp-error {
  padding: 16px;
  font-size: 13.5px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--red-soft);
}

/* 批量审核确认框 / 失败结果框 */
.bulk-list {
  background: var(--line-soft);
  border-radius: var(--radius-sm);
  padding: 9px 11px;
  font-size: 13px;
  line-height: 1.75;
  word-break: break-all;
}
.bulk-warn {
  margin-top: 9px;
  padding: 8px 11px;
  border-radius: var(--radius-sm);
  background: var(--orange-soft);
  border: 1px solid #f2d9b5;
  color: #8a4a06;
  font-size: 12.5px;
  line-height: 1.7;
}
.fail-list { font-size: 13px; }
.fail-list .fail-head { color: var(--text-2); margin-bottom: 6px; }
.fail-items { max-height: 240px; overflow-y: auto; }
.fail-item {
  padding: 7px 0;
  border-top: 1px solid var(--line-soft);
}
.fail-item .fi-no { font-weight: 700; color: var(--red); }
.fail-item .fi-why { font-size: 12.5px; color: var(--text-2); line-height: 1.6; }

/* 窄屏：明细面板留白收紧，表头信息换行显示 */
@media (max-width: 900px) {
  .detail-panel { padding: 12px 12px 14px; margin-top: 14px; }
  .dp-head .dp-meta { width: 100%; justify-content: flex-start; }
  .dp-scroll { max-height: 300px; }
  .dp-tabs { margin: 10px 0 10px; }
  .toolbar-status { flex: 1 1 100%; }
  table.data th.col-check,
  table.data td.col-check { width: 40px; padding-left: 6px; padding-right: 4px; }
}

/* ===========================================================================
 *  待审列表页：整页不滚动，只有列表区域滚，明细面板常驻下方
 *
 *  【为什么这么改】
 *
 *  原来的样子：整页滚动。一页 20 行，屏幕放不下，
 *  点开某张单的明细要往下拉才能看见；
 *  等拉到下面，上面的列表已经滚出视野，根本想不起来这是哪张单的明细。
 *  对账的时候要反复上下翻，很累。
 *
 *  【现在的做法】
 *
 *  把这一页变成「固定高度 + 内部分区」：
 *
 *      ┌ 标题 ────────────────────┐  固定
 *      ├ 工具条 ──────────────────┤  固定
 *      ├ 列表 ───── ← 固定 8 行 ──┤  ★ 高度锁死约 8 行，超出靠它自己滚
 *      ├ 分页 ────────────────────┤  固定
 *      └ 明细面板 ── ← 占剩下的 ──┘  ★ 吃掉列表下面的全部剩余高度
 *
 *  于是无论一页 20 行还是 200 行，明细面板永远在视野里，
 *  点哪一行、明细就在正下方，而且屏幕越高明细能看到的行越多。
 *
 *  ★ 关键是把「固定」加在【列表】上，不是加在明细上 ★
 *     如果反过来把明细设成固定 40%，屏幕一高列表就露十几二十行，
 *     等于没框住，又会回到「一屏放不下、得上下翻」的老问题。
 * =========================================================================*/

/* 这一页的 #view 要变成弹性列容器，子元素才能按比例分高度 */
.view-flow {
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

.flow-page {
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1 1 auto;
  min-height: 0; /* 关键：不加这句，flex 子元素不会收缩，内层滚动条出不来 */
}

.flow-page .page-head,
.flow-page .toolbar,
.flow-page .pager {
  flex: 0 0 auto; /* 这几块高度固定，不参与伸缩 */
}

/* 空的占位块（比如没有字段警告时的 banner）不要白占间距 */
.flow-page > div:empty { display: none; }

/* ---- 列表滚动区：高度锁死在「约 8 行」，超出自己滚 ---- */
.flow-page .list-scroll {
  /*
   * 高度怎么来的：
   *   表头  padding 10+10 + 字号 12.5×1.6 ≈ 40px
   *   每行  padding 10+10 + 字号 13×1.6   ≈ 41px
   *   8 行 + 表头 = 40 + 8×41 ≈ 368，加上边框取整 376
   * 所以这里定 376px —— 刚好露 8 行，第 9 行开始要拖滚动条。
   *
   * 想改成别的行数，改这个数就行（每多一行 +41px）。
   */
  flex: 0 1 auto;      /* 0 = 不主动变大；1 = 屏幕实在太矮时允许被压缩 */
  max-height: 376px;
  min-height: 0;
  overflow: auto;      /* 超出 8 行的部分在这里滚 */
  border-radius: var(--radius);
}

/*
 * .table-wrap 自己原本带 overflow-x:auto。
 * 两层滚动条叠在一起很难用，而且纵向 sticky 表头会失效
 * （一个容器只要某个方向是 auto，另一个方向就没法保持 visible）。
 * 所以把滚动统一交给外层 .list-scroll。
 */
.flow-page .list-scroll .table-wrap {
  overflow: visible;
  box-shadow: none;
}

/* ---- 明细面板：吃掉列表下面的全部剩余高度，内部自己滚 ---- */
.flow-page .detail-panel {
  flex: 1 1 auto;      /* ★ 关键：明细是「占剩下的」，不是「固定多少」 */
  min-height: 0;
  max-height: none;
  /* 基础样式里有 margin-top:18px，这一页的间距已经由 gap 统一管了，去掉免得叠两层 */
  margin-top: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/*
 * 面板内部的伸缩链：.detail-panel → .dp-pane → .dp-scroll
 * 中间只要断一环，内层就撑不出滚动条，内容会被 overflow:hidden 直接切掉。
 * 所以这两层都必须 flex + min-height:0。
 */
.flow-page .dp-pane {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/* 面板里的明细表格跟着面板高度伸缩，不要再由它自己定高 */
.flow-page .dp-scroll {
  flex: 1 1 auto;
  min-height: 0;
  max-height: none;
  overflow: auto;
}

/* ---------------------------------------------------------------------------
 *  手机卡片：16 个字段全列之后的收尾处理
 *
 *  卡片里是两列网格，格子默认 min-width:auto，
 *  遇到「订单金额 27,594.00」这种长值会把卡片撑破、导致横向溢出。
 *  这里允许格子里换行。
 * ------------------------------------------------------------------------*/
.bill-card .bc-grid > div {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------------------
 *  窄屏（手机）不做固定分区
 *
 *  手机屏幕本来就小，硬切成"上面列表 + 下面明细"两半，
 *  两边都只剩一百多像素，谁也看不了。窄屏仍走原来的整页滚动。
 *  而且窄屏用的是卡片式列表，一屏本来也放不下几行。
 * ------------------------------------------------------------------------*/
/* 关闭按钮默认不显示 —— 宽屏的明细不是浮层，点别的行就切走了，不需要关 */
.dp-close { display: none; }

/* 浮层遮罩：默认不显示（只有窄屏浮层打开时才有） */
.sheet-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgba(16, 24, 40, .38);
}

/* ---------------------------------------------------------------------------
 *  窄屏：明细改成「底部浮层」（bottom sheet）
 *
 *  【要解决的问题】
 *  原来窄屏的明细面板是跟在【整张列表后面】的一块内容。
 *  一页 20 张卡片，点第 12 张，得往下穿过剩下 8 张才看得到明细；
 *  等滚下去，又忘了刚才点的是哪一行。列表越长越难受。
 *
 *  【现在的做法】
 *  点任意一行，明细从屏幕底部滑上来、盖住列表（列表位置一点不动），
 *  点 ✕ 或点遮罩就收回去。
 *
 *  宽屏完全不受影响：那边列表固定 8 行，明细本来就是常驻在下方的一块。
 * ------------------------------------------------------------------------*/
@media (max-width: 900px) {
  .view-flow { display: block; overflow: visible; }
  .flow-page { display: block; }
  /* 手机上不用锁 8 行：窄屏用的是卡片式列表，一屏本来也放不下几行，
     再锁高度等于平白多一层滚动条 */
  .flow-page .list-scroll { overflow: visible; max-height: none; }

  /* ---- 明细容器：固定在屏幕底部，靠 transform 滑入滑出 ---- */
  .flow-page .detail-slot {
    position: fixed;
    left: 0;
    right: 0;
    /* 贴在底部导航栏上沿，并避开 iPhone 的底部安全区 */
    bottom: calc(var(--bottomnav-h) + env(safe-area-inset-bottom));
    z-index: 41;
    max-height: 78vh;
    display: flex;
    flex-direction: column;
    /* 收起时整体推到屏幕外；打开时滑回来 */
    transform: translateY(110%);
    transition: transform .24s cubic-bezier(.32, .72, 0, 1);
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -10px 34px rgba(16, 24, 40, .24);
    overflow: hidden;
  }

  /*
   * 收起状态下必须让它「不吃点击」。
   * 否则这个盖住半屏的透明容器会拦住下面列表的点击 ——
   * 表现就是"卡片怎么点都没反应"，而看起来一切正常，极难排查。
   */
  .flow-page .detail-slot:not(.is-open) { pointer-events: none; }
  .flow-page .detail-slot.is-open {
    transform: translateY(0);
    pointer-events: auto;
  }

  /* ---- 浮层里的面板 ---- */
  .flow-page .detail-panel {
    height: auto;
    min-height: 0;
    max-height: none;
    margin: 0;
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border-radius: 16px 16px 0 0;
    border-bottom: 0;
    box-shadow: none;
  }
  .flow-page .dp-pane {
    display: flex;
    flex-direction: column;
    flex: 0 0 auto;
    min-height: 0;
  }

  /*
   * ★ 明细表格只露 4 行，其余靠滚动条 ★
   *
   * 高度是算出来的：
   *   表头  padding 10+10 + 字号 12.5×1.6 + 下边框 1 ≈  41px
   *   每行  padding 10+10 + 字号 13×1.6   + 下边框 1 ≈  42px
   *   4 行 + 表头 + 上下边框 2 = 41 + 4×42 + 2 = 211
   * 取 214px 留 3px 余量 —— 宁可多露一点点，也不要把第 4 行切掉半个字。
   * （写 206 就正好会把第 4 行切掉 2px，看着像"最后一行显示不全"。）
   *
   * 想改行数：每多一行加 42px。
   *   3 行 → 172px    5 行 → 256px    6 行 → 298px
   *
   * 这里刻意【不用】flex 伸缩，而是老老实实给一个 max-height + overflow:auto：
   * 纯块级元素的「定高 + 溢出滚动」是浏览器最稳的一档行为；
   * 而 flex 嵌套里只要中间少一环 min-height:0，内层就撑不出滚动条、
   * 内容被 overflow:hidden 直接切掉 —— 之前就是这么翻车的。
   */
  .flow-page .dp-scroll {
    flex: 0 0 auto;
    min-height: 0;
    max-height: 214px;
    overflow: auto;
    -webkit-overflow-scrolling: touch; /* iOS 上滚动手感更跟手 */
  }

  /* 顶部那道小横杠：提示"这是一块可以收起的浮层" */
  .flow-page .detail-panel::before {
    content: '';
    display: block;
    flex: 0 0 auto;
    width: 42px;
    height: 4px;
    margin: 0 auto 8px;
    border-radius: 2px;
    background: var(--line);
  }

  /* 关闭按钮和遮罩只在窄屏生效 */
  .dp-close { display: inline-flex; }
  .sheet-backdrop.is-open { display: block; }
}

/* ===========================================================================
 *  跟随式「审核」浮动按钮（窄屏专用）
 *
 *  【为什么要有】
 *
 *  手机上单据一多，勾完某张单得一路划回列表顶部才能点工具条里的「审核」；
 *  划回去的过程里还容易忘了自己勾的是哪几条。
 *
 *  【怎么表现】
 *
 *  宽屏：一直显示。因为宽屏列表是固定 8 行、工具条始终在视野里，
 *        再浮一个按钮纯属碍事，所以默认 display:none。
 *  窄屏：勾了单据才出现（JS 控制 hidden 属性），
 *        显示「审核 N 条」，审核中实时显示「正在审核 3 / 10 …」。
 * =========================================================================*/
.flow-fab {
  display: none;
  position: fixed;
  right: 14px;
  /* 让开底部导航栏（它高 var(--bottomnav-h) = 58px）和 iPhone 的底部安全区 */
  bottom: calc(var(--bottomnav-h) + 14px + env(safe-area-inset-bottom));
  z-index: 31; /* 比 .bottomnav 的 z-index:30 高一层，别被它盖住 */
  align-items: center;
  gap: 7px;
  padding: 12px 20px;
  border: 0;
  border-radius: 999px;
  background: var(--blue);
  color: #fff;
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 8px 22px rgba(30, 94, 255, .4);
  transition: transform .12s ease, box-shadow .12s ease;
}

.flow-fab:active { transform: scale(.96); }

.flow-fab:disabled {
  opacity: .62;
  cursor: default;
  box-shadow: 0 6px 16px rgba(30, 94, 255, .25);
}

.flow-fab svg { flex: 0 0 auto; }

/*
 * 只在窄屏、并且勾了单据（JS 把 hidden 去掉）时显示。
 * 注意全局有 [hidden]{display:none!important}，所以这里必须用 :not([hidden])，
 * 否则这条规则会把 hidden 覆盖掉、按钮一直显示。
 */
@media (max-width: 900px) {
  .flow-fab:not([hidden]) { display: inline-flex; }
}
