/* ==========================================================================
   *毕节卓高*订单系统* · 网页版（H5）
   视觉对齐微信小程序：主色 #07c160 / 底色 #f5f6f8 / 白底圆角卡片 / 底部弹层
   说明：尺寸用 px（小程序里的 rpx ÷ 2 即为 px），在 375px 宽的手机上与原版等宽。
   ========================================================================== */

:root {
  --green: #07c160;
  --green-d: #06ad56;
  --green-l: #eaf9f0;
  --red: #fa5151;
  --bg: #f5f6f8;
  --card: #ffffff;
  --line: #f0f1f3;
  --line2: #e6e8eb;
  --t1: #222222;
  --t2: #333333;
  --t3: #666666;
  --t4: #999999;
  --t5: #bbbbbb;
  --radius: 10px;
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
}

* {
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
}

html {
  height: 100%;
  /* 🔴🔴 第一百一十四批（2026-10-09 用户需求）：「手机上整页能被左右拉动，左边第一列被切掉」。
     根因：页面里只要**任何**元素比视口宽（宽表格 / 长串），iOS 就会给**整页**一个横向可滚动区，
     手指一拖整页跟着跑、露出底色，第一列被切到屏幕外。桌面 Chrome 不这样，所以只在手机上出现。
     修法：把「视口」的横向滚动**整条关掉** —— 手指再怎么拖，整页也不再左右移动。
     ⚠️ 只关「整页」这一层：`overflow-x:hidden` 会让 y 轴自动算成 auto（上下照常滚），
        而页面内真正的横滚容器（.tw 表格）是**自己那层**的滚动，完全不受影响。
     🔴 可翻转点：删掉下面两行即恢复「整页可左右拖」。 */
  overflow-x: hidden;
  overscroll-behavior-x: none;   /* 顺带禁掉 iOS 横向的橡皮筋回弹 */
  /* 禁止缩放（浏览器层）。两层是有意的降级写法：
     · manipulation —— 禁「双击缩放」，所有浏览器都认（顺带消掉 300ms 点击延迟）
     · pan-x pan-y  —— 连「双指缩放」一起禁掉；不认这条的浏览器会保留上一行
     只允许平移(pan)，所以页面里横向表格的左右滑动不受影响，缩放则永不发生。 */
  touch-action: manipulation;
  touch-action: pan-x pan-y;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100%;
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue",
    "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
  font-size: 14px;
  line-height: 1.45;
  color: var(--t2);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  overscroll-behavior-y: none;
  /* 与 html 同一策略，兜底不沿继承链解析 touch-action 的老 WebView */
  touch-action: manipulation;
  touch-action: pan-x pan-y;
}

input,
select,
textarea,
button {
  margin: 0;
  font-family: inherit;
  font-size: inherit;
  color: inherit;
  background: none;
  border: 0;
  border-radius: 0;
  outline: none;
  -webkit-appearance: none;
  appearance: none;
}

input::-webkit-input-placeholder,
textarea::-webkit-input-placeholder {
  color: var(--t5);
}

/* ---------- 顶部导航 ---------- */
.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  height: calc(48px + var(--safe-t));
  padding: var(--safe-t) 6px 0;
  background: #ffffff;
  border-bottom: 1px solid var(--line);
}

.nav__side {
  flex: none;
  min-width: 62px;
  height: 48px;
  display: flex;
  align-items: center;
  padding: 0 6px;
  font-size: 15px;
  color: var(--t2);
}

.nav__side--r {
  justify-content: flex-end;
  color: var(--green);
}

.nav__back {
  display: flex;
  align-items: center;
  font-size: 24px;
  line-height: 1;
  padding: 0 4px 2px 0;
}

.nav__title {
  flex: 1;
  text-align: center;
  font-size: 16px;
  font-weight: 600;
  color: var(--t1);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.nav__btn {
  padding: 6px 10px;
  font-size: 14px;
  color: var(--green);
  border-radius: 6px;
}

.nav__btn:active {
  background: var(--green-l);
}

/* ---------- 页面容器 ---------- */
.screen {
  padding: calc(48px + var(--safe-t)) 0 calc(24px + var(--safe-b));
  min-height: 100vh;
  /* 🆕 第一百一十四批：内容区再加一道 —— 任何比视口宽的东西只在这里被裁掉，
     绝不外溢成「整页横向可拖」。
     ⚠️ 用 clip 而不是 hidden：clip **不会**把另一轴改成 auto，所以不会凭空造出
        一个纵向滚动容器去干扰页面本身的上下滚动；老浏览器不认就直接忽略（上层 html 已兜住）。 */
  overflow-x: clip;
}

.boot {
  padding: 80px 0;
  text-align: center;
  color: var(--t4);
}

.boot__dot {
  width: 26px;
  height: 26px;
  margin: 0 auto 16px;
  border: 3px solid #dfe1e5;
  border-top-color: var(--green);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* ---------- 首页 ---------- */
.home {
  padding: 16px;
}

/* 🆕 第317批：首页底部备案号（工信部要求：首页底部标明备案编号并链接至备案系统）
   ⚠️ 只新增这一组类，不动文件开头 70~84 行的 reset（铁律 5）。 */
.home__icp {
  padding: 18px 0 10px;
  text-align: center;
  font-size: 12px;
  line-height: 1.6;
  color: var(--t4);
  word-break: break-all;
}

.home__icp a {
  color: var(--t4);
  text-decoration: none;
}

.home__icp a:hover {
  color: var(--t3);
  text-decoration: underline;
}

/* 财务概览卡片：固定 2 列（2026-09-28 用户要求：当年销售额要与当年利润同一行） */
.kpis {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin-bottom: 18px;
}

.kpi {
  min-width: 0;
  border-radius: 12px;
  padding: 14px 12px;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.04);
}

.kpi--asset {
  background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%);
}

.kpi--unrecv {
  background: linear-gradient(135deg, #fff3e0 0%, #ffe0b2 100%);
}

.kpi--profit {
  background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%);
}

.kpi__label {
  font-size: 12px;
  color: #555555;
}

.kpi__value {
  margin-top: 7px;
  font-size: 17px;
  font-weight: 700;
  color: #1f1f1f;
  word-break: break-all;
}

.kpi--sales {
  background: linear-gradient(135deg, #ede7f6 0%, #d1c4e9 100%);
}

/* 第二十三批：年度已收款卡（与「年度未收款」的暖色区分开） */
.kpi--received {
  background: linear-gradient(135deg, #e0f2f1 0%, #b2dfdb 100%);
}

/* 第十六批需求 B-1：业务员「当年销售额排名」卡 */
.kpi--rank {
  background: linear-gradient(135deg, #e0f7fa 0%, #b2ebf2 100%);
}

.kpi__hint {
  margin-left: 2px;
  font-size: 11px;
  font-weight: 400;
  color: #6a6a6a;
}

.kpis__hint {
  margin: -8px 0 18px;
  font-size: 12px;
  color: var(--t4);
  background: #ffffff;
  border-radius: 10px;
  padding: 12px 14px;
}

/* 财务三页页头统计卡（第二十四批需求变更二）：固定 3 列 —— 合计 / 已结算 / 未结算。
   贴在列表页「元信息行」与「操作按钮行」之间；卡片本身复用首页 .kpi 配色。 */
.fcard {
  margin: 0 0 12px;
}

.fcard .kpis {
  margin-bottom: 0;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}

.fcard .kpi {
  padding: 10px;
  border-radius: 10px;
}

.fcard .kpi__label {
  font-size: 11px;
}

.fcard .kpi__value {
  margin-top: 5px;
  font-size: 15px;
}

/* 系统管理 · 历史版本记录（最近 20 次） */
.rel-list {
  padding: 4px 0;
}

.rel-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 9px 14px;
  border-bottom: 1px solid #f0f1f3;
}

.rel-item:last-child {
  border-bottom: 0;
}

.rel-item__v {
  font-size: 14px;
  font-weight: 600;
  color: #1f1f1f;
}

.rel-item__t {
  font-size: 12px;
  color: var(--t4);
}

.pending {
  margin-bottom: 18px;
}

.pending__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 8px;
}

.pending__title {
  font-size: 15px;
  font-weight: 600;
  color: var(--t1);
}

.pending__count {
  font-size: 12px;
  color: var(--t4);
}

/* 🆕 第八十九批：「我的双包清单」按订单号筛选时的提示条（「只看 XXX」+ 可点的「看全部」）。
   没有它施工员选了单之后不知道表被筛了；没有「看全部」就再也回不到全量。 */
.pending__filter {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: 8px;
  padding: 2px 8px;
  border-radius: 999px;
  background: #eef5fd;
  color: #1268d6;
  font-size: 11.5px;
  white-space: nowrap;
}

.pending__filter-x {
  text-decoration: underline;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* 第十三批：仓管员首页「出入库明细」标题与「+ 新增」各占 1/2（标题左半 / 按钮右半）。
   .pending__head--half 只给该区用，「未完成订单」区仍走原 .pending__head。 */
.pending__head--half {
  align-items: center;
}
.pending__head--half > .pending__lead {
  display: flex;
  align-items: baseline;
  flex: 0 0 50%;
  width: 50%;
  min-width: 0;
  box-sizing: border-box;
}
.pending__head--half > .pending__lead .pending__count {
  margin-left: 8px;
}
.pending__head--half > .act {
  flex: 0 0 50%;
  width: 50%;
  box-sizing: border-box;
  height: 36px;
}

/* 🔴 第195批（2026-10-11 用户需求）：仓管员主页「未出库订单」区两处**线上失效**修复。
   ① 头部溢出：「已备好」「列设置」原来各自走上面那条 flex:0 0 50%（不可收缩），两个按钮
      就是整个头部宽；第189批又在同一行塞进一个订单号 <select> ⇒ 总宽 = 头部的 3 倍，
      溢出到屏幕外、再被 .screen{overflow-x:clip} 裁掉 ⇒ 线上「列设置」与订单号选框
      **根本看不见**（用户报的正是这个）。
      改法：两个按钮收进 .pending__acts 容器平分右半（各 flex:1 1 0，可收缩）；
      订单号选框挪到表格上方独立一行（.pending__pick）。
      ⚠️ 实测（本地无头 Chrome + CDP 设备度量）：改前 390px 下 #un-cols 左边界 374、
         #un-no 左边界 553，双双越界；改后 360 / 390px 全部落在视口内、
         scrollWidth == 视口宽（无横向溢出）。
   ② 复选框不可见：app.css 顶部第 70~84 行的全局 reset 对 input 做了
      appearance:none + background:none + border:0，把原生复选框抹成 **0×0**
      （实测 getBoundingClientRect() 宽高皆 0）⇒ 既看不见也点不到。
      这里只用 #un-ptable 限定作用域把它自绘回来，**不动全局 reset**
      （全站输入框 / 下拉都靠它抹掉系统外观）。
   🔴 可翻转点：想让复选框回到系统原生外观，把下面三段换成
      `#un-ptable input[type="checkbox"]{ -webkit-appearance:auto; appearance:auto;
       width:20px; height:20px; accent-color: var(--green); }` 即可（去掉 :checked 两段）。 */
.pending__head--half > .pending__acts {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 50%;
  width: 50%;
  min-width: 0;
  box-sizing: border-box;
}
.pending__head--half > .pending__acts > .act {
  flex: 1 1 0;
  width: auto;
  min-width: 0;
  height: 36px;
}

/* 订单号选框：独占一行，落在表格**上方** */
.pending__pick {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 10px;
}
.pending__pick-label {
  flex: 0 0 auto;
  font-size: 14px;
  color: var(--t3);
}
.pending__pick .aform__select {
  flex: 1 1 auto;
  min-width: 0;
  height: 40px;
  padding: 0 12px;
  background: var(--card);
  border: 1px solid var(--line2);
  border-radius: 8px;
  color: var(--t1);
  /* ⚠️ 16px 是硬下限：iOS Safari 对字号 <16px 的输入控件会自动放大整个页面
     （同第 2504 行那条规则的道理），这里必须留够。 */
  font-size: 16px;
}

/* 复选框：把被全局 reset 抹平的勾选框自绘回来（仅限未出库订单表内） */
#un-ptable input[type="checkbox"] {
  -webkit-appearance: none;
  appearance: none;
  width: 20px;
  height: 20px;
  margin: 0;
  border: 1.5px solid var(--line2);
  border-radius: 4px;
  background: var(--card);
  position: relative;
  vertical-align: middle;
}
#un-ptable input[type="checkbox"]:checked {
  background: var(--green);
  border-color: var(--green);
}
#un-ptable input[type="checkbox"]:checked::after {
  content: '';
  position: absolute;
  left: 6px;
  top: 2px;
  width: 5px;
  height: 10px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
/* 🔴 第197批·补（2026-10-11 用户口径「库存不够时，此记录不能被选中」）：
   库存不足的行 —— 复选框描虚线灰框、鼠标显示禁止，并由 app.js 拦掉勾选（点击会说明还缺多少）。
   ⚠️ 与上面那条 unchecked 样式同作用域（#un-ptable），特异性更高（多一个类）⇒ 只覆盖边框，
      不影响 20px 尺寸与圆角。勾选态永远到不了这里（代码保证它勾不上），故无需写 :checked。
   🔴 第198批（2026-10-11 用户口径「库存不足的，参考 #out/register，显示为灰色」）：
      整行改由 `.or-row--no{opacity:.5}` 压暗（app.css 第 2984 行，与出库登记页同一套类名）。
      这里**删掉了原来的 `opacity: 0.35`** —— 行已经 0.5，再叠 0.35 相乘只剩 0.175，
      勾选框会淡到几乎看不见（等于把框「抹掉」而不是「灰掉」）。虚线框与禁止光标保留，
      当「不可勾」的补充提示。
   🔴 可翻转点：想彻底对齐出库登记页（那边勾选框不描虚线、只被行透明度带着一起变淡），
      把下面两行删到只剩 `cursor: not-allowed;` 即可。 */
#un-ptable input[type="checkbox"].un-chk--no {
  border-style: dashed;
  cursor: not-allowed;
}

/* 第四十九批（C-2）：出入库明细表**上方**的「新增订单」按钮（整宽一条）。 */
/* 第四十九批（C-2）：出入库明细表**上方**的「新增订单」按钮。
   第五十六批（2026-10-05 用户需求）：旁边加「退货订单」，两个**同为一排**（各占一半）——
   容器负责并排与间距，按钮自己负责外观（padding / 配色 / 圆角）。 */
.pending__addrow {
  display: flex;
  margin: 10px 12px 8px;
}

.pending__addrow-btn {
  flex: 1;
  padding: 11px 0;
  text-align: center;
  font-size: 14px;
  color: #07c160;
  background: #f2fbf5;
  border: 1px solid #cdeed9;
  border-radius: 10px;
  cursor: pointer;
}

/* 两个按钮之间的间距（只给第二个加左边距，容器右侧不会多出一截） */
.pending__addrow-btn + .pending__addrow-btn {
  margin-left: 10px;
}

.pending__addrow-btn:active {
  background: #e6f7ec;
}

/* 第五十六批：「退货订单」用蓝调区分（与「+ 新增订单」的绿调并列，一眼分得清） */
.pending__addrow-btn--ret {
  color: #1989fa;
  background: #f2f8ff;
  border-color: #cfe4fb;
}

.pending__addrow-btn--ret:active {
  background: #e6f1ff;
}

.pending__empty {
  padding: 28px 0;
  text-align: center;
  font-size: 13px;
  color: var(--t5);
  background: #ffffff;
  border-radius: 12px;
}

.pending__more {
  margin-top: 8px;
  text-align: right;
  font-size: 12px;
  color: var(--green);
}

/* ── 施工员首页「我的施工单」区（第十八批） ── */
.aform {
  margin-top: 10px;
  padding: 4px 12px 14px;
  background: #ffffff;
  border-radius: 12px;
}

.aform__row {
  display: flex;
  align-items: center;
  min-height: 46px;
  border-bottom: 1px solid var(--line);
}

/* 最后一行（备注）不要底边线，免得与提交按钮之间多一道线 */
.aform__row:last-child {
  border-bottom: none;
}

.aform__label {
  flex: 0 0 88px;
  font-size: 14px;
  color: var(--t3);
}

.aform__ctl {
  flex: 1 1 auto;
  min-width: 0;
  /* 🔴 必须 ≥16px：iOS 上点字号 <16px 的输入框会把整页放大且缩不回来（见网页护栏） */
  font-size: 16px;
  color: var(--t1);
}

/* 输入框去掉浏览器默认描边，与表单其余部分的观感保持一致 */
.aform__input {
  height: 46px;
  border: 0;
  outline: none;
  background: transparent;
  font-family: inherit;
  font-size: 16px;
}

.aform__select {
  height: 46px;
  border: 0;
  outline: none;
  background: transparent;
  font-family: inherit;
  /* 🔴 同样必须 ≥16px：下拉也是输入控件，字号小了 iPhone 一点就整页放大 */
  font-size: 16px;
}

/* 第二十三批：一行两格（施工单价 | 施工费）—— 两格各占一半，中间留 12px 间隙 */
.aform__row--pair {
  display: flex;
  align-items: center;
}

.aform__cell {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: center;
}

.aform__cell + .aform__cell {
  margin-left: 12px;
}

/* 半格里的标签不占固定宽度，改为紧贴数值，免得把数字挤没 */
.aform__label--pair {
  flex: 0 0 auto;
  margin-right: 6px;
}

/* 只读展示（施工单价 / 施工费）：看起来像输入框，但不给改 */
.aform__ro {
  height: 46px;
  line-height: 46px;
  color: var(--t1);
}

/* 施工费是这一屏最重要的数字 —— 加重显示 */
.aform__ro--fee {
  font-size: 17px;
  font-weight: 600;
  color: var(--green);
}

.aform__btn {
  margin-top: 14px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background: var(--green);
  color: #ffffff;
  font-size: 15px;
  font-weight: 600;
}

.aform__btn:active {
  opacity: 0.85;
}

.aform__tip {
  margin-top: 8px;
  font-size: 11px;
  line-height: 1.6;
  color: var(--t4);
}

.grid {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.grid__item {
  width: calc((100% - 12px) / 2);
  min-height: 92px;
  background: #ffffff;
  border-radius: 12px;
  padding: 18px 16px;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.04);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.grid__item:active {
  background: #fafbfc;
}

.grid__item:last-child:nth-child(odd) {
  width: 100%;
}

/* 模块卡片图标（2026-09-28 用户要求：加图标提升观感） */
.grid__icon {
  width: 40px;
  height: 40px;
  margin-bottom: 9px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 21px;
  line-height: 1;
  background: #f0f2f5;
}

.grid__icon--order { background: #e8f1ff; }
.grid__icon--product { background: #fff4e5; }
.grid__icon--stock { background: #e8f6ee; }
.grid__icon--employee { background: #efeafc; }
.grid__icon--settings { background: #eef0f3; }
.grid__icon--logout { background: #ffe9e9; }
/* 🆕 第五十八批新增的菜单图标底色（施工派单 / 施工登记 / 调色登记 / 财务；调色费结算在「财务」页内） */
.grid__icon--build { background: #fdeee2; }
.grid__icon--buildReg { background: #e9f3ff; }
.grid__icon--colorReg { background: #fdeaf4; }
.grid__icon--financeHome { background: #e8f1ff; }
.grid__icon--financeColor { background: #fdeaf4; }
.grid__icon--orderAdd { background: #eef7ee; }
/* 「财务」页的卡片名是 4~5 个字（订单收款 / 施工费结算 / 调色费结算），
   而首页那套字间距（12px）是为 2 字标题（订单 / 产品 / 仓库）调的 —— 只给「财务」页单独特调。
   ⚠️ 必须带 .finance 限定：否则首页那张网格也会被一起改窄。 */
#screen .home.finance .grid__name { letter-spacing: 1px; text-indent: 0.5px; font-size: 15px; }

.grid__name,
.grid__count,
.grid__desc {
  width: 100%;
}

.grid__name {
  font-size: 16px;
  font-weight: 600;
  color: var(--t1);
  letter-spacing: 12px;
  text-indent: 6px;
}

.grid__count {
  margin-top: 8px;
  font-size: 12px;
  color: var(--green);
}

.grid__desc {
  margin-top: 5px;
  font-size: 12px;
  color: #8a8f99;
}

.grid__item--danger {
  background: #fff6f6;
}

.grid__item--danger:active {
  background: #ffeeee;
}

.grid__name--danger {
  color: var(--red);
}

/* ---------- 搜索条 / 页信息 / 操作按钮 ---------- */
.bar {
  padding: 0 12px;
}

.bar__input {
  width: 100%;
  height: 38px;
  background: #ffffff;
  border-radius: 8px;
  padding: 0 12px;
  font-size: 16px; /* 必须 ≥16px，否则 iOS 一点搜索框就把页面放大 */
}

.meta {
  padding: 10px 16px 0;
}

.meta__title {
  display: block;
  font-size: 16px;
  font-weight: 600;
  color: var(--t1);
}

.meta__sub {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  color: var(--t4);
}

.meta__stat {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  color: var(--green);
}

/* ==========================================================================
   🆕 第八十五批（2026-10-07 用户需求）：移动端「下拉刷新」的提示气泡
   需求原文：「移动端和小程序下拉页面，也要有刷新的功能」。
   行为由 app.js 的 installPullRefresh() 驱动（只在触摸设备上装）。
   ⚠️ 两条关键位置约束，改动前先读：
     · top 落在**导航栏下方**（导航栏高 48px + 安全区 + 一点间距）；
     · z-index **低于**导航栏（导航栏是 60）—— 这样它初始 translateY(-60px) 时
       正好藏在导航栏背后看不见；下拉时才从导航栏下沿滑出来。
   ⚠️ transform 由 JS 逐帧设置（跟手），所以这里**不要**给 transform 加 transition，
      否则会滞后于手指。只给 opacity 和 background-color 做过渡。
   ========================================================================== */
.pulltip {
  position: fixed;
  left: 50%;
  top: calc(54px + var(--safe-t));
  z-index: 55;
  padding: 5px 14px;
  font-size: 12px;
  line-height: 1.4;
  color: #ffffff;
  background: rgba(0, 0, 0, 0.62);
  border-radius: 999px;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  will-change: transform;
  transition: opacity 0.14s ease, background-color 0.14s ease;
}

/* 拉够了、松手就会刷新 —— 变绿，给一个明确的「可以松手了」信号 */
.pulltip.is-ready {
  background: var(--green);
}

.pulltip.is-busy {
  background: rgba(0, 0, 0, 0.75);
}

.acts {
  display: flex;
  gap: 8px;
  padding: 10px 12px;
}

/* 🆕 第八十五批（2026-10-07 用户需求）：「+双包单 / +销售单 / +退货单 改成一列 3 排」
   ⇒ 把这一排从横排改成**竖向一列**（每个按钮占一整行）。
   ⚠️ 只加在用了 .acts--col 的那一排（目前只有 #view/orderDetail），其余列表页的按钮排不受影响。
   ⚠️ .act 自身是 flex:1（横排时用来均分宽度）；在竖向容器里必须改成 flex:none + 满宽，
      否则会被拉伸/压扁。 */
.acts--col {
  flex-direction: column;
}

.acts--col .act {
  flex: none;
  width: 100%;
}

/* 🆕 第248批（2026-10-16 用户需求）：订单详情页（#view/orderDetail）的菜单改成
   **方块、一行 2 个**，括号内文字单独放第二行（.act__main / .act__sub）。
   · 一行 2 个 = flex + `flex-wrap: wrap` + 每个方块 `flex: 0 0 calc(50% - 4px)`
     （gap 8px ⇒ 减 4px 正好两列铺满；写 50% 会因为 gap 溢出换行）。
   · 方块 = 固定高度 + 竖向居中两行 + 更方的圆角。
   ⚠️ 只作用在 `.acts--tile2`；其余列表页的 `.acts`（横排）/`.acts--col`（一列）不受影响。
   🔴 可翻转点 = 下面那个 `calc(50% - 4px)`（改 33% 即一行 3 个）。 */
.acts--tile2 {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 10px 12px;
}

.acts--tile2 .act--tile {
  flex: 0 0 calc(50% - 4px);
  width: auto;
  height: 56px;
  padding: 4px 6px;
  flex-direction: column;      /* 两行竖排 */
  gap: 1px;
  line-height: 1.25;
  text-align: center;
  border-radius: 10px;
  white-space: normal;          /* 允许换行（长文案不至于顶破方块） */
}

.act__main {
  font-weight: 600;
}

.act__sub {
  font-size: 11.5px;
  opacity: 0.82;
  line-height: 1.2;
}

.act {
  flex: 1;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  color: var(--t2);
  background: #ffffff;
  border-radius: 8px;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.04);
}

.act--primary {
  background: var(--green);
  color: #ffffff;
}

/* 🔴 第六十一批（2026-10-05 用户需求）：「+双包」的独立样式**已删除**。
   第五十九批那套「白底绿字绿框（.act.act--dbl）」撤掉 ⇒ 该按钮改用 `.act--primary`
   （实心绿 + 白字），外观与紧挨着的「+ 新增」**一模一样**。
   ⚠️ 别再给「+双包」加回独立样式：那样两个按钮外观就又不一致了（护栏已钉住）。
   ⚠️ 与小程序 pages/view/list.wxss 同口径（那边的 `.act--dbl` 同样已删）。 */

.act:active {
  opacity: 0.72;
}

/* 第五十二批（B）：「订单详细表」视图操作栏里的「退货订单」入口（在「字段设置」上方）。
   它是「新增类」动作，用橙色文案与「列设置 / 字段设置」区分开
   （绿色留给「+ 新增」，橙色才不至于被误当成主按钮）。 */
.act.retbar__btn {
  color: #d97706;
  font-weight: 600;
}

/* ---------- 表格（横向滚动） ---------- */
.tw {
  width: 100%;
  max-width: 100%;   /* 🆕 第一百一十四批：横滚容器自身绝不超出父级（防被内容顶宽） */
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* ======================================================================
   🔴 第一百二十八批（2026-10-09 用户需求）：「本项目所有人所有的页面所有的表格，
   字段的值要全部显示出来，表格中的数据和字段左右居中对齐。」
   用户选定口径（AskUserQuestion 选项）＝ **列宽跟着内容变宽**：
   值多长列就多宽、一行显示完不换行；整张表超出屏幕时由外层 `.tw` 横向滚动。
   ----------------------------------------------------------------------
   做法：把两套表格（大表 .table/.tr/.td 与小表 .ptable/.ptr/.ptd）
   从「flex 行 + 写死列宽 + 溢出省略号」改成 **CSS 表格布局**
   （display:table / table-row / table-cell）：
     ① 浏览器原生「列宽 = 该列全部单元格内容的最大宽度」，且**跨行自动对齐**；
     ② 去掉 overflow:hidden / text-overflow:ellipsis ⇒ 值不再被截成「…」；
     ③ 数据格与表头一律 text-align:center（用户原话「数据和字段左右居中对齐」）。
   ⚠️ 为什么非换布局不可：flex 那套是「每一行各自一条 flex 线」，列宽全靠写死的 width
      对齐 —— 一旦让宽度跟着内容走，各行的同列宽度就互不相同、整张表错位。
      表格布局由浏览器统一算列宽，是唯一**不用 JS 测量**就能「内容驱动 + 跨行对齐」的写法。
   ⚠️ 三条必须跟着改的连带处（少一条就出错）：
      · `.table--fit`（#tables 页，第七十七批的「一屏看全 + 折行」）要显式锁回 flex；
      · `@media print` 里 `.table { display:block !important }` 要改成 table；
      · `.ptd__inp`（数量输入框）的 width:100% 要改固定宽（否则列宽 ← input ← 列宽 循环依赖）。
   🔴 可翻转点 = 下面 .table / .tr / .td 三条的 display、width、text-align、overflow 四类属性
      （改回 inline-block / flex / flex:none + width:92px + overflow:hidden + ellipsis 即回到旧版式）。
   ⚠️ 小表那一套（.ptable/.ptr/.ptd）改法完全相同，见下面 890 行附近那一段。
   ====================================================================== */
.table {
  display: table;      /* 🔴 原 inline-block —— 表格布局：列宽由内容决定 */
  width: 100%;         /* 铺满容器；内容更宽时被 max-content 撑开（表格布局下 width 只是「目标宽」） */
  min-width: 100%;
  background: #ffffff;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.04);
}

.table--inset {
  margin: 0 12px;
}

.tr {
  display: table-row;  /* 🔴 原 flex —— ⚠️ .table--fit 内在下面被显式锁回 flex */
  border-bottom: 1px solid var(--line);
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

.tr:last-child {
  border-bottom: none;
}

.tr--head {
  background: #f7f8fa;
}

.td {
  display: table-cell;     /* 🆕 本批：配合 .tr 的 table-row */
  width: auto;             /* 🔴 原 flex:none; width:92px —— 改成跟着内容走（值多长列多宽） */
  padding: 11px 9px;
  font-size: 13px;
  color: var(--t2);
  white-space: nowrap;     /* 一行显示完、不换行（用户口径） */
  text-align: center;      /* 🆕 数据与字段一律左右居中（用户原话） */
  vertical-align: middle;  /* 🆕 行内上下居中（原来靠 flex 的 stretch） */
  /* 🔴 本批删掉了 overflow:hidden 与 text-overflow:ellipsis —— 值不再被截断 */
}

/* 首列原本写死 102px（订单号列），本批起列宽跟着内容走 ⇒ 不再需要固定值。
   🔴 想回到「首列固定 102px」：把下面 width 改回 102px 即可。
   ⚠️ 下面 .td.td--narrow:first-child / .td.td--pick:first-child 那两条「抢回窄列」的规则
      （历史注释在 854 行与 2699 行）现在只是冗余，**保留不动** —— 免得翻转时又得补回来。 */
.td:first-child {
  width: auto;
}

.tr--head .td {
  font-size: 12px;
  color: var(--t3);
  font-weight: 600;
}

/* 🔴 第190批（2026-10-11 用户需求）：原 .td--status / .ptd--status（状态格可点选）
   与 .td__dd（▾ 提示标记）三条样式，已随「点状态格改状态」入口整体删除。 */

/* ---------- 窄列：状态 / 客户 / 数量 / 采购量 / 当前库存 / 编号 ----------
   这些字段的值本来只有两三个字，却和「产品名称」一样宽，把后面的数据挤出屏幕
   （2026-09-28 用户要求「宽度改到最小」）。加类由引擎 D.isNarrowColumn() 判定，两端同口径。
   ⚠️ 必须写成 .td.td--narrow（两个类）：单类选择器权重低于上面的 .td:first-child，
      落在首列时会被 102px 抢回去，表现成「有的表生效、有的表没生效」。 */
.td.td--narrow {
  width: 60px;
  padding-left: 5px;
  padding-right: 5px;
}

.td.td--narrow:first-child {
  width: 60px;
}

.ptd.ptd--narrow {
  width: 58px;
  padding-left: 4px;
  padding-right: 4px;
}

.ptd.ptd--narrow:first-child {
  width: 58px;
}

/* 「点一下就地改」的单元格（目前只有产品视图的「采购量」）：
   蓝色 + 一条内阴影下划线当提示。用 box-shadow 而不是 border ——
   border 会把行撑高 1px，整张表格跟着跳。 */
.td--edit {
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  color: #1268d6;
  box-shadow: inset 0 -1px 0 #c8dcf5;
}

/* 首页「未完成订单」小表：与小程序 index.wxss 的 .ptable/.ptr 一致（rpx÷2）。
   ⚠️ .ptr 必须是 display:flex —— 少了它每个 .ptd 退化成块级元素，
   表头和数据会整列竖着摞（2026-09 线上踩过）。
   🔴 第一百二十八批（2026-10-09 用户需求）：.ptr/.ptd 已改成 **表格布局**
   （table-row / table-cell），上面那句「必须是 flex」的老约束随之作废 ——
   现在「整列竖着摞」这个坑由 table-cell 天然兜住（表格布局下不可能摞）。
   ⚠️ app.js 往 .ptd 行内写的 `style="flex:…"`（PT_COL_WIDTH / ptFlexOf）
      在 table-cell 上被浏览器**直接忽略**（无害、也不报错）——
      保留它只是为了让「想回退 flex 版式」时少改一处，本批它已不再决定任何列宽。
   🔴 可翻转点 = .ptable/.ptr/.ptd 三条的 display、width、text-align、overflow
      （改回 inline-block / flex / flex:none + width:86px + overflow:hidden + ellipsis 即回旧版式）。 */
.ptable {
  display: table;      /* 🔴 原 inline-block —— 小表也改成表格布局（列宽由内容决定） */
  width: 100%;
  min-width: 100%;
  background: #ffffff;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.04);
}

.ptr {
  display: table-row;  /* 🔴 原 flex */
  border-bottom: 1px solid #f0f1f3;
}

/* 🆕 第九十二批：偶数行淡底 + 行间留白，移动端纵向扫读更容易（原来纯白一片）。
   ⚠️ :nth-child 从 2 开始 —— 第 1 行是表头（.ptr--head），不能算进斑马纹。 */
.ptr:not(.ptr--head):nth-child(even) {
  background: #fafbfc;
}

.ptr:last-child {
  border-bottom: none;
}

.ptr--head {
  background: #f7f8fa;
}

.ptd {
  display: table-cell;     /* 🆕 第一百二十八批：配合 .ptr 的 table-row */
  width: auto;             /* 🔴 原 flex:none; width:86px —— 改成跟着内容走（值多长列多宽） */
  padding: 10px 8px;
  font-size: 12.5px;
  color: var(--t2);
  white-space: nowrap;     /* 一行显示完、不换行（用户口径） */
  text-align: center;      /* 🆕 数据与字段一律左右居中（用户原话） */
  vertical-align: middle;  /* 🆕 行内上下居中 */
  /* 🔴 本批删掉了 overflow:hidden 与 text-overflow:ellipsis —— 值不再被截断 */
}

.ptd:first-child {
  width: auto;
}

/* 🆕 第245批：「使用场景」多值格允许换行（.ptd 默认 nowrap，会被英文逗号串撑得很宽）。
   🔴 为什么不给这一列加宽：打印小表的定宽面宽之和（PT_COL_WIDTH）双包清单已是 384px，
      手机内容宽约 390px ⇒ 加宽必然横向溢出。只放开换行，其余列的 nowrap 一个字不动。 */
.ptd--wrap {
  white-space: normal;
  word-break: break-all;
  line-height: 1.35;
}

/* 🆕 第九十二批（2026-10-07 用户反馈「移动端很不美观」）：小表排版优化 ——
   ① 宽度改由**行内 style 的 flex** 给（app.js 的 PT_COL_WIDTH / ptFlexOf），
      上面那条 width: 105px 必须让位，否则会盖掉 flex 的分配。
   ② 名称类字段允许换行（产品名普遍 4~6 字，原来 nowrap+ellipsis 直接截断）。
   ③ 上下内边距略增、行高放松 —— 原来挤在一起，5 列并排时看着像一张 Excel。
   ④ 「订单号」重复行用 .ptd--cont 去掉左内边距，视觉上像合并单元格。
   ⚠️ 只影响 .ptd（那张小表），.table / .td 那一套大表不受影响。 */
.ptd {
  min-width: 0;                 /* ⚠️ 第一百二十八批改表格布局后，这条对「收缩」已无作用
                                   （表格布局下列宽由内容定），保留只为翻转时少改一处 */
  padding: 12px 8px;
  line-height: 1.5;
}

/* 名称/规格类可换行显示，不再截断
   🔴 第一百二十八批（2026-10-09 用户需求）：「字段的值要全部显示出来」+ 当面选定的
   「列宽跟着内容变宽（一行显示完、不换行）」⇒ 本类**不再允许换行**。
   ⚠️ 当前全项目没有任何地方挂 .ptd--wrap（grep 过 app.js / index.html），本改动实际无影响，
      纯粹是防止将来有人挂上它、又把值折成两行，与用户口径冲突。
   🔴 想恢复「名称类可换行」：把下面 white-space 改回 normal + 加回 word-break: break-all。 */
.ptd--wrap {
  white-space: nowrap;
}

/* 订单号重复行：去掉左内边距 + 极淡的分隔，模拟合并单元格 */
.ptd--cont {
  padding-left: 0;
  color: var(--t4);
}

/* 表头略小一点、留白匀一些 */
.ptr--head .ptd {
  padding: 10px 8px;
  letter-spacing: 0.2px;
}

.ptr--head .ptd {
  font-size: 11.5px;
  color: var(--t3);
  font-weight: 600;
}

/* ---------- 表头点击排序（第二十批）----------
   所有表头都可点：鼠标移上去变手型，点一下按该列升序、再点降序。
   当前排序列标 ▲/▼ —— 那个小三角是**只在排序时**才渲染的 span，
   所以未排序的表头文字（各种按 textContent 的断言）原样不变。
   ⚠️ 这两条「当前排序列高亮」必须写在 .tr--head .td / .ptr--head .ptd 的**后面**：
      同为 2 个类选择器时权重相同，靠后写的赢，否则会被基础色压掉。 */
.tr--head .td,
.ptr--head .ptd {
  cursor: pointer;
}

.tr--head .td--sorted,
.ptr--head .ptd--sorted {
  color: #1268d6;
}

.th__arrow {
  margin-left: 3px;
  font-size: 10px;
}

.empty {
  text-align: center;
  color: var(--t5);
  font-size: 14px;
  padding: 40px 0;
}

/* 🆕 第一百零八批：已出库订单的编辑页提示（.empty 里嵌一个加粗片段 + 一行更淡的补充说明）。 */
.empty__b {
  color: #d9822b;
  font-weight: 600;
}

.empty__hint {
  display: inline-block;
  margin-top: 10px;
  font-size: 12.5px;
  color: var(--t6, #a8b0bb);
}

.hint {
  text-align: center;
  color: var(--t5);
  font-size: 11px;
  padding: 10px 16px 0;
}

/* ---------- 卡片列表 ---------- */
.list {
  padding: 4px 12px 0;
}

.card {
  background: #ffffff;
  border-radius: 10px;
  padding: 14px 16px;
  margin-bottom: 10px;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.04);
  position: relative;
}

.card--tap:active {
  background: #fafbfc;
}

.card__title {
  font-size: 15px;
  font-weight: 600;
  color: var(--t1);
  padding-right: 52px;
  word-break: break-all;
}

.card__row {
  display: flex;
  align-items: flex-start;
  margin-top: 7px;
  font-size: 13px;
}

.card__label {
  flex: none;
  width: 88px;
  color: var(--t4);
}

.card__value {
  flex: 1;
  color: var(--t2);
  word-break: break-all;
}

/* 卡片右上角按钮组（第六十九批：团队页多了「权限」按钮，与「删除」并排） */
.card__acts {
  position: absolute;
  top: 10px;
  right: 10px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.card__perm {
  padding: 5px 10px;
  font-size: 12px;
  color: #1a73e8;
  background: #eef4fe;
  border-radius: 6px;
}

.card__perm:active {
  background: #e0ecfd;
}

.card__del {
  padding: 5px 10px;
  font-size: 12px;
  color: var(--red);
  background: #fff5f5;
  border-radius: 6px;
}

.card__del:active {
  background: #ffe9e9;
}

/* 关联带出的只读信息 */
.ref {
  margin-top: 6px;
  background: #f8f9fb;
  border-radius: 8px;
  padding: 8px 10px;
}

.ref__row {
  display: flex;
  font-size: 12px;
  line-height: 1.7;
}

.ref__label {
  flex: none;
  width: 84px;
  color: var(--t3);   /* 引用框标签加深：原 var(--t4) #999 偏浅 */
}

.ref__value {
  flex: 1;
  color: var(--t2);
  word-break: break-all;
}

/* ---------- 库存结存汇总 ---------- */
.sum {
  margin: 4px 12px 10px;
  background: #ffffff;
  border-radius: 10px;
  padding: 12px 14px;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.04);
}

.sum__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 8px;
}

.sum__title {
  font-size: 14px;
  font-weight: 600;
  color: var(--t1);
}

.sum__warn {
  font-size: 12px;
  color: var(--red);
}

.sum__ok {
  font-size: 12px;
  color: var(--green);
}

.sum__row {
  display: flex;
  align-items: center;
  font-size: 13px;
  padding: 5px 0;
  border-top: 1px solid var(--line);
}

.sum__code {
  flex: none;
  width: 56px;
  color: var(--t3);
}

.sum__name {
  flex: 1;
  color: var(--t2);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.sum__qty {
  flex: none;
  color: var(--t1);
  font-weight: 600;
}

.sum__safe {
  color: var(--t5);
  font-weight: 400;
}

.sum__row.is-low .sum__qty {
  color: var(--red);
}

/* ---------- 表单（动态字段） ---------- */
.form {
  padding: 4px 12px 0;
}

/* 表单行：订单表把短字段（业务经理+施工老师、数量+单价）两两并排一行，省一半竖向空间；
   其余字段仍各自占一整行。见 mf-data.js 的 orderFormHalves / formRows。 */
.frow {
  display: flex;
  align-items: stretch;
}

.frow > .fitem {
  flex: 1;
  min-width: 0;
}

/* 并排两列的内边距收窄一点，窄列里内容区更大 */
.frow--half {
  gap: 8px;
}

.frow--half > .fitem {
  padding-left: 10px;
  padding-right: 10px;
}

/* 🆕 第301批（用户需求）：#collect 收款行 —— 订单金额 20% / 收款金额 50% / 其他支出 30%。
   两处 gap = 8px × 2 = 16px，按「可用宽」扣掉再分，三格合计正好 100%。 */
.frow--collect-253 {
  gap: 8px;
}
.frow--collect-253 > .fitem:nth-child(1) {
  flex: 0 0 calc(20% - 3.2px);
  width: calc(20% - 3.2px);
}
.frow--collect-253 > .fitem:nth-child(2) {
  flex: 0 0 calc(50% - 8px);
  width: calc(50% - 8px);
}
.frow--collect-253 > .fitem:nth-child(3) {
  flex: 0 0 calc(30% - 4.8px);
  width: calc(30% - 4.8px);
}

/* 第四十九批（A-1）：订单表单「产品 + 库存」那一行 —— 产品占 2/3、库存占 1/3。
   （选择器比 .frow > .fitem 更具体，会盖住等分） */
.frow--w21 > .fitem:first-child {
  flex: 2;
}

.frow--w21 > .fitem:last-child {
  flex: 1;
}

/* 🔴🔴 第七十批补丁 2（2026-10-06 用户需求）：「新增双包清单页」把「客户」与「平方单价」
   并成一排 —— 客户占 4/5（80%）、平方单价占 1/5（20%）。
   对应页面 buildDblAddRows 里 dSplitCust = [4, 1]（小程序翻成 form-row--w41）。
   翻转点 = 那个 [4, 1]（两处一起改：这里 + 小程序 edit.wxss）。 */
.frow--w41 > .fitem:nth-child(1) {
  flex: 4;
}

.frow--w41 > .fitem:nth-child(2) {
  flex: 1;
}

/* 平方单价那一格只有 1/5 宽 ⇒ 内容太长就省略号，别把整行撑破（只影响显示，不影响取值）。 */
.frow--w41 > .fitem:nth-child(2) .fitem__input,
.frow--w41 > .fitem:nth-child(2) .fitem__ro {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 🆕 第246批（2026-10-15 用户需求）：**双包清单新增页**（#edit/dbllist 与 #edit/qb）
   「产品编号宽度缩小 15%，位置给调色」⇒ 产品排由 4 : 1 改成 **17 : 8**。
   · 4 : 1 ⇒ 产品 80% / 调色 20%；80% × 0.85 = 68% ⇒ 68 : 32 = 17 : 8（正好缩 15.00%）。
   · 🔴 用**新类**而不是改 .frow--w41 —— 那个类同时被「客户名 80% + 双包单价 20%」用着（第70批），
     改了会连坐那一页。按本项目纪律「新增类、不覆盖旧类」。
   · ⚠️ 网页端的 split 是**自动翻成类名**的（withSplitClass：'frow--w' + split.join('')）
     ⇒ 页面写了 17 / 8 而这里没有 .frow--w178，比例就**完全不生效**（静默回落到 .frow > .fitem 的等分）。
     两处必须一起改。
   · 🔴 可翻转点 = 下面这两个 flex（改回 4 / 1 即恢复原样，但要连页面 dSplit1 一起改）。 */
.frow--w178 > .fitem:nth-child(1) {
  flex: 17;
}

.frow--w178 > .fitem:nth-child(2) {
  flex: 8;
}

/* 调色格变宽了但值仍可能长（「是」/「否」很短，保险起见留收尾；只影响显示，不影响取值）。 */
.frow--w178 > .fitem:nth-child(2) .fitem__input,
.frow--w178 > .fitem:nth-child(2) .fitem__ro {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 🔴🔴 第一百三十五批（2026-10-09 用户需求）：「新增双包订单页」把「平方单价」与「订单说明」
   并成一排 —— 平方单价在**左**、占 1/5（**20%**），订单说明在右、占 4/5（80%）。
   对应页面 buildDblAddRows 里 dSplitNote135 = [1, 4]（类名 .frow--w14）。
   ⚠️ 纯**新增**类，不覆盖上面任何旧类（旧类可能还有别的页面在用，删了会连坐）。
   翻转点 = 那个 [1, 4] 与两格的先后（两处一起改：这里 + 页面那段）。 */
.frow--w14 > .fitem:nth-child(1) {
  flex: 1;
}

.frow--w14 > .fitem:nth-child(2) {
  flex: 4;
}

/* 平方单价那一格只有 1/5 宽 ⇒ 内容太长就省略号，别把整行撑破（只影响显示，不影响取值）。 */
.frow--w14 > .fitem:nth-child(1) .fitem__input,
.frow--w14 > .fitem:nth-child(1) .fitem__ro {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 🔴🔴 第八十批（2026-10-07 用户需求 1）：「新增双包清单页」把「姓名」与「双包单价」
   并成一排 —— 姓名占 3/5（**60%**）、双包单价占 2/5（40%）。
   对应页面 buildDblAddRows 里 dSplitCust = [3, 2]（小程序翻成 form-row--w32）。
   🔴 第七十批那版是 .frow--w41（姓名 80% + 单价 20%），本批按用户新口径改成 60/40
   —— 旧类保留（.frow--w41 可能还有别的页面在用，删了会连坐）。
   翻转点 = 那个 [3, 2]（两处一起改：这里 + 小程序 edit.wxss）。 */
.frow--w32 > .fitem:nth-child(1) {
  flex: 3;
}

.frow--w32 > .fitem:nth-child(2) {
  flex: 2;
}

/* 双包单价那一格占 2/5 ⇒ 内容太长就省略号，别把整行撑破（只影响显示，不影响取值）。 */
.frow--w32 > .fitem:nth-child(2) .fitem__input,
.frow--w32 > .fitem:nth-child(2) .fitem__ro {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 第五十批：「使用场景」并进「产品」那一排 ⇒ 产品 2/4 · 库存 1/4 · 使用场景 1/4。
   🔴 第五十二批：使用场景挪走（去「单价」那一排）⇒ 本类现在的用武之地是
   「数量 + 单价 + 使用场景」那一排。
   🔴 第五十四批（2026-10-05 用户需求）：「图中 3 项的宽度设置为均分」
   ⇒ 由 2:1:1 改成 1:1:1（类名也由 frow--w211 变成 frow--w111，与小程序 form-row--w111 对应）。
   显式 flex:1 与 .frow > .fitem 的默认等分同值，写出来是为了让「刻意均分」看得见、护栏钉得住。
   翻转点 = 引擎 orderRowsWithStock 那一行的 [1, 1, 1]。 */
.frow--w111 > .fitem:nth-child(1) {
  flex: 1;
}

.frow--w111 > .fitem:nth-child(2) {
  flex: 1;
}

.frow--w111 > .fitem:nth-child(3) {
  flex: 1;
}

/* 🆕 第251批（2026-10-16 用户需求 3）：「场景」新增页（#edit/scene）第二排 ——
   当前库存 / 使用场景 / 平方单价 三格。
   用户口径：「使用场景向当前库存靠近 8 毫米」⇒ 把「当前库存」缩掉 8mm、那 8mm 让给「使用场景」
   ⇒ **使用场景的左边缘左移 8 毫米**，而「平方单价」的左右边缘**一动不动**（它要留在原位）。
   · 🔴 为什么用「绝对长度」而不复用 split 比例：8 毫米是屏幕绝对尺寸，比例表达不出来
     ⇒ 页面侧走 row.splitClass = 'frow--scene3'（见 app.js withSplitClass 第251批那段）。
   · 三格都写死 flex-basis（**不涨**；允许缩只为吸收亚像素误差）：`.frow--half` 的 gap 是 8px、三格两个间隙 = 16px，
     所以 `(100% - 16px) / 3` 正是「均分」时每一格的内容宽；
     再给第 1 格 −8mm、第 2 格 +8mm ⇒ 三格 basis 之和**恰好等于可用宽**（不多不少，不溢出）。
   · 1mm = 96/25.4 px（CSS 定义）⇒ 8mm ≈ 30.24px；直接写 8mm，由浏览器精确换算。
   · ⚠️ 与网页端 app.css 的 .fitem 内边距口径无关：这里分的是**内容宽**（铁律 23），
     三格内边距一致 ⇒ 可见框的左右边缘跟着内容宽等量移动，正是用户要的效果。
   · 🔴 可翻转点 = 下面那两处 8mm（删掉即回到第249批的「三格均分」）。
   🔴🔴 第255批（2026-10-16 用户需求）改了本段的两条口径：
     ① 三格的**标签文字与下方数据一律水平居中** ⇒ 见本段末尾那条 text-align 规则；
     ② 「当前库存」的宽度缩到**刚够放下「当前库存」四个字**，省下来的宽度**全部给「使用场景」**
        ⇒ 第 1 格由 `calc((100% - 16px)/3 - 8mm)` 改成**定宽 68px**；
           第 2 格由 `+ 8mm` 改成 `flex:1 1 0`（吃掉全部剩余宽）；
           第 3 格（平方单价）**一动不动**（用户口径：多出来的宽度只分给使用场景）。
   · 68px 怎么算出来的 —— 全局 `* { box-sizing: border-box }`（本文件第 26 行）
     ⇒ 写进 flex-basis 的数字就是**外框宽**，内容宽 = 外框宽 − 左右内边距：
         标签 4 个字 × 12px（.fitem__label 的 font-size）= 48px
         + 本排左右内边距 10px × 2（.frow--half > .fitem 把 .fitem 的 14px 收到 10px）= 20px
         ⇒ 48 + 20 = **68px**（内容区恰好 48px，四个字一字不多一字不少）。
   · ⚠️ 副作用（真有，且已处理）：这一格的内容宽只剩 48px，而里面那个只读格 .fitem__ro
     自带 12px 左右的横向内边距 ⇒ 数字可用宽度只有 24px，「1500」这种四位数会**溢出框外**。
     修法 = 只把**这一格**里 .fitem__ro 的内边距由 12px 收到 2px（见下面最后那条规则），
     **不动** .fitem__ro 的全局定义（别的页面一个字节不变）。
   · 🔴 可翻转点 = ① 下面第 1 格的 `68px`；② 第 2 格的 `flex:1 1 0`；③ 末尾那条 text-align:center；
     ④ 再末尾那条 `.fitem__ro` 的 2px 内边距。
     （把 ①② 改回 `calc((100% - 16px)/3 ∓ 8mm)` 即回到第251批口径。） */
.frow--scene3 > .fitem:nth-child(1) {
  /* 🔴 第286批（2026-10-17 用户）：「库存显示框显示4位字符，平方单价显示6位，
     剩下的宽度全部给使用场景选项」⇒ 三格**不再按 15/60/25 的百分比分**：
       · 当前库存 = **68px**（标签「当前库存」4 字 × 12px = 48 + 左右内边距 10×2 = 20），
         格内 .fitem__ro 再定宽 **44px**（4 个 16px 粗体数字 ≈ 39.5px + 内边距 2×2）；
       · 使用场景 = **flex:1 1 0**（吃掉前两格与两个 8px 间隙之后**剩下的全部宽度**）；
       · 平方单价 = **80px**（6 字符输入框 60px + 左右内边距 10×2）。
     ⚠️ 这是用户第286批的最新口径，**取代**第282批的 15/60/25。
     🔴 可翻转点 = 下面三条 flex 与 ro 的 width（改回三个 calc 占比即回第282批）。 */
  flex: 0 0 68px;
}

.frow--scene3 > .fitem:nth-child(2) {
  /* 🔴 第286批（用户）：剩下的宽度**全部**给使用场景（不再钉 60%）。 */
  flex: 1 1 0;
}

.frow--scene3 > .fitem:nth-child(3) {
  /* 🔴 第286批（用户）：平方单价 = 6 字符输入框 60px + 左右内边距 20px = **80px**（固定）。 */
  flex: 0 0 80px;
}

.frow--scene3 > .fitem:nth-child(3) {
  /* 🔴 第285批（2026-10-17 用户）：「平方单价4个字向左移动，和调色对齐」
     ⇒ 本格**单独改成左对齐**（当前库存 / 使用场景两格仍居中，一个字不动）。
     为什么只改这一格：左边缘要与上一排「调色」对齐。
     ⚠️ 第286批格子改成**固定 80px** 后，与调色格（按 1/4 分、随行宽变）的差**不再是常数**：
        390 宽差 10.75px（本批 -12px 补偿后差 1.25px）、430 宽差约 20px、500 宽差约 38px。
        手机端（390~430）可接受；宽屏会偏右，属已知边界（要完全对齐只能让本格回到按比例分）。
     🔴 可翻转点 = 这一条（删掉即回到第255批口径：三格一律居中）。 */
  text-align: left;
}

.frow--scene3 > .fitem:nth-child(3) .fitem__label {
  /* 🔴 第285批：标签随格子左对齐后再左移 12px（390 宽下与「调色」只差 1.25px）。
     ⚠️ 第286批格子固定 80px 后，这个差随行宽变化（见上一条注释）——手机端可接受。 */
  margin-left: -12px;
}

.frow--scene3 > .fitem:nth-child(3) .fitem__input {
  /* 🔴 第285批（用户）：「平方单价输入框宽度改为 6 个字符」。
     16px 字号下「0」宽实测 9.39px ⇒ 6 个字符 + 左右内边距 2px×2 ≈ 60px。
     ⚠️ 第282批的 width:100% 只是把**盒子**撑满（58.75px），左右内边距各 12px
        ⇒ 文字区只剩 34.75px，「123.45」要 50.77px ⇒ 仍然显示不完（实测 scrollWidth 75 > clientWidth 59）。
     本批把内边距收到 2px ⇒ 文字区 54.75~56px，6 个字符（如 123.45）完整可见。
     第286批起本格固定 80px（内容区正好 60px）⇒ `max-width:100%` 就是 60px，不再需要借间隙。
     margin-left:-12px 与标签 / 上一排「调色」同一左边缘（390 宽实测差 1.25px）。
     🔴 可翻转点 = width 60px（改回 100% 即第282批口径）与两处 padding。 */
  width: 60px;
  max-width: 100%;
  padding-left: 2px;
  padding-right: 2px;
  margin-left: -12px;
  margin-right: 0;
}

/* 🆕 第255批（2026-10-16 用户需求 1）：「场景」新增页（#edit/scene）第二排三格 ——
   用户原话「图中 3 项文字和下边的数据居中对齐」⇒ 标签与下方数据**一律水平居中**。
   做法：把 text-align 直接挂在**格子本身**（.fitem）上 —— text-align 是**继承属性**
   ⇒ 里面的标签 .fitem__label、只读格 .fitem__ro、输入框 .fitem__input、多选胶囊里的
     占位符 .scenepick__ph **全部**跟着居中。不必逐个子元素列一遍，也就不会因为漏了
     某个子元素而「半中半左」（这一批第一版正是这么漏掉了 .scenepick 的）。
   · 为什么选择器带 `.frow--scene3 > .fitem` 前缀：只作用于本排三格，别的页面、别的排的
     .fitem 一个字不动（特异性 0,2,0，与书写顺序无关）。
   🔴 可翻转点 = 这一条（删掉即回到默认左对齐）。 */
.frow--scene3 > .fitem {
  text-align: center;
}

/* 🆕 第255批（承上）：<input> / <textarea> 这类**表单控件不吃继承** ——
   浏览器 UA 样式表给它们自己的 `text-align`（Chrome 算出来是 start）⇒ 只靠上面那条继承
   是不够的：「平方单价」里打出来的数字仍会**贴左**（实测 getComputedStyle 返回 start）。
   ⇒ 显式再写一遍。
   🔴 可翻转点 = 这一条。 */
.frow--scene3 > .fitem .fitem__input,
.frow--scene3 > .fitem .fitem__area {
  text-align: center;
}

/* 🆕 第255批（承上）：「使用场景」那格的**数据**要单独处理 —— 它不吃 text-align。
   · 线上这一格渲染成**多选胶囊**：结构 = .scenepick > .scenepick__box(flex + wrap)。
     判据恒为真：引擎 sceneIsMulti 认「表名 scene ∈ SCENE_MULTI_TABLES + key f_mutvpv7e」
     （见 mf-data.js 第6318行），所以这**不是**「也许会」（实测真页面 dump 出来的正是
     `<div class="scenepick" data-scenepick="f_mutvpv7e">`）。
     它是个 flex 盒子，位置由 justify-content 决定 ⇒ 必须补一条 justify-content:center
     才能让「请选择（可多选）」和已选胶囊居中（text-align 对它无效）。
   · .fitem__picker 一并兜住：万一这一列在字段设置里改成普通下拉，它同样是 flex 盒子
     （justify-content: space-between）—— 不兜的话那次改动会让「居中对齐」静默失效。
   🔴 可翻转点 = 这一条。 */
.frow--scene3 > .fitem .scenepick__box,
.frow--scene3 > .fitem .fitem__picker {
  justify-content: center;
}

/* 🆕 第255批（承上）：「当前库存」那一格收窄到 68px 后的配套微调 ——
   该格内容区只剩 48px，而 .fitem__ro 自带 `padding: 0 12px`（全局定义，见本文件 1833 行）
   ⇒ 数字只剩 24px 可用宽，四位数的库存量（如「1500」≈36px）会溢出灰框。
   这里把**这一格**的内边距收到 2px（数字可用宽 48 − 4 = 44px），
   **不动**全局 .fitem__ro 定义 ⇒ 别的页面零影响。
   ⚠️ 已知边界：库存量到 **5 位数**（如「15000」≈45px）会贴到灰框边缘、6 位数会溢出。
      真遇到就把下面 68px 调大（5 位 ⇒ 77px、6 位 ⇒ 86px），或把这一格的字号调小。
   🔴 可翻转点 = 这一条（删掉即回到 12px 内边距，四位数就会溢出）。 */
.frow--scene3 > .fitem:nth-child(1) .fitem__ro {
  /* 🔴 第286批（用户）：「库存显示框显示4位字符」⇒ 定宽 44px =
     4 个 16px 粗体数字 ≈ 39.5px + 左右内边距 2px×2；贴左，与标签同一左缘。 */
  width: 44px;
  margin-left: 0;
  margin-right: auto;
  padding-left: 2px;
  padding-right: 2px;
}

/* 🆕 第255批（承上）：68px 是「4 个字 × 12px + 左右内边距」算出来的**恰好值**（内容区正好 48px）。
   不同设备的中文字体可能把汉字渲染成 48.x px（亚像素舍入）⇒ 一旦超出，浏览器就把
   「当前库存」挤成两行。这里补一句 nowrap 兜住：宁可溢出 0.x 像素，也绝不让它折行。
   🔴 可翻转点 = 这一条（删掉即恢复可折行）。 */
.frow--scene3 > .fitem:nth-child(1) .fitem__label {
  white-space: nowrap;
}

/* 🆕 第252批（2026-10-16 用户需求 1）：「场景」新增页（#edit/scene）**产品栏的输入框改白底**。
   用户口径（两轮确认）：「只变能打字的输入框」⇒ 只动那两个 input（产品编号 / 平方单价），
   当前库存（只读格）、使用场景（胶囊）都保持原样。
   · 默认输入框底色是 .fitem__input 的 #f7f8fa（浅灰，见本文件 1801 行那条**分组选择器**）⇒ 这里覆盖成纯白 #ffffff。
   · 类由**字段标记**打上（页面侧 `f.white`，只在场景页为真 —— app.js buildDblAddRows 那两格）
     ⇒ 与**布局位置无关**（不靠 nth-child），行内格子增删都不会误伤；
     也不需要动 .frow--scene3 / .frow--w178 这两条既有规则。
   🔴🔴 **第253批修：选择器必须是 `.fitem__input.fitem__input--white`（复合类，特异性 0,2,0）。**
     第252批写的是单类 `.fitem__input--white`（0,1,0），而它落在**第 1555 行**、
     基础规则 `.fitem__input` 落在**第 1801 行** —— 同特异性**后写的赢** ⇒ 白色被浅灰压掉、
     线上一直没变白（浏览器实测 `rgb(247, 248, 250)`）。
     复合类让本规则**不依赖书写顺序**，以后谁把它挪到哪儿都照样生效。
     ⚠️ 教训：CSS 覆盖不能用「单类 + 靠位置」，判据必须是**渲染后的计算样式**，不是「HTML 里有这个类名」。
   🔴 可翻转点 = 这条规则（删掉即回到浅灰 #f7f8fa）。 */
.fitem__input.fitem__input--white {
  background: #ffffff;
}

/* 🆕 第252批（2026-10-16 用户追加需求）：「**场景**新增页（#edit/scene）产品排」——
   用户原话「产品编号后边加上调色开关，和产品编号一行，调色开关占 25% 宽度，
   调色开关对应双包清单表中的调色字段」
   ⇒ 产品编号 75% : 调色 25% = **3 : 1**（类名 frow--w31，由 withSplitClass 按 split [3,1] 拼出）。
   · ⚠️ 双包页（#edit/dbllist、#edit/qb）第246批是 **17 : 8**，走的是 .frow--w178 —— **本类与它并存、
     互不影响**（页面按 sceneAdd 分流给 split，见 app.js buildDblAddRows 的 dSplit1）。
   · 「调色开关对应双包清单表中的调色字段」= 字段设置层面 scene.f_muuerysr 是
     relation → dbllist.f_muuerysr（见 tmp/upd252-scene-fields.php），页面控件仍是开关。
   🔴 可翻转点 = 这两条 flex（改回 17 / 8 即与双包页同宽，但要连 app.js 那个三元一起改）。 */
.frow--w31 > .fitem:nth-child(1) {
  flex: 3;
}

.frow--w31 > .fitem:nth-child(2) {
  flex: 1;
}

/* 🔴 第五十七批（2026-10-05 用户需求）：「4 个字段放一排均分左右位置」
   ⇒ 「数量 / 单价 / 库存 / 使用场景」四格一排、各占 1/4（类名 frow--w1111）。
   翻转点 = 引擎 orderRowsWithStock 那一行的 items.map(function () { return 1; })。 */
.frow--w1111 > .fitem:nth-child(1) {
  flex: 1;
}

.frow--w1111 > .fitem:nth-child(2) {
  flex: 1;
}

.frow--w1111 > .fitem:nth-child(3) {
  flex: 1;
}

.frow--w1111 > .fitem:nth-child(4) {
  flex: 1;
}

/* 🔴 第七十批补充需求（2026-10-06 用户截图 + 已确认口径）：新增销售订单页的产品行改成与
   「新增双包清单页」同一套 ——「数量 / 平方单价 / 面积 / 总价」四格，外加本页独有的
   「库存」格 ⇒ 五格一排、各占 1/5（类名 frow--w11111，与小程序 form-row--w11111 对应）。
   翻转点 = 页面 buildOrderAddRows 里 items2.map(function () { return 1; })。 */
.frow--w11111 > .fitem:nth-child(1) {
  flex: 1;
}

.frow--w11111 > .fitem:nth-child(2) {
  flex: 1;
}

.frow--w11111 > .fitem:nth-child(3) {
  flex: 1;
}

.frow--w11111 > .fitem:nth-child(4) {
  flex: 1;
}

.frow--w11111 > .fitem:nth-child(5) {
  flex: 1;
}

/* 🔴 第六十三批（2026-10-05 用户需求 2）：「新增双包订单页面内容，原样拷贝新增销售订单」
   ⇒ 双包页的「产品排」= 产品 + 调色 两格（本批当时写的是三格，后来「使用场景」挪到第二排）。
   产品占 4/6、调色开关占 1/6（类名 frow--w411；小程序端那份走内联 flex，不再用同名类）。
   翻转点 = 页面 buildDblAddRows 里 dSplit1 那一行（xi === 0 ? 4 : 1）。
   🔴 第215批（2026-10-12）：**新增销售订单页**的产品排已改用新类 .frow--w1659（16 : 5 : 9），
      本类在网页端**不再被任何页面产生**（双包页只有两格 ⇒ 生成的是 .frow--w41）。
      按本项目「新增类、不覆盖旧类」的纪律**原样保留**，不删 —— 以防历史/其它引用连坐。
      如果真的确认全项目零引用，可在下一轮死码清理里一并删掉。 */
.frow--w411 > .fitem:nth-child(1) {
  flex: 4;
}

.frow--w411 > .fitem:nth-child(2) {
  flex: 1;
}

.frow--w411 > .fitem:nth-child(3) {
  flex: 1;
}

/* 这两格变窄后值太长会把格子撑破 ⇒ 省略号收尾（只影响显示，不影响取值）。 */
.frow--w411 > .fitem:nth-child(2) .fitem__input,
.frow--w411 > .fitem:nth-child(2) .fitem__ro,
.frow--w411 > .fitem:nth-child(3) .fitem__input,
.frow--w411 > .fitem:nth-child(3) .fitem__ro {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 🔴🔴 第215批（2026-10-12 用户需求）：「#edit/saleslist 页面产品编号宽度缩小20%，
   空间分配给使用场景。」⇒ **新增销售订单页**的产品排比例由 4 : 1 : 1 改成 16 : 5 : 9。
     产品编号 16/30 = 53.33%（原 66.67%，相对缩小 20%）
     调色      5/30 = 16.67%（不变）
     使用场景  9/30 = 30.00%（原 16.67%）
   口径：产品编号 4/6 × 0.8 = 3.2/6，腾出的 0.8/6 全部并给使用场景（1/6 → 1.8/6）；
   三数同乘 5 去小数。和 = 30 = 整排，不改动排内格数。
   ⚠️ 用**新类**而不是改 .frow--w411 —— 本项目纪律「新增类、不覆盖旧类」，免得其它引用连坐。
   ⚠️ 只服务新增销售订单页（app.js 的 buildOrderAddRows）；新增双包订单页的产品排是
      产品 4 : 调色 1（.frow--w41），**不受本类影响**。
   翻转点 = app.js 里 split1 压入的 16 / 5 / 9（两处一起改）。 */
.frow--w1659 > .fitem:nth-child(1) {
  flex: 16;
}

.frow--w1659 > .fitem:nth-child(2) {
  flex: 5;
}

.frow--w1659 > .fitem:nth-child(3) {
  flex: 9;
}

/* 「调色」那一格仍只有 1/6 ⇒ 值太长就省略号，别把整行撑破（只影响显示，不影响取值）。
   使用场景已加宽到 30% ⇒ **刻意不加**省略号，内容尽量完整显示。 */
.frow--w1659 > .fitem:nth-child(2) .fitem__input,
.frow--w1659 > .fitem:nth-child(2) .fitem__ro {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 🔴 第五十七批：本类现在挂在「产品 + 配色开关」那一排 —— 产品占 5/6、配色开关占 1/6。
   （第五十二批~第五十六条是「产品 + 库存」那一排；第五十七批「库存」已挪到「单价」排。）
   对应引擎 orderRowsWithStock 给出的 split = [5, 1]（小程序翻 form-row--w51）。
   同样靠 :nth-child 提高具体度盖住 .frow > .fitem 的等分。 */
.frow--w51 > .fitem:first-child {
  flex: 5;
}

.frow--w51 > .fitem:last-child {
  flex: 1;
}

/* 库存格窄了一半多 ⇒ 数字放不下就省略号，别把这一行撑破（完整值在标题里） */
.frow--w51 > .fitem:last-child .fitem__input,
.frow--w51 > .fitem:last-child .fitem__ro {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 第五十一批：新增订单页「继续加产品 / 删除本产品」——一排两格，落在备注下方 */
.linebar {
  display: flex;
  align-items: stretch;
  margin-top: 10px;
  background: #ffffff;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.04);
}

.linebar__btn {
  flex: 1;
  padding: 13px 0;
  text-align: center;
  font-size: 15px;
  color: #12924a;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.linebar__btn + .linebar__btn {
  border-left: 1px solid #f0f0f0;
}

.linebar__btn--del {
  color: #fa5151;
}

.linebar__btn--hover,
.linebar__btn:active {
  background: #f7f7f7;
}

/* 第五十三批（2026-10-05 用户需求）：「前一条产品信息填完全后，方可执行『继续加产品』。」
   ⇒ 上一条没填完时按钮变灰（点下去也会被拦，见 app.js 的 onAddLine）。
   唯一可翻转点 = 这条规则 + onAddLine 里那句 orderLineReady 判断。 */
.linebar__btn.is-off {
  color: #c8c9cc;
}

/* 🔴 第五十三批（2026-10-05 用户需求）：「一种产品和另一种产品，分别用蓝色大括号隔开。」
   ⇒ 每个产品一组（「产品+库存」排 + 「数量+单价+使用场景」排），用**蓝色左竖条 + 浅蓝底 + 圆角**
   圈成一个整体，像一对大括号把这一组括起来。
   做法：行仍是平铺的兄弟节点（.frow.linebox），第一 / 最后一排各补一条边，中间那排只有左竖条
   ⇒ 几排拼起来就是一个连续的框。不改 row 结构、不动渲染与保存链路。
   唯一可翻转点 = 下面这几条 .linebox 规则（删掉即回到「产品行与普通字段无差别」）。 */
.linebox {
  margin: 0 12px;
  background: #f5f8ff;
  border-left: 4px solid #3b7bf6;
  padding-left: 6px;
}

.linebox--first {
  margin-top: 10px;
  padding-top: 6px;
  border-top: 1px solid #d6e2fb;
  border-right: 1px solid #d6e2fb;
  border-top-right-radius: 12px;
  border-top-left-radius: 4px;
}

.linebox--last {
  margin-bottom: 12px;
  padding-bottom: 6px;
  border-bottom: 1px solid #d6e2fb;
  border-right: 1px solid #d6e2fb;
  border-bottom-right-radius: 12px;
  border-bottom-left-radius: 4px;
}

/* 组内的字段卡别再各带白底 / 圆角 / 间隔，否则蓝色底被盖住、蓝竖条被切成一段段 */
.linebox > .fitem {
  margin-bottom: 0;
  box-shadow: none;
  background: transparent;
  border-radius: 0;
}

.fitem {
  background: #ffffff;
  border-radius: 10px;
  padding: 12px 14px;
  margin-bottom: 10px;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.04);
}

.fitem__label {
  display: block;
  font-size: 12px;
  color: var(--t3);   /* 字段名加深：原 var(--t4) #999 偏浅（用户要「文字加深、框内提示保持浅色」） */
  margin-bottom: 6px;
}

.fitem__req {
  color: var(--red);
  margin-left: 2px;
}

.fitem__input,
.fitem__area,
.fitem__picker {
  width: 100%;
  min-height: 36px;
  line-height: 36px;
  background: #f7f8fa;
  border-radius: 8px;
  padding: 0 12px;
  font-size: 16px; /* 必须 ≥16px：iOS 点输入框自动放大的唯一触发条件 */
  color: var(--t1);
}

.fitem__area {
  min-height: 68px;
  line-height: 1.5;
  padding: 9px 12px;
  resize: none;
}

/* 只读展示（订单金额 = 单价 × 数量，自动算出不可输入） */
.fitem__ro {
  min-height: 36px;
  line-height: 36px;
  background: #f7f8fa;
  border-radius: 8px;
  padding: 0 12px;
  font-size: 16px;
  font-weight: 600;
  color: var(--t2);
}

/* 第三十九批（2026-10-04 用户需求）：库存不足的提示色 ——
   「数量」输入框 与「库存」只读格 一起变红（只做视觉提示，不拦保存、不改值）。 */
.fitem__input--danger {
  color: #fa5151;
}

.fitem__ro--danger {
  color: #fa5151;
}

/* 第三十九批：说明文案放在输入框**下方**时用（如「（默认显示未收金额）」） */
.fitem__hint--below {
  display: block;
  margin-left: 0;
  margin-top: 4px;
  line-height: 1.4;
}

.fitem__picker {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.fitem__picker.is-ph {
  color: var(--t5);
}

.fitem__picker::after {
  content: "›";
  font-size: 18px;
  color: #c8c9cc;
  margin-left: 6px;
}

/* 下拉/关联字段：原生 select 藏在 picker 壳里，保留系统选择器（手机上体验最好） */
.fitem__picker select {
  flex: 1;
  min-width: 0;
  height: 36px;
  font-size: 16px; /* 同上：select 也参与 iOS 自动放大 */

  color: var(--t1);
  background: none;
  padding: 0;
}

.fitem__picker.is-ph select {
  color: var(--t5);
}

/* ---------- 第245批：「使用场景」多选（胶囊 + 自绘弹层）----------
   仅双包清单表（dbllist）用得上；别的地方不会渲染这些类。
   ⚠️ 收起态允许**换行**（选得满时格会变高）—— 这是有意的，别加
      overflow:hidden / white-space:nowrap，否则第 3 个场景会被静默裁掉。 */
.scenepick {
  background: #f7f8fa;
  border-radius: 8px;
  padding: 6px 10px;
  min-height: 36px;
  cursor: pointer;
}

.scenepick__box {
  display: flex;
  flex-wrap: wrap;      /* 选得满自动换行，不裁切 */
  gap: 5px;
  align-items: center;
}

.scenepick__ph {
  font-size: 15px;
  line-height: 22px;
  color: var(--t5);
}

.scenepick input[type="hidden"] {
  display: none;
}

.scenechip {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  height: 22px;
  padding: 0 8px;
  border-radius: 11px;
  background: #eaf3ff;
  border: 1px solid #c9defb;
  color: #0a68d8;
  font-size: 13px;
  line-height: 20px;
  white-space: nowrap;
}

.scenechip__x {
  font-size: 14px;
  color: #7fb0ee;
  cursor: pointer;
  padding-left: 1px;
}

.scenechip__x:hover {
  color: #0a68d8;
}

.scenechip--add {
  background: #fff;
  border: 1px dashed #d6d7dc;
  color: var(--t4);
}

/* 弹层里的候选项：圆圈勾选（多选语义，不能用对勾方块） */
.sceneopt {
  display: flex;
  align-items: center;
  gap: 10px;
}

.sceneopt__box {
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 1.6px solid #d3d4d8;
  box-sizing: border-box;
}

.sceneopt.is-on {
  color: #0a68d8;
  font-weight: 600;
}

.sceneopt.is-on .sceneopt__box {
  background: #0a68d8;
  border-color: #0a68d8;
  box-shadow: inset 0 0 0 3.5px #fff;
}

.fitem__row {
  display: flex;
  gap: 8px;
}

.fitem__row > * {
  flex: 1;
  min-width: 0;
}

.fitem__count {
  margin-top: 4px;
  font-size: 11px;
  color: var(--t5);
  text-align: right;
}

.fitem__err {
  margin-top: 4px;
  font-size: 12px;
  color: var(--red);
}

.fitem__sw {
  display: flex;
  align-items: center;
  min-height: 36px;
}

/* 第三十五批：开关右侧的说明文案（如「（默认打开=需要施工）」）——只挂在新增订单页的开关上 */
.fitem__hint {
  margin-left: 10px;
  font-size: 13px;
  color: var(--t4);
}

/* 开关 */
.sw {
  position: relative;
  flex: none;
  width: 50px;
  height: 30px;
  border-radius: 15px;
  background: #e5e5e5;
  transition: background 0.18s;
}

.sw::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: #ffffff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
  transition: transform 0.18s;
}

.sw.is-on {
  background: var(--green);
}

.sw.is-on::after {
  transform: translateX(20px);
}

.sw.is-disabled {
  opacity: 0.5;
}

/* 🆕 第226批（2026-10-13 用户需求）：团队页「岗位」**多选**胶囊。
   🔴 自绘（不用原生 input[type=checkbox]）—— 全局 reset 会把原生复选框压成 0×0（见文件顶部 reset）。 */
.rolepick {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 2px 0;
}

.rolepick__item {
  flex: none;
  padding: 6px 14px;
  border: 1px solid var(--line2);
  border-radius: 16px;
  background: var(--card);
  color: var(--t3);
  font-size: 14px;
  line-height: 1.2;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
}

.rolepick__item.is-on {
  border-color: var(--green);
  background: var(--green-l);
  color: var(--green);
  font-weight: 600;
}

/* 底部保存条 */
.footbar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 50;
  display: flex;
  gap: 10px;
  padding: 10px 12px calc(10px + var(--safe-b));
  background: rgba(255, 255, 255, 0.96);
  border-top: 1px solid var(--line);
  backdrop-filter: blur(6px);
}

.footbar__btn {
  flex: 1;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  background: #f2f3f5;
  border-radius: 8px;
  color: var(--t2);
}

.footbar__btn--primary {
  background: var(--green);
  color: #ffffff;
  font-weight: 600;
}

.footbar__btn--danger {
  background: #fff0f0;
  color: var(--red);
  flex: none;
  padding: 0 18px;
}

.footbar__btn:active {
  opacity: 0.75;
}

.screen--withbar {
  padding-bottom: calc(84px + var(--safe-b));
}

/* ---------- 系统管理：分区 / 行 ---------- */
.sec {
  padding: 0 12px;
  margin-bottom: 18px;
}

.sec__head {
  padding: 0 4px 8px;
}

.sec__title {
  display: block;
  font-size: 14px;
  font-weight: 600;
  color: var(--t1);
}

.sec__tip {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  color: var(--t4);
  line-height: 1.5;
}

.sec__card {
  background: #ffffff;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.04);
}

.row {
  display: flex;
  align-items: center;
  min-height: 46px;
  padding: 8px 14px;
  border-bottom: 1px solid var(--line);
}

.row:last-child {
  border-bottom: none;
}

.row--tap:active {
  background: #fafbfc;
}

.row__label {
  flex: none;
  width: 88px;
  font-size: 14px;
  color: var(--t2);
}

.row__value {
  flex: 1;
  font-size: 13px;
  color: var(--t4);
  text-align: right;
  word-break: break-all;
}

.row__value--warn {
  color: #ff976a;
}

.row__arrow {
  flex: none;
  margin-left: 8px;
  font-size: 17px;
  color: #c8c9cc;
  line-height: 1;
}

.row__input {
  flex: 1;
  height: 36px;
  line-height: 36px;
  font-size: 16px; /* 必须 ≥16px，见文件末尾说明 */

  color: var(--t1);
  text-align: right;
  background: #f7f8fa;
  border-radius: 6px;
  padding: 0 10px;
}

.hintbox {
  margin: 10px 14px;
  padding: 10px 12px;
  font-size: 12px;
  line-height: 1.6;
  color: #7a6a3a;
  background: #fffbe6;
  border-radius: 8px;
}

/* 分段控件 */
.seg {
  flex: none;
  display: flex;
  border: 1px solid var(--line2);
  border-radius: 7px;
  overflow: hidden;
}

.seg__item {
  padding: 5px 12px;
  font-size: 12.5px;
  color: var(--t3);
  background: #ffffff;
}

.seg__item + .seg__item {
  border-left: 1px solid var(--line2);
}

.seg__item.is-on {
  background: var(--green);
  color: #ffffff;
}

/* 权限矩阵 */
.role__head {
  display: flex;
  align-items: center;
  padding: 12px 14px 6px;
}

.role__name {
  font-size: 14px;
  font-weight: 600;
  color: var(--t1);
}

.role__lock {
  margin-left: 8px;
  padding: 1px 7px;
  font-size: 11px;
  color: var(--green);
  background: var(--green-l);
  border-radius: 4px;
}

.perm {
  display: flex;
  align-items: center;
  padding: 7px 14px;
  border-top: 1px solid var(--line);
}

.perm__text {
  flex: 1;
  min-width: 0;
}

.perm__label {
  font-size: 13.5px;
  color: var(--t2);
}

.perm__desc {
  font-size: 11px;
  color: var(--t4);
  line-height: 1.4;
}

.perm__sw {
  flex: none;
  margin-left: 10px;
}

.role__note {
  padding: 8px 14px 12px;
  font-size: 11px;
  color: var(--t4);
}

/* ---------- 字段设置列表 ---------- */
.fld {
  display: flex;
  align-items: center;
  background: #ffffff;
  border-radius: 10px;
  padding: 11px 12px;
  margin: 0 12px 8px;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.04);
}

.fld__main {
  flex: 1;
  min-width: 0;
}

.fld__label {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--t1);
  word-break: break-all;
}

.fld__meta {
  margin-top: 4px;
  font-size: 11px;
  color: var(--t4);
  line-height: 1.5;
}

.fld__ops {
  flex: none;
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: 8px;
}

.fld__op {
  min-width: 32px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  color: var(--t3);
  background: #f4f5f7;
  border-radius: 6px;
  padding: 0 7px;
}

.fld__op:active {
  opacity: 0.7;
}

.fld__op--danger {
  color: var(--red);
  background: #fff5f5;
}

.fld__op.is-off {
  opacity: 0.35;
}

.badge {
  display: inline-block;
  margin-left: 6px;
  padding: 0 5px;
  font-size: 10.5px;
  line-height: 16px;
  border-radius: 4px;
  vertical-align: 1px;
}

.badge--sys {
  color: #7a6a3a;
  background: #fffbe6;
}

.badge--sens {
  color: #fa5151;
  background: #fff0f0;
}

/* ---------- 弹层 / 遮罩 ---------- */
.layer {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: none;
}

.layer.is-open {
  display: block;
}

.mask {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.mask--center {
  align-items: center;
}

.sheet {
  width: 100%;
  max-width: 560px;
  max-height: 86vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  background: #ffffff;
  border-radius: 16px 16px 0 0;
  padding: 20px 16px calc(18px + var(--safe-b));
  animation: slideUp 0.2s ease-out;
}

@keyframes slideUp {
  from {
    transform: translateY(30px);
    opacity: 0.6;
  }
  to {
    transform: none;
    opacity: 1;
  }
}

.dlg {
  width: calc(100% - 64px);
  max-width: 320px;
  background: #ffffff;
  border-radius: 12px;
  overflow: hidden;
  text-align: center;
}

.dlg__title {
  padding: 22px 20px 6px;
  font-size: 16px;
  font-weight: 600;
  color: var(--t1);
}

.dlg__body {
  padding: 0 20px 20px;
  font-size: 13.5px;
  color: var(--t3);
  line-height: 1.6;
  word-break: break-all;
}

.dlg__btns {
  display: flex;
  border-top: 1px solid var(--line);
}

.dlg__btn {
  flex: 1;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  color: var(--t2);
}

.dlg__btn + .dlg__btn {
  border-left: 1px solid var(--line);
}

.dlg__btn--primary {
  color: var(--green);
  font-weight: 600;
}

.dlg__btn--danger {
  color: var(--red);
  font-weight: 600;
}

.dlg__btn:active {
  background: #fafbfc;
}

.sheet__title {
  font-size: 16px;
  font-weight: 600;
  color: var(--t1);
  text-align: center;
  margin-bottom: 4px;
}

.sheet__tip {
  font-size: 11.5px;
  color: var(--t4);
  line-height: 1.6;
  margin-bottom: 14px;
  text-align: center;
}

.checks {
  display: flex;
  flex-wrap: wrap;
}

.check {
  display: flex;
  align-items: center;
  width: 50%;
  padding: 8px 0;
}

.check--full {
  width: 100%;
}

/* 🆕 第161批：列设置弹层里「跟随字段设置」的锁定区（本页字段列，不在此增删） */
.checks--lock {
  border-bottom: 1px dashed #e2e4e8;
  padding-bottom: 6px;
  margin-bottom: 4px;
}

.check--lock {
  opacity: .55;
}

.check__lock {
  margin-left: 6px;
  padding: 0 4px;
  font-size: 11px;
  line-height: 15px;
  color: #8a8f99;
  border: 1px solid #dcdee2;
  border-radius: 3px;
}

.check__t {
  margin-left: 8px;
  font-size: 13.5px;
  color: var(--t2);
}

.cbox {
  flex: none;
  width: 19px;
  height: 19px;
  border: 1px solid #d0d2d6;
  border-radius: 50%;
  position: relative;
}

.cbox.is-on {
  background: var(--green);
  border-color: var(--green);
}

.cbox.is-on::after {
  content: "";
  position: absolute;
  left: 6px;
  top: 3px;
  width: 5px;
  height: 9px;
  border: solid #ffffff;
  border-width: 0 2px 2px 0;  transform: rotate(45deg);
}

/* ---- 列设置弹层（仅限 #col-list，不影响别处的 .check 两列勾选布局） ---- */
#col-list {
  display: block;
  max-height: 50vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

#col-list .check {
  width: 100%;
  padding: 10px 4px;
  border-bottom: 1px solid var(--line);
}

#col-list .check--on .check__t {
  color: var(--t1);
  font-weight: 600;
}

.sheet__tip2 {
  font-size: 12px;
  color: var(--t2);
  text-align: center;
  margin: -6px 0 10px;
}

.colmv {
  flex: none;
  width: 28px;
  height: 26px;
  margin-left: 6px;
  border: 1px solid var(--line2);
  border-radius: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  color: var(--t2);
  background: #f6f7f9;
  user-select: none;
  -webkit-user-select: none;
}

.colmv--dis {
  color: #c3c6cb;
  background: #f1f2f4;
}

.prow {
  display: flex;
  align-items: center;
  padding: 9px 0;
  border-bottom: 1px solid var(--line);
}

.prow__label {
  flex: none;
  width: 74px;
  font-size: 13.5px;
  color: var(--t2);
}

.prow__input {
  flex: 1;
  height: 38px;
  line-height: 38px;
  font-size: 16px; /* 必须 ≥16px，见文件末尾说明 */

  color: var(--t1);
  background: #f7f8fa;
  border-radius: 8px;
  padding: 0 12px;
}

.sheet__btns {
  display: flex;
  gap: 10px;
  margin-top: 18px;
}

.sheet__btn {
  flex: 1;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  color: var(--t2);
  background: #f2f3f5;
  border-radius: 8px;
}

.sheet__btn--primary {
  background: var(--green);
  color: #ffffff;
}

.sheet__btn--danger {
  background: var(--red);
  color: #ffffff;
}

.sheet__btn:active {
  opacity: 0.75;
}

.sheet__sec {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}

.sheet__secT {
  font-size: 12px;
  color: var(--t4);
  margin-bottom: 8px;
}

/* ---------- 登录页 ---------- */
.login {
  min-height: 100vh;
  padding: 64px 24px 32px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* 🆕 第302批（用户）：「把首页的绿底LOGO『美缝』换成图片」——
   原样式 = 64×64 绿底渐变圆角方块 + 「美缝」两个字；现在换成卓高官方商标图
   （红底白字、比例约 3.9:1）⇒ 容器只保留圆角与阴影，尺寸交给图片本身。
   🔴 可翻转点 = 下面 height：整体（含宽度）就由它一个数决定（56px 左右最协调；给 40px 更秀气、72px 更醒目）。 */
.login__logo {
  display: block;
  height: 56px;
  width: auto;
  max-width: 100%;
  border-radius: 12px;
  box-shadow: 0 6px 18px rgba(214, 24, 34, 0.22);
}

.login__title {
  margin-top: 16px;
  font-size: 20px;
  font-weight: 700;
  color: var(--t1);
}

.login__sub {
  margin-top: 6px;
  font-size: 12px;
  color: var(--t4);
}

.login__card {
  width: 100%;
  max-width: 420px;
  margin-top: 28px;
  background: #ffffff;
  border-radius: 14px;
  padding: 6px 16px 16px;
  box-shadow: 0 2px 14px rgba(0, 0, 0, 0.05);
}

.lg__row {
  display: flex;
  align-items: center;
  border-bottom: 1px solid var(--line);
}

.lg__row span {
  flex: none;
  width: 60px;
  font-size: 14px;
  color: var(--t3);
}

.lg__row input {
  flex: 1;
  height: 50px;
  font-size: 16px; /* 必须 ≥16px，见文件末尾说明 */

  color: var(--t1);
}

.lg__btn {
  width: 100%;
  height: 46px;
  margin-top: 18px;
  background: var(--green);
  color: #ffffff;
  font-size: 16px;
  font-weight: 600;
  border-radius: 8px;
}

.lg__btn:active {
  background: var(--green-d);
}

.lg__btn[disabled] {
  opacity: 0.55;
}

.login__tip {
  margin-top: 18px;
  max-width: 420px;
  font-size: 11.5px;
  line-height: 1.7;
  color: var(--t4);
  text-align: left;
  text-indent: 2em;
}

/* 🆕 第318批（2026-11-02）：登录页备案号
   备案核查是匿名访问，登录页才是第一屏 ⇒ 编号必须在这一页可见。
   ⚠️ 只新增这一组类，不动文件开头 70~84 行的 reset（铁律 5）。 */
.login__icp {
  margin-top: 18px;
  font-size: 12px;
  line-height: 1.6;
  color: var(--t4);
  text-align: center;
  word-break: break-all;
}

.login__icp a {
  color: var(--t4);
  text-decoration: none;
}

.login__icp a:hover {
  color: var(--t3);
  text-decoration: underline;
}

.login__foot {
  margin-top: auto;
  padding-top: 32px;
  font-size: 11px;
  color: var(--t5);
  text-align: center;
}

/* ---------- toast ---------- */
.toast-wrap {
  position: fixed;
  left: 0;
  right: 0;
  bottom: calc(72px + var(--safe-b));
  z-index: 200;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  pointer-events: none;
}

.toast {
  max-width: 78%;
  padding: 10px 16px;
  font-size: 13.5px;
  line-height: 1.5;
  color: #ffffff;
  background: rgba(0, 0, 0, 0.78);
  border-radius: 8px;
  text-align: center;
  word-break: break-all;
  animation: fadeIn 0.15s ease-out;
}

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

/* ---------- 空态 / 说明 ---------- */
.note {
  padding: 8px 16px 0;
  font-size: 11.5px;
  line-height: 1.7;
  color: var(--t4);
}

.foot {
  padding: 24px 16px 32px;
  text-align: center;
  font-size: 11px;
  color: var(--t5);
}

@media (min-width: 560px) {
  .home,
  .form,
  .list {
    max-width: 560px;
    margin: 0 auto;
  }

  .sec,
  .bar,
  .meta,
  .acts,
  .fld {
    max-width: 560px;
    margin-left: auto;
    margin-right: auto;
  }

  .table--inset {
    max-width: 536px;
    margin-left: auto;
    margin-right: auto;
    /* 🔴 第一百二十八批（2026-10-09）：原 display:block —— 基础 .table 现在是**表格布局**
       （display:table），这里必须跟着改，否则宽屏（≥560px）下：
         表格变 block，而它里面的 .tr 仍是 table-row ⇒ 浏览器把每一行各自包进一个「匿名表」
         ⇒ 行的宽度单独按内容算（实测 648px），与表格容器的 1280px 对不上
         ⇒ **表格右侧一大片空白**（2026-10-09 截图实测到的坏样子）。
       🔴 可翻转点 = 这一行（改回 display:block 即回到「宽屏下表格右侧留白」的坏样子）。
       ⚠️ 故意**不写** min-width:0：基础 .table 带 min-width:100%，而 min-width 优先于 max-width
          ⇒ 上面那个 536px 从第七十七批起就是条「被 min-width 压住的死规则」（实测表格宽度
          一直是内容区的整宽），本批保持原样、不顺手改变宽屏下的表格宽度。 */
    display: table;
  }
}

/* ==========================================================================
   禁止缩放 · 最后一道保险
   iOS Safari 有一条硬规则：**输入框（input / textarea / select）字号小于 16px 时，
   点它就会强制把整个页面放大**。而页面设了 maximum-scale=1（禁缩放）后，iOS 放大完
   又拒绝缩回 —— 结果就是「页面被放大后卡住，怎么都缩不小」。两者互相打架。
   唯一可靠的办法：页面上每个输入控件的字号都 ≥ 16px。
   这条规则加 !important，是为了**以后新增的输入框也自动受保护**
   （只约住字号，不影响任何布局尺寸——输入框高度/圆角/内边距都还是原样）。
   🆕 第一百一十三批（2026-10-09）：复核确认这条是最关键的一层（双击/点输入框放大都靠它兜底），
   全文件**保留且仅保留这一条**；同批另补了 JS 层「双击 touchend 兜底」与 .ptd__inp 字号 → 16px。
   ========================================================================== */
input,
select,
textarea {
  font-size: 16px !important;
}

/* ---- 订单新增页：历史记录联想 ---- */
.suggest {
  border: 1px solid var(--line2);
  border-radius: 8px;
  margin-top: 4px;
  background: #ffffff;
  overflow: hidden;
}

.suggest__item {
  padding: 10px 12px;
  font-size: 14px;
  color: var(--t2);
  border-bottom: 1px solid var(--line);
  cursor: pointer;
}

.suggest__item:last-child {
  border-bottom: none;
}

.suggest__item:active {
  background: var(--green-l);
}

/* 只读视图页只剩「列设置」一个按钮：别 flex 拉满整行，否则像条主操作栏 */
.acts--single .act {
  flex: 0 0 auto;
  padding: 0 18px;
}

/* ==========================================================================
   第二十四批：财务页（老板专用）—— **已移除**（2026-10-03 需求变更）
   财务页改用通用列表页（#view/financeDetail），原来那套 .fin / .finrow /
   .aform__btn--off 样式全部成了死代码，已整块删除。
   旧样式另存一份在 artifacts/备份-财务专用页已移除-2026-10-03/（回滚兜底）。
   ========================================================================== */

/* ==========================================================================
   第三十三批（2026-10-03 用户需求）：系统管理 →「数据管理」改版
   备份列表铺在页面上（.bkl），点一条选中高亮（.is-on）；
   小节标题 .sub；两个操作按钮复用 .acts / .act（见第 602 行）。
   样式与小程序端 pages/settings/index.wxss 的同名类保持同一套观感。
   ========================================================================== */
.sub {
  padding: 14px 16px 6px;
  font-size: 12px;
  color: var(--t4);
}

.bkl__empty {
  padding: 14px;
  font-size: 12px;
  color: var(--t4);
  line-height: 1.6;
}

.bkl__item {
  display: flex;
  align-items: center;
  min-height: 46px;
  padding: 8px 14px;
  border-bottom: 1px solid var(--line);
  border-left: 3px solid transparent;
}

.bkl__item:last-child {
  border-bottom: none;
}

.bkl__item:active {
  background: #fafbfc;
}

/* 选中态：左侧绿条 + 浅绿底 + 名称加粗（与小程序端逐字一致） */
.bkl__item.is-on {
  background: var(--green-l);
  border-left-color: var(--green);
}

.bkl__item.is-on .bkl__name {
  font-weight: 600;
  color: var(--green-d);
}

.bkl__name {
  flex: 1;
  font-size: 13px;
  color: var(--t2);
  word-break: break-all;
}

.bkl__meta {
  flex: none;
  margin-left: 8px;
  font-size: 11px;
  color: var(--t4);
}

/* ══ 第四十一批（2026-10-04）：施工费结算页（条件区 + 统计卡 + 复选框表格 + 批量支付）══
   这套类只被 app.js 的 drawFeeSettle 用到，其他页面一行不动。
   布局与小程序端 pages/view/list 的 feeMode 分支同构（那边用 rpx，这里用 px）。 */

.fsf {
  margin: 0 0 12px;
  padding: 14px 14px 8px;
  background: #ffffff;
  border-radius: 12px;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.04);
}

.fsf__row {
  display: flex;
  gap: 12px;
  margin-bottom: 12px;
}

.fsf__item {
  flex: 1;
  min-width: 0;
}

.fsf__item--full {
  flex: 1 1 100%;
}

.fsf__label {
  margin-bottom: 5px;
  font-size: 12px;
  color: #888888;
}

.fsf__pick,
.fsf__input {
  width: 100%;
  height: 38px;
  padding: 0 10px;
  /* 🔴 输入控件字号必须 ≥ 16px：小于 16px 时 iOS Safari 一点输入框就把页面放大、
     且放大后缩不回来（项目红线，护栏 verify-web.js 会拦）。 */
  font-size: 16px;
  color: var(--t1);
  background: #f7f8fa;
  border: 1px solid #eceef1;
  border-radius: 8px;
  box-sizing: border-box;
  font-family: inherit;
}

.fsf__input::placeholder {
  color: #bbbbbb;
}

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

.fsf__dates .fsf__input {
  flex: 1;
  min-width: 0;
}

.fsf__tilde {
  flex: none;
  font-size: 13px;
  color: #bbbbbb;
}

/* 「清空 / 重置条件」这类文字按钮：不是主操作，用链接式样式 */
.fsf__clr {
  flex: none;
  padding: 4px 8px;
  font-size: 13px;
  color: #1268d6;
  background: transparent;
  border: none;
  cursor: pointer;
  font-family: inherit;
}

/* 结算状态三段（未支付 / 已支付 / 全部），选中段绿底白字 */
.fsf__segs {
  display: flex;
  height: 38px;
  background: #f7f8fa;
  border: 1px solid #eceef1;
  border-radius: 8px;
  overflow: hidden;
}

.fsf__seg {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  color: #666666;
  cursor: pointer;
}

.fsf__seg--on {
  background: var(--green);
  color: #ffffff;
  font-weight: 600;
}

.fsf__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 4px 0 6px;
  border-top: 1px solid #f0f1f3;
  /* 第八十二批·补：说明文案变长了（「数量为空的会列出来，但不能勾选出库」），
     原来的 flex 排布会把「看全部订单」按钮挤到下一行、左右参差不齐。
     ⇒ 说明文字允许换行并自己占满剩余宽度，按钮固定靠右不换行。 */
  gap: 10px;
}

.fsf__note {
  font-size: 11px;
  color: #bbbbbb;
  min-width: 0;
  flex: 1 1 auto;
  line-height: 1.5;
}

.fsf__foot .fsf__clr {
  flex: 0 0 auto;
  white-space: nowrap;
}

/* 结果条：左边「N 条结果 · 已选 M」，右边两个按钮 */
.fsacts {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 0 10px;
}

.fsacts__hint {
  font-size: 13px;
  color: #666666;
}

.fsacts__btns {
  display: flex;
  gap: 8px;
}

/* 小按钮：不参与 .act 的 flex 拉伸（放在 .act 之后，靠同权重后定义覆盖 flex:1） */
.act--sm {
  flex: none;
  height: 34px;
  padding: 0 14px;
  font-size: 13px;
}

/* 不可点状态（权限不足 / 没勾选）—— 只降透明度，点了仍给 toast 说明原因 */
.act--dis {
  opacity: 0.45;
}

/* 复选框列：固定窄列，把第一列默认的 102px 抢回来
   ⚠️ 必须写 .td.td--pick:first-child —— 单类选择器权重低于 .td:first-child */
.td.td--pick {
  flex: none;
  width: 42px;
  padding-left: 10px;
  padding-right: 4px;
}

.td.td--pick:first-child {
  width: 42px;
}

.ckb {
  display: inline-block;
  width: 20px;
  height: 20px;
  line-height: 18px;
  text-align: center;
  font-size: 13px;
  color: #ffffff;
  background: #ffffff;
  border: 1px solid #cfd4dc;
  border-radius: 4px;
  box-sizing: border-box;
}

.ckb--on {
  background: var(--green);
  border-color: var(--green);
}

/* 🆕 第七十六批（2026-10-07 用户需求：「#tables 的记录增加删除按钮」）
   —— 行首勾选框 + 区块级「删除选中」。
   ⚠️ 列宽与方框样式**复用上面既有的 .td--pick / .ckb**（施工费结算页已在用），
      全站复选框保持一个样；这里只补本页特有的三样东西。 */

/* 表头全选框的「半选」：勾了一部分（不是全勾也不是没勾）*/
.ckb--half {
  background: var(--green);
  border-color: var(--green);
  opacity: 0.45;
}

/* 算出来的行 / 员工表这类不给删的行：留一个灰色占位方块，
   让整列对齐（否则可删与不可删的行会左右错位），但明显不可点。 */
.tvpick--no {
  display: inline-block;
  width: 20px;
  height: 20px;
  border: 1px dashed #d8dce3;
  border-radius: 4px;
  box-sizing: border-box;
  cursor: not-allowed;
}

/* 「删除选中」按钮：与同排的「字段设置」同一档样式，但用红色（不可逆操作）*/
.tvdel {
  font-size: 12px;
  color: #d0342c;
  border: 1px solid #d0342c;
  border-radius: 4px;
  padding: 2px 8px;
  cursor: pointer;
  user-select: none;
}

.tvdel:active {
  background: #d0342c;
  color: #fff;
}

/* 没勾选任何行时置灰 —— 仍可点，点了给 toast 提示（别做成点不动的死按钮）*/
.tvdel--off {
  opacity: 0.4;
}

/* 本页整行点击 = 勾选（不是通用列表页的「点行编辑」） */
.fs-row {
  cursor: pointer;
}

.fs-row:active {
  background: #f4f7f5;
}

/* 第八十二批（2026-10-07 用户需求）：出库登记页（#out/register）
   · 复选框 / 表头方块 / 表格全部**复用**上面施工费结算页那套（.td--pick / .ckb / .table--inset），
     这里只补本页特有的两种行态：
   · .or-row--on 已勾选 —— 淡绿底，一眼能看出这次要出哪几行；
   · .or-row--no 库存不足 —— 整行压暗且**不可勾**（点击会给 toast 说明还缺多少）。
     ⚠️ 别用 pointer-events:none —— 用户点了要有反馈（告诉他缺多少），不是当没看见。 */
.or-row {
  cursor: pointer;
}

.or-row--on {
  background: #eaf6ee;
}

.or-row--on:active {
  background: #dcefe2;
}

.or-row--no {
  opacity: 0.5;
}

.or-row--no td:last-child {
  color: #c0392b;
  font-weight: 600;
}

/* 第八十二批·补（2026-10-07 用户需求）：**没有数量**的行照常显示，只是不能勾选出库。
   与「库存不足」分开一个类：压暗程度轻一点，提示字用琥珀色而不是红 ——
   因为这不是「缺货」的问题，是「订单还没填数量」，两者要做的下一步完全不同。
   ⚠️ 选择器要压过上面的 .or-row--no（同样 0.5 权重，靠出现在后面覆盖 opacity）。 */
.or-row--noqty {
  opacity: 0.62;
}

.or-row--noqty td:last-child {
  color: #b8860b;
}

/* 第四十二批（2026-10-04 用户需求）：关联下拉里**已收款**的选项标绿 ——
   订单收款【新增】页的「订单号」下拉：钱已收齐的订单号显示为绿色。
   ⚠️ 桌面 Chrome / Edge / Firefox 认 <option> 的 color；旧 Safari 不认（那时靠内联样式兜底）。
   标记由 mf-data.js 的 relPickMarks 给出，其余关联下拉一个 option 都不加这个类。 */
.fitem__picker option.is-paid {
  color: #12924a;
  font-weight: 600;
}

/* ======================================================================
   🆕 第六十四批（2026-10-05 用户需求）：「表查看」页（#tables）
   9 张逻辑表的明细表格**依次铺开**；横向滚动复用既有的 .tw / .table / .tr / .td。
   ⚠️ 这里只有外观；表名、顺序、列与行全由引擎（TABLE_VIEW_ORDER / tableViewTables /
      tableViewSheet）决定，页面不自己算。
   ====================================================================== */
.tvpage {
  padding-top: 10px;
  padding-bottom: 12px;
}

/* 一张表 = 一个小节（标题行 + 可横向滚动的表格） */
.tvsec {
  margin: 0 12px 18px;
}

.tvsec__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 0 2px 6px;
}

.tvsec__name {
  font-size: 14px;
  font-weight: 600;
  color: var(--t1);
}

.tvsec__cnt {
  font-size: 12px;
  color: var(--t3);
}

/* 🆕 第七十三批（2026-10-06 用户需求 2）：区块标题右侧的操作区 ——
   「字段设置」按钮 + 条数列数并排（原来 .tvsec__head 用 space-between，
   这里多一个元素要自己抱团，否则「字段设置」会被顶到最右、条数跑到中间）。 */
.tvsec__ops {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

.tvsec__fld {
  font-size: 12px;
  color: #1268d6;
  border: 1px solid #1268d6;
  border-radius: 4px;
  padding: 2px 8px;
  cursor: pointer;
  user-select: none;
}

.tvsec__fld:active {
  background: #1268d6;
  color: #fff;
}

/* 🔴🔴 第一百零六批（2026-10-07 用户需求 3）：两张清单**新增页**的「已开产品」表格。
   位置 = 产品栏目（含「继续加产品 / 删除本产品」按钮）的下方、提交栏的上方。
   用户的硬口径：标题**居中显示**；本订单号下**没有记录时整块隐藏**。
   ⚠️ 「隐藏」的做法 = 容器内容为空 ⇒ 这里**绝不能给空容器留高/留白**，
      否则会凭空多出一段空白（看着像坏了）。所以纵向留白只挂在标题上（有表才有标题），
      容器本身只在**有内容时**才吃下边距（:not(:empty)）。
   ⚠️ :empty 对本项目是可靠的 —— 页面把 innerHTML 精确写成 ''（没有空白文本节点）。 */
.opened-sec {
  margin: 0 12px;
}

.opened-sec:not(:empty) {
  margin-bottom: 18px;
}

.opened__title {
  text-align: center;
  font-size: 14px;
  font-weight: 600;
  color: var(--t1);
  padding: 14px 0 6px;
}

/* 🔴 第七十五批（2026-10-06 用户需求）：「#tables 的表格靠左显示，不要居中。」
   ⇒ **只把整张表格的水平位置从居中改成靠左**（.table 是 inline-block，
      外层 .tw 的 text-align 决定它贴左还是居中）。
   ⚠️ 第七十四批做的「列名居中」**保留不动** —— 那条是 .tvpage .tr--head .td，
      写在本块之后、特异性更高，压得住这里的继承。
   ⚠️ 只作用于「表查看」页（.tvpage）—— #queryprint 也复用 .tvsec / .tw，但那边不受影响。
   🔴 可翻转点：如果哪天又要整体居中，把下面那句 left 改回 center 即可（表头居中不受影响）。 */
.tvpage .tw {
  text-align: left;             /* ← 本批唯一改动点：center ⇒ left */
}

.tvpage .table {
  min-width: 0;               /* 覆盖 .table 的 min-width:100%（不铺满） */
  width: auto;
  text-align: left;           /* 表格内部左对齐（数据格一律顶左） */
}

.tvpage .td {
  width: auto;                /* 列宽 = 内容宽度（够显示就行） */
  white-space: nowrap;
  word-break: normal;
}

.tvpage .td:first-child {
  width: auto;
}

/* 🆕 第七十四批（2026-10-06 用户需求）：「#tables 表的标题居中显示，目前是靠左」
   ⇒ **只把表头（列名）居中，数据格仍左对齐**。
   为什么只改表头：表查看页的用途是把原始明细看全，地址/说明这类长文本左对齐更好读；
   而列名就两三个字，居中后一眼能对齐下面那一列的边界。
   ⚠️ 权重说明：下面 .tvpage .table{text-align:left} 会继承到表头格，
      这里用 .tvpage .tr--head .td 特异性更高，压得住。
   🔴 想连数据格也一起居中：把下面那条的 .tr--head 去掉即可。 */
.tvpage .tr--head .td {
  text-align: center;
}

/* ======================================================================
   🆕 第七十七批（2026-10-07 用户需求）：「表格中的记录和字段居中对齐，并完全显示出来」
   用户口径（AskUserQuestion 选定）：
     ① **一屏看全、不用左右滑** —— 长内容（地址 / 订单号）自动折行，行会变高；
     ② **只改 #tables** —— 查询打印页（#queryprint）版式保持原样。
   做法：给 #tables 的表格挂 .table--fit（app.js 里由 cfg.fit 决定），
     把「列宽跟内容走 + 横向滚动」换成「列宽按屏宽自适应 + 文字折行」。

   ⚠️ 为什么用 .table--fit 而不是直接改 .tvpage：
      #queryprint 也复用 .tvsec / .tvpage 同层的 .tw / .table，
      挂在 .tvpage 上会把打印页一起改掉（用户明确只要改 #tables）。
   🔴 可翻转点：把 app.js 里 paintTables 的 fit 改成 false，本页即回到旧版式；
      样式本身不用动（.table--fit 就没人挂了）。 */

/* 表格铺满整行（原来是 inline-block + min-width:0 的内容宽，可以横向滚）*/
.table--fit {
  display: block;
  width: 100%;
  min-width: 0;
}

/* 🔴 第一百二十八批：基础 .tr 已改成 display:table-row —— 这里必须**显式锁回 flex**。
   否则 table-row 的父级是 block（.table--fit 本身是 display:block）⇒
   浏览器会为每一行各自生成一个匿名表 ⇒ 各行独立算列宽 ⇒ 全表错位。
   ⚠️ #tables 页（第七十七批特意要的「一屏看全 + 折行」）本批**不动** ——
      它本来就已「值全显示 + 居中」，满足本批需求，没必要把折行改成横滚。
   🔴 可翻转点 = 这一条与下面 .table--fit .td 的 display（删掉即回到「跟随全局表格布局」）。 */
.table--fit .tr {
  display: flex;
  align-items: stretch;
}

/* 列宽自适应：按内容比例分配、可压缩（但不压到「数字/单词被拆开」）。
   🔴 这里**故意不写 min-width: 0**：flex 项默认 min-width:auto = 内容最小宽度，
      数字（1542）与英文单词会作为一个整体不被拆散 —— 写了 0 就会出现
      「1542 显示成 15 / 42」「电话号码被拆两行」这种看着像乱码的结果。
   ⚠️ 覆盖 .td 的 flex:none（0 0 auto ⇒ 1 1 auto 才允许伸缩）。
   🆕 第一百二十八批：多加一个 display:block —— 基础 .td 现在是 table-cell，
      必须显式改回块级，才能当 flex 子项用（否则 flex 属性全部失效）。 */
.table--fit .td {
  display: block;
  flex: 1 1 auto;
  width: auto;
  /* 完全显示：不截断、不省略、长内容折行 */
  white-space: normal;
  /* 🔴 必须是 break-word（**不能**用 anywhere）：
       anywhere 会把「内容最小宽度」算成 1 个字符 ⇒ 列可以被压到任意窄 ⇒
       数字/电话被从中间拆开（实测 bug）。break-word 只在单个「词」比整列还长时
       才断，平时以词为单位换行 ⇒ 数字与英文单词保持完整。 */
  overflow-wrap: break-word;
  word-break: normal;
  overflow: visible;
  text-overflow: clip;
  /* 记录与字段一律居中（用户需求原话）*/
  text-align: center;
}

/* 🔴 勾选列必须排除在上面那条之外：它是固定窄列，不能参与均分
   （否则勾选框会被拉得很宽）。特异性要比 .table--fit .td 高 ⇒ 多写一个类。 */
.table--fit .td.td--pick {
  flex: none;
  width: 34px;
  min-width: 34px;
  padding-left: 8px;
  padding-right: 2px;
}

.table--fit .td.td--pick:first-child {
  width: 34px;
  min-width: 34px;
}

/* 折行后行高会变，单元格内容顶部对齐更好读（默认 stretch 会把行撑满）
   🔴 第一百二十八批：这一条已合并进上面新增的 `.table--fit .tr`（display:flex 那条），
   此处不再重复定义，只留说明 —— 免得下次有人再写一遍、以为是两套规则。 */

/* 表头文字跟随数据格一起居中（原表头居中规则用的是 .tvpage .tr--head .td，
   特异性低于 .table--fit .td ⇒ 会被压掉，这里补回来并保持居中）*/
.table--fit .tr--head .td {
  text-align: center;
}

/* ======================================================================
   🆕 第七十八批（2026-10-07 用户需求）：「#tables 表格中记录边上增加编辑按钮」
   ⇒ 每行末尾多一列（行内右侧），点「编辑」跳该行底表的编辑页。
   范围（用户口径）= 全部区块（含产品算出来的三块与员工表）；
   权限 = 账号的「修改数据」开关（无权限时整列都不渲染）。
   ⚠️ 这一列**必须在 .tr--head 之内**（表头也要占一格），否则表头比数据行少一格 ⇒ 错位。
   ====================================================================== */

/* 操作列：固定窄列，不参与均分（与勾选列同理）*/
.tvpage .td--act {
  flex: none;
  width: 52px;
  min-width: 52px;
  padding-left: 4px;
  padding-right: 8px;
  text-align: center;
}

.table--fit .td--act {
  flex: none;
  width: 52px;
  min-width: 52px;
}

/* #queryprint 也复用 .tvsec，但那边不渲染编辑列（withEdit:false）⇒ 这条只对 #tables 有效 */

.tvedit {
  display: inline-block;
  font-size: 12px;
  color: #1268d6;
  border: 1px solid #1268d6;
  border-radius: 4px;
  padding: 1px 7px;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

.tvedit:active {
  background: #1268d6;
  color: #fff;
}

/* 不能编辑的行（合成行 / 没底表的）留个灰占位，保持整列对齐 */
.tvedit--no {
  display: inline-block;
  color: #c8ccd4;
  border: 0;
  padding: 1px 7px;
  cursor: not-allowed;
}

/* ======================================================================
   🆕 第六十五批（2026-10-05 用户需求）
     ① 「查询打印」页（#queryprint）：四个按钮 + 每类一张（或多张）明细表 + 「打印」。
     ② 全站表格列宽可调（用户需求 3）：表头右边缘的拖拽手柄 .cw-handle。
   ====================================================================== */
.qppage {
  padding-bottom: 24px;
}

/* 🆕 第七十批（用户需求 · 版式如截图）：查询打印页顶部的「筛选下拉」——
   [表 ▾] 起止日期 [起] ~ [止] [查询]（[清空日期]）。
   ⚠️ 与下面那排 .qptabs 按钮共用同一个 qpTab：下拉改 = 点按钮改，两处始终一致。 */
.qpfilter {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0 12px 10px;
  padding: 10px 12px;
  border: 1px solid var(--line2);
  border-radius: var(--radius);
  background: var(--card);
}

.qpfilter__sel {
  height: 34px;
  padding: 0 10px;
  border: 1px solid var(--line2);
  border-radius: 6px;
  background: var(--card);
  color: var(--t1);
  font-size: 14px;
  min-width: 120px;
}

.qpfilter__lab {
  font-size: 13px;
  color: var(--t3);
}

.qpfilter__date {
  height: 34px;
  padding: 0 8px;
  border: 1px solid var(--line2);
  border-radius: 6px;
  background: var(--card);
  color: var(--t1);
  font-size: 13px;
}

.qpfilter__sep {
  color: var(--t4);
}

.qpfilter__clear {
  font-size: 13px;
  color: var(--t4);
  cursor: pointer;
  text-decoration: underline;
}

.qptabs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0 12px 14px;
}

.qptab {
  padding: 6px 16px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: #ffffff;
  font-size: 13px;
  color: var(--t2);
  /* 🆕 第一百一十六批：这排标签支持「拖住左右移动调顺序」⇒ 光标改成抓手
     （原来是 pointer，只表达「可点」；grab 同时表达了「可拖」）。
     ⚠️ 点一下仍然是切表，只是可发现性靠光标来提示。 */
  cursor: grab;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* 🆕 第一百一十六批：拖拽调序的视觉反馈（逻辑见 app.js 的 tabDragBind）——
   被拖的那个标签压暗 + 抬起，整条栏给 grabbing 光标，跟手换位时看得清。 */
.qptabs--dragging,
.qptabs--dragging .qptab {
  cursor: grabbing;
}

.qptab--drag {
  opacity: .55;
  box-shadow: 0 3px 10px rgba(0, 0, 0, .18);
}

.qptab--on {
  background: var(--brand, #1d9e75);
  border-color: var(--brand, #1d9e75);
  color: #ffffff;
}

.qpbtn {
  margin-left: auto;
  padding: 6px 18px;
  border-radius: 999px;
  background: var(--brand, #1d9e75);
  color: #ffffff;
  font-size: 13px;
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}

.qpbtn--ghost {
  margin-left: 0;
  background: #ffffff;
  border: 1px solid var(--line);
  color: var(--t2);
}

/* 列宽拖拽手柄：贴在表头格右边缘内侧（.td 有 overflow:hidden，所以不能往外伸）
   日常只有鼠标划过时露出一条竖线，不打扰阅读 */
.cw-handle {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 7px;
  cursor: col-resize;
  background: transparent;
}

.cw-handle:hover {
  background: rgba(29, 158, 117, 0.28);
}
/* 🆕 第八十八批（2026-10-07）：「施工登记」页表格内的数量直编输入框 ——
   只给 .ptd--celledit 里的 input 用，不影响任何既有样式。
   边框用 box-shadow 而不是 border —— border 会把行撑高，整张表格跟着跳（与 .td--edit 同理）。
   ⚠️ 必须放在 @media print 之前（下面那段是打印样式，会整体套到打印里）。 */
.ptd--celledit {
  padding: 4px 6px;
}

.ptd__inp {
  /* 🔴 第一百二十八批：原 width:100% —— 表格布局下 cell 宽度由「内容」决定，
     而 input 的百分比宽又要反过来看 cell 有多宽 ⇒ 循环依赖，浏览器只能按 input 的
     固有宽度（size 属性 ≈ 170px）算，会把「数量」列撑得又宽又空。
     ⇒ 改成固定宽 + border-box，列宽就稳定为「表头文字宽 / 输入框宽」里的大者。
     🔴 想回退：改回 width: 100%; min-width: 48px（并确认列宽是否还受原 flex 值控制）。 */
  width: 56px;
  box-sizing: border-box;
  min-width: 0;
  padding: 4px 6px;
  border: none;
  border-radius: 6px;
  background: #eef5fd;
  box-shadow: inset 0 0 0 1px #c8dcf5;
  color: #1268d6;
  font-size: 16px; /* 第一百一十三批：12.5px → 16px，iOS 点它不再放大整页 */
  line-height: 1.4;
  text-align: center;
  -webkit-appearance: none;
  appearance: none;
}

.ptd__inp:focus {
  outline: none;
  background: #ffffff;
  box-shadow: inset 0 0 0 2px #1268d6;
}

.ptd__inp::placeholder {
  color: #b9c6d6;
}

/* 🆕 第九十二批：已出库的单 ⇒ 数量格**只读**（灰底 + 不可编辑的视觉）。
   判据在 app.js 的 regRowEditMap（与服务端 mf_guard_dbl_qty 的出库门禁同口径）。 */
.ptd--locked {
  color: #9aa4b2;
  background: #f4f6f8;
  text-align: center;
  border-radius: 6px;
  box-shadow: inset 0 0 0 1px #e6e9ed;
  font-size: 12.5px;
  min-width: 48px;
}

/* 🆕 第九十六批：列表页（.td 系列）里已出库订单的「产品编号 / 数量」只读格 —— 与上面的
   .ptd--locked 同一套视觉（灰字 + 浅灰底 + 内描边），只是尺寸按大表格走。 */
.td--locked {
  color: #9aa4b2;
  background: #f4f6f8;
  box-shadow: inset 0 0 0 1px #e6e9ed;
  border-radius: 5px;
}

/* 🆕 第一百一十一批（2026-10-09 用户需求）：已出库订单的**外观标识**。
   ⚠️ 本批中途改过一次口径（用户追加需求，两次口径都记在这里，免得以后翻不到）：
      · 先做的是「整行 62% 变灰」——把第一百一十批删掉的那条恢复回来；
      · 随后用户改口径：「有出库记录的改为浅黄色……**只是变文字，不变底色**，和调色不冲突」
        ⇒ **那层 opacity 已撤掉**，改成**文字**变琥珀黄（见文件末尾的 .tr--cout / .ptr--cout）。
   🔴 想回到「整行变灰」：把下面这行加回来即可 ——
         .tr--frozen { opacity: .62; }
   保留下来的 cursor: not-allowed —— 它只是鼠标形态、不影响颜色，
   且点下去本来就会被拦（提示「要改得先撤出库」）。 */
.tr--frozen .td {
  cursor: not-allowed;
}

@media print {
  #nav,
  .qptabs,
  .cw-handle,
  .pending__more,
  .act,
  .listbar,
  .ptoolbar,
  .tvsec__cnt,
  /* 🆕 第七十六批：打印时不要勾选框 / 删除按钮 —— 打印出来是给人看的存档，
     留一列空方框和「删除选中」按钮毫无意义（甚至误导）。
     🆕 第七十八批：行末「编辑」列同理（打印稿上点不了，留着只会占位置）。 */
  .td--pick,
  .td--act,
  .tvsec__fld,
  .tvdel {
    display: none !important;
  }

  .screen {
    padding: 0 !important;
    min-height: 0 !important;
  }

  .qppage {
    padding: 0 !important;
  }

  .tvsec {
    margin: 0 0 12px !important;
    break-inside: auto;
  }

  .tw {
    overflow: visible !important;
  }

  .table {
    box-shadow: none !important;
    border: 1px solid #cccccc;
    border-radius: 0 !important;
    /* 🔴 第一百二十八批：原 display:block !important —— 基础 .tr 已改成 table-row，
       而 block 父级会让每一行各自生成匿名表（列宽各行独立 ⇒ 打印稿错位）⇒ 改成 table。
       ⚠️ 下面那条 `.table--fit` 必须留在本行**之后**（同特异性、后定义赢），
          让 #tables 的表格在打印时仍是 block + flex。 */
    display: table !important;
    min-width: 0 !important;
    width: 100% !important;
  }

  /* 🔴 第一百二十八批：.table--fit 的表格打印时保持 block（它的行是 flex，见上面那条说明）。 */
  .table--fit {
    display: block !important;
  }

  .tr--head {
    break-inside: avoid;
  }

  .tvsec .td {
    white-space: normal !important;
    word-break: break-word;
  }
}

/* ---------- 🆕 第一百一十一批（2026-10-09 用户需求）：订单「调色」状态的整行底色 ----------
   判据在引擎（mf-data.js 的 colorToneOf，按**订单号**跨表查「调色信息」表的调色日期）：
     · 浅蓝 = 「调色 = 是」但调色日期还空着（待调色）
     · 浅绿 = 「调色 = 是」且已有调色日期（已调色）
   其余订单（调色 ≠ 是）一律保持原样。
   ⚠️ 改之前先读这两条硬约束：
     ① 小表斑马纹 `.ptr:not(.ptr--head):nth-child(even)` 的特异性是 (0,3,0)，
        行底色必须**不低于**它，否则偶数行的淡灰底会把染色盖掉
        ⇒ 所以下面写成 `.ptr:not(.ptr--head).ptr--cblue`（同样是 0,3,0，靠**后定义**取胜）。
     ② 这两段必须留在上面那条斑马纹**之后**（同权重时后写的赢）。
   ⚠️ 打印时不输出背景色（浏览器默认行为）⇒ 打印仍是白底黑字，
      与用户口径「表格**预览显示**时着色」一致。 */
.ptr:not(.ptr--head).ptr--cblue,
.tr.tr--cblue {
  background: #d6ecfb;              /* 浅蓝底：待调色 */
}

.ptr:not(.ptr--head).ptr--cgreen,
.tr.tr--cgreen {
  background: #d9f2d9;              /* 浅绿底：已调色 */
}

/* 黑字：颜色必须落在**单元格**上 —— .td / .ptd 各自带 color: var(--t2)（#333），
   写在行级会被它们盖掉，所以这里用「行类 + 单元格」两段选择器压过去。 */
.ptr--cblue .ptd,
.ptr--cgreen .ptd,
.tr--cblue .td,
.tr--cgreen .td {
  color: #111111;
}

/* 🆕 第一百一十一批·追加（2026-10-09 用户需求）：**有出库记录的订单 ⇒ 整行文字单独着色**。
   口径：只改**文字**颜色，**不碰底色** ⇒ 与「调色底色」各管各的，
   同一行可以同时是「浅蓝/浅绿底 + 粉字」，两个维度分别回答「要不要调色」与「出库了没」。
   🆕 第一百二十六批（2026-10-09 用户需求）：文字颜色由「琥珀黄 #a8620a」改为 **粉红 #d81b60**。
   ⚠️ 粉红**不能取浅粉**（#ffc0cb 这类）：在浅蓝 / 浅绿底上根本读不清（对比度不足 2:1）。
      现用的 #d81b60 对比度 —— 白底 4.96:1 / 浅绿底 4.22:1 / 浅蓝底 4.07:1，三处都够看。
   ⚠️ 必须写在上面那条「黑字」**之后**：同一行既带 cblue/cgreen 又带 cout 时，
      两条规则权重相同（各 2 个类），靠**后定义**的这条赢 ⇒ 出库行显粉字、非出库行显黑字。 */
.ptr--cout .ptd,
.tr--cout .td {
  color: #d81b60;
}

/* 🆕 第152批（2026-10-10 用户需求 规格D）：状态着色 —— 已完成=绿字，完结未款=黄底。
   · `.tr--done .td` 绿字：必须写在上面 `.tr--cout .td`（粉字）**之后** —— 同权重（各 2 个类）
     靠后定义赢 ⇒ 同一行既带 done 又带 cout 时显绿不显粉（规格A 已让 已完成 不挂 cout，这里双保险）。
   · `.tr.tr--unpaid` 黄底：写在调色底色（`.tr.tr--cblue` 等）之后，确保压过浅蓝/浅绿底。
   🔵 2026-10-10 第152批·补充③：底色由**深黄 `#f9a825` 改为浅黄 `#fff59d`**（用户要求「改成浅黄色底」）。
   ⚠️ 浅黄底上配深棕字（`.td` 自带 #333 ⇒ 这里再压一层 #5a4500）⇒ 对比度足够可读。
   ⚠️ 打印不输出背景色（浏览器默认），与「预览显示着色」口径一致。 */
.tr--done .td,
.ptr--done .ptd {
  color: #1b8a3a;              /* 已完成：绿字 */
}

.tr.tr--unpaid,
.ptr:not(.ptr--head).ptr--unpaid {
  background: #fff59d;         /* 完结未款：浅黄底（原深黄 #f9a825） */
}

.tr.tr--unpaid .td,
.ptr--unpaid .ptd {
  color: #5a4500;             /* 浅黄底上的深棕字，保证可读 */
}

/* ======================================================================
   🆕 打印中心（第一百四十六批）：#queryprint 重做为 7 类业务打印模板。
   移动端为主：顶部横向菜单 + 卡片式稿纸；打印时只输出 .pc-sheet。
   ====================================================================== */
.pcwrap { display: flex; flex-direction: column; min-height: 100%; }
.pcnav {
  display: flex; gap: 6px; overflow-x: auto; -webkit-overflow-scrolling: touch;
  padding: 8px; background: #f3f4f6; border-bottom: 1px solid #e2e5ea;
  position: sticky; top: 0; z-index: 5;
}
/* 🆕 第一百七十一批（用户需求）：菜单按钮**居中显示**。
   用「首尾 auto 外边距」这一手：放得下时两侧均分空白 ⇒ 居中；放不下时 auto 归零 ⇒ 仍能横向滚动（不会把左边第一个挤到屏外）。 */
.pcnav > .pctab:first-child { margin-left: auto; }
.pcnav > .pctab:last-child { margin-right: auto; }
.pctab {
  flex: 0 0 auto; padding: 8px 12px; border-radius: 8px; background: #fff; color: #374151;
  font-size: 14px; line-height: 1.2; white-space: nowrap; border: 1px solid #e2e5ea; cursor: pointer;
}
.pctab--on { background: #2b6cb0; color: #fff; border-color: #2b6cb0; }
.pctab__sub { display: block; font-size: 11px; opacity: .8; margin-top: 2px; }
.pcbody { padding: 12px; }
.pc-sheet {
  background: #fff; color: #1f2937; border: 1px solid #d1d5db; border-radius: 10px;
  /* 🆕 第275批（用户）：「网页端也同步改成上下和左右到页边距2CM」
     ⇒ 纸按**物理 A4**：21 × 29.7cm；四边内边距 **2cm**（内容区 = 21 − 4 = 17cm）。
     · 直接写 cm（用户就是按厘米提的口径），浏览器按 96dpi 换算：1cm = 37.7953px。
     · 与小程序第274批**逐像素同口径**：小程序内容区 640.52px（= 793.7 − 75.59×2 − 1×2），
       这里 21cm − 2cm×2 − 1px×2 同样是 640.52px。
     🔴 可翻转点 = 这两处（max-width 21cm / padding 2cm）；改回 820px / 16px 即恢复原样。 */
  padding: 2cm; max-width: 21cm; margin: 0 auto; box-shadow: 0 1px 4px rgba(0,0,0,.08);
}
.pc-sheet.a5l { max-width: 29.7cm; }   /* 第275批：A5 横 = A4 横放（29.7×21cm） */
.pc-orderno { font-size: 16px; font-weight: 700; margin-bottom: 10px; color: #111827; }
/* 🆕 第一百七十一批：员工结算模板 —— 段落小标题 + 结算月份说明 */
.pc-secttl { font-size: 14px; font-weight: 700; color: #111827; margin: 14px 0 4px; }
.pc-settlemeta { font-size: 13px; color: #6b7280; margin-bottom: 8px; }
/* 🆕 店名：独占一排、居中、字号放大（约 3×，比原 13px 大约 200%）*/
/* 🆕 第一百七十七批：页头店名再放大 80%（38→68.4px）并加粗。🔴 可翻转点 = 下列 font-size / font-weight（屏上 + 打印两处同步）。*/
.pc-shopname { text-align: center; margin: 4px 0 14px; }
.pc-shopname input { font-size: 68.4px; font-weight: 700; text-align: center; border: 1px solid #cbd5e1; border-radius: 8px; padding: 6px 10px; width: 92%; box-sizing: border-box; }
/* 🆕 投诉电话 / 联系人 / 地址：客户签字下方一排 3 列，且三列保持同一行不换行 */
.pc-contacts { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 18px; margin-top: 12px; }
.pc-contact__item { display: flex; flex-direction: column; font-size: 13px; color: #374151; min-width: 0; }
.pc-contact__item > span { margin-bottom: 2px; color: #6b7280; }
.pc-contact__item input { border: 1px solid #cbd5e1; border-radius: 6px; padding: 4px 6px; font-size: 13px; width: 100%; box-sizing: border-box; min-width: 0; }
.pc-savehint { font-size: 11px; color: #9ca3af; margin-top: 6px; text-align: center; }
/* 客户信息 / 订单说明 / 业务员 块 */
.pc-cust { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 24px; margin: 8px 0; }
.pc-line { margin: 6px 0; font-size: 13px; }
.pc-line__k { font-weight: 700; margin-right: 8px; color: #111827; }
/* 🆕 订单说明：标题 + 内容用方框框起来 */
.pc-notebox { border: 1px solid #cbd5e1; border-radius: 8px; margin: 10px 0; overflow: hidden; }
.pc-notebox__t { background: #eef2f7; color: #374151; font-weight: 700; font-size: 13px; padding: 6px 10px; border-bottom: 1px solid #cbd5e1; text-align: center; }
.pc-notebox__v { padding: 8px 10px; font-size: 13px; color: #1f2937; min-height: 20px; white-space: pre-wrap; word-break: break-word; }
.pc-sel { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin-bottom: 14px; font-size: 14px; }
.pc-radio {
  display: inline-block; padding: 5px 10px; border: 1px solid #cbd5e1; border-radius: 16px;
  background: #fff; color: #374151; font-size: 13px; cursor: pointer; margin-left: 4px;
}
.pc-radio--on { background: #2b6cb0; color: #fff; border-color: #2b6cb0; }
.pc-sel__no select { padding: 5px 8px; border-radius: 6px; border: 1px solid #cbd5e1; font-size: 14px; }
/* 🆕 第291/292批：订单号选框改成「可手输 + 自绘候选」（边输边筛，子串匹配） */
.pc-no-wrap { position: relative; display: inline-block; width: 240px; max-width: 100%; }
.pc-sel__no input.pc-noinput { width: 100%; max-width: 100%; padding: 5px 8px; border-radius: 6px; border: 1px solid #cbd5e1; font-size: 14px; }
.pc-nosug { display: none; position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 60;
  max-height: 240px; overflow: auto; background: #fff; border: 1px solid #cbd5e1; border-radius: 6px;
  box-shadow: 0 8px 24px rgba(15, 23, 42, .12); }
.pc-nosug__i { padding: 6px 10px; font-size: 13px; color: #1f2937; cursor: pointer; }
.pc-nosug__i:hover { background: #eef6f0; }
.pc-nosug__empty { padding: 6px 10px; font-size: 12px; color: #9ca3af; }
.pc-head { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 24px; margin-bottom: 12px; }
.pch-row { display: flex; font-size: 13px; line-height: 1.6; }
.pch-k { flex: 0 0 92px; color: #6b7280; }
.pch-v { flex: 1; color: #1f2937; word-break: break-all; }
.pctab-table { width: 100%; border-collapse: collapse; margin: 8px 0; font-size: 13px; }
.pctab-table th, .pctab-table td { border: 1px solid #cbd5e1; padding: 6px 8px; text-align: center; }
.pctab-table thead th { background: #eef2f7; color: #374151; }
.pctab-table tfoot td { background: #f8fafc; font-weight: 600; }
.pctab-amt { text-align: center; font-variant-numeric: tabular-nums; }
/* 🆕 第一百七十七批（追加，仅施工确认单）：明细表尾行（双包单价 + 实际总面积 / 本单总金额手写空） */
.pctab-table tfoot td.pctab-footnote { text-align: left; font-weight: 500; }
.pc-fill { display: inline-block; min-width: 110px; border-bottom: 1px solid #374151; }
/* 🆕 第一百七十一批：签字行改「两条等宽弹性下划线」——客户签字 / 签字日期 两段一样长，
   窄屏自动收缩不溢出。曾为 text-align:right（第169批），改弹性布局后整体铺满一行。
   补：下划线长度缩到**一半**（flex: 0 0 50%），再缩 20%（50%→40%）；签字栏下移半行（margin-top 18→28px）。
   再补（用户需求）：**删除签字栏上方的虚线**（去掉 border-top）。
   🔴 可翻转点 = 这几行。 */
.pc-sign { margin-top: 28px; font-size: 13px; color: #374151; padding-top: 10px; display: flex; gap: 28px; }
.pc-sign__i { flex: 1 1 0; display: flex; align-items: baseline; min-width: 0; }
.pc-sign__k { flex: 0 0 auto; color: #374151; }
.pc-sign__l { flex: 0 0 40%; min-width: 40px; margin-left: 4px; border-bottom: 1px solid #374151; height: 1.1em; }
.pc-tools {
  display: flex; gap: 12px; align-items: center; justify-content: center; margin-top: 16px;
  padding: 10px; background: #f3f4f6; border-radius: 10px; position: sticky; bottom: 0;
}
.pc-print {
  background: #2b6cb0; color: #fff; border-radius: 8px; padding: 10px 22px; font-size: 15px; cursor: pointer;
}
.pc-locked, .pc-empty { text-align: center; color: #9ca3af; padding: 40px 12px; font-size: 14px; }

/* 🔴 打印：只输出 .pc-sheet，隐藏所有交互栏（菜单 / 工具 / 选择栏 / 填写提示） */
/* 🆕 第275批（用户）：「上下和左右到页边距2CM」——
   屏上那份纸已经用 padding:2cm 表达边距；**真打印**时交给浏览器按 @page 留 2cm
   （print 段里 .pc-sheet 的 padding 已置 0，所以不会叠加成 4cm）。
   ⚠️ 只设 margin、**不设 size**：用户在打印对话框里选 A4 / A5 仍然自由，不会被这里钉死。 */
@page { margin: 2cm; }
@media print {
  body { background: #fff; }
  .pcnav, .pc-tools, .pc-sel, .pc-shop__title, .pc-savehint { display: none !important; }
  .pcbody { padding: 0; }
  .pc-sheet { border: none; box-shadow: none; max-width: none; margin: 0; padding: 0; border-radius: 0; }
  .pc-shopname { text-align: center; }
  .pc-shopname input { border: none; padding: 0; font-size: 68.4px; font-weight: 700; text-align: center; width: 100%; }
  .pc-contact__item input { border: none; padding: 0; font-size: 13px; }
}


/* ══════════════════════════════════════════════════════════════════════
   🔴 第200批（2026-10-11 用户需求）：#orderReturn 页改「销售退货订单」——
   产品栏目改成**一张表 + 每行左侧复选框**，选中订单号后把该单全部产品一次铺进来。
   ① 复选框必须**自绘**：app.css 顶部第 70~84 行的全局 reset 对所有 input 做了
      appearance:none + background:none + border:0，原生复选框会被抹成 **0×0**
      （第195批实测）⇒ 只能像 #un-ptable 那样按作用域把它画回来，**不动全局 reset**
      （全站输入框 / 下拉都靠它抹掉系统外观）。
   ② 作用域 = #ret-ptable（退货表容器 id，app.js 的 retTableHtml 里写死，改一处要两处一起改）。
   ③ 窄屏（360px）也要能用：表格外面套一层 .ret-tab__wrap{overflow-x:auto} 自带横向滚动，
      产品名那一格用 span 截断 —— 绝不把内容推给 .screen{overflow-x:clip} 静默裁掉（第189批踩过）。
   🔴 可翻转点：想让复选框回系统原生外观，把 #ret-ptable input[type="checkbox"] 那三段换成
      `appearance:auto; width:20px; height:20px; accent-color:var(--green);` 即可。
   ══════════════════════════════════════════════════════════════════════ */
.ret-tab {
  margin: 2px 0 10px;
  border: 1px solid var(--line2);
  border-radius: 8px;
  overflow: hidden;
  background: var(--card);
}
.ret-info {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 4px 14px;
  padding: 8px 10px;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
  font-size: 12px;
  color: var(--t4);
}
.ret-info b {
  color: var(--t1);
  font-weight: 400;
}
.ret-tab__bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}
.ret-tab__btn {
  flex: 0 0 auto;
  padding: 3px 10px;
  border: 1px solid var(--line2);
  border-radius: 6px;
  background: var(--card);
  color: var(--t3);
  font-size: 12px;
}
.ret-tab__sum {
  margin-left: auto;
  font-size: 12px;
  color: var(--t3);
}
.ret-tab__sum b {
  color: #c0392b;
  font-weight: 400;
}
.ret-tab__wrap {
  overflow-x: auto;
}
.ret-tab__t {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
}
.ret-tab__t th {
  padding: 6px 4px;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
  color: var(--t3);
  font-weight: 400;
  text-align: right;
  white-space: nowrap;
}
.ret-tab__t td {
  padding: 6px 4px;
  border-bottom: 1px solid var(--line);
  color: var(--t2);
  text-align: right;
  white-space: nowrap;
}
.ret-tab__t tbody tr:last-child td {
  border-bottom: 0;
}
.ret-tab__c0 {
  width: 26px;
  text-align: center !important;
}
.ret-tab__c1 {
  text-align: left !important;
  /* 产品列的宽度上限 —— 360px 手机上 6 列合计必须 ≤ 容器宽（326px），
     留给产品列约 130~170px；封顶 168 保证不撑破表格，超长名字由 .ret-prod 省略号截断。 */
  max-width: 168px;
}
/* 表头折成两行用的列（本次退货 / 退货单价）—— 2 个字宽，比单行省一半横向空间 */
.ret-tab__c2 {
  white-space: normal;
}
.ret-prod {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 产品列副行：已卖 / 已退（只读参考数，不参与录入） */
.ret-ref {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-top: 1px;
  color: var(--t4);
  font-size: 11px;
}
.ret-row--full {
  opacity: 0.5;
}
.ret-amt {
  color: #c0392b;
}
.ret-tab__empty {
  padding: 14px 10px;
  color: var(--t4);
  font-size: 13px;
  text-align: center;
}
.ret-tab__note {
  padding: 6px 10px;
  border-top: 1px solid var(--line);
  color: #b8860b;
  font-size: 12px;
}
#ret-ptable input[type="checkbox"] {
  -webkit-appearance: none;
  appearance: none;
  width: 20px;
  height: 20px;
  margin: 0;
  border: 1.5px solid var(--line2);
  border-radius: 4px;
  background: var(--card);
  position: relative;
  vertical-align: middle;
}
#ret-ptable input[type="checkbox"]:checked {
  background: var(--green);
  border-color: var(--green);
}
#ret-ptable input[type="checkbox"]:checked::after {
  content: '';
  position: absolute;
  left: 6px;
  top: 2px;
  width: 5px;
  height: 10px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
#ret-ptable input[type="checkbox"]:disabled {
  border-style: dashed;
  cursor: not-allowed;
}
.ret-inp {
  width: 100%;
  min-width: 40px;   /* 保证 3 位数（如 100）不被挤掉；再大就会把表撑过 360px 手机的容器宽 */
  max-width: 90px;
  height: 28px;
  padding: 0 6px;
  box-sizing: border-box;
  border: 1px solid var(--line2);
  border-radius: 6px;
  background: var(--card);
  color: var(--t1);
  font-size: 13px;
  text-align: right;
}
.ret-inp:disabled {
  background: var(--bg);
  color: var(--t4);
}

/* ==========================================================================
   🆕 第206批（2026-10-11）：「入库登记」页（#edit/stock）的「退货确认」栏目样式。
   结构（app.js paintReturnSection 生成）：
     #ed-return-sec.opened-sec
       ├ .opened__title            栏目标题（沿用全站「已开产品 / 收款记录」同一套居中标题）
       ├ .fitem                     订单号下拉卡片（复用表单的 fitem / fitem__picker 惯例）
       ├ #ed-return-rows.rtn-box    负数行列表（空 ⇒ 整块隐藏，绝不留白）
       └ .rtn-act > .rtn-act__btn  「提交退货」按钮
   ⚠️ 按钮**不能**用 .footbar —— 那条是 position:fixed 的底部固定条（表单提交栏专用），
      放进栏目里会浮在屏幕上、盖住真正的提交栏。
   ⚠️ 类名一律 rtn- 前缀 —— ret- 已被「销售退货订单」页占用（那张表的行是 <tr class="ret-row">），
      别复用免得两处样式打架。
   ========================================================================== */
.rtn-box {
  background: var(--card);
  border-radius: var(--radius);
  padding: 2px 14px;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.04);
  /* 🆕 第207批（2026-10-11 用户需求）：「确认退货的表格缩小，放居中显示」—— */
  /*   卡片收窄到 330px 并水平居中；可翻转点 = 去掉这三行即恢复满宽。 */
  max-width: 330px;
  margin-left: auto;
  margin-right: auto;
}

/* 空 = 没选单号 / 还没渲染出行 ⇒ 整块消失（与 .opened-sec 的 :empty 同一套路，靠 innerHTML 精确写 ''） */
.rtn-box:empty {
  display: none;
}

.rtn-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 0;
  border-bottom: 1px solid var(--line);
}

.rtn-row:last-child {
  border-bottom: 0;
}

.rtn-row__info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 10px;
}

.rtn-row__pid {
  font-size: 14px;
  font-weight: 600;
  color: var(--t1);
}

.rtn-row__meta {
  font-size: 12px;
  color: var(--t4);
}

/* 覆盖 .fitem__input 的 width:100%（本文件后写、同特异性 ⇒ 生效）：
   输入框定宽靠右，给左边的产品信息留出弹性空间。 */
.rtn-row__input {
  flex: 0 0 104px;
  width: 104px;
  padding: 0 8px;
  text-align: right;
}

/* 🆕 第208批（2026-10-11 用户需求 ①）：「退货数量改成不可更改」——
   锁定态（readonly）：自动填好原数量的绝对值、不可改、不弹键盘；
   视觉与可填态区分（更深一档的灰 + 稍暗的字）。可翻转点 = 去掉这两条属性。 */
.rtn-row__input--lock {
  background: #f2f3f5;
  color: var(--t2);
}

.rtn-none {
  text-align: center;
  color: var(--t5);
  font-size: 13px;
  padding: 18px 0;
}

.rtn-act {
  margin-top: 12px;
}

.rtn-act__btn {
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--green);
  color: #ffffff;
  border-radius: 8px;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.rtn-act__btn:active {
  opacity: 0.75;
}

/* 🆕 第207批（2026-10-11 用户需求）：「入库登记」页（#edit/stock）的「提交」按钮
   从 .footbar 底部固定栏上移到「数量」卡下方（app.js 第207批的 moveSave207）。
   外层 flex 容器让 .footbar__btn 的 flex:1 撑满；按钮外观与它在底栏时逐像素一致。
   与相邻元素的间距：上 = 「数量」卡自带 margin-bottom 10px；下 = 本行 margin-bottom 18px
   （与 .opened-sec 非空时的下距同一节奏 —— 按钮到「退货确认」栏目之间）。 */
.form-act {
  display: flex;
  margin-bottom: 18px;
}

/* 🆕 第208批（2026-10-11 用户需求）：「退货确认」栏目的「订单号」卡与「提交退货」按钮
   也收窄（与负数行表格 .rtn-box 330px 同宽）并居中 —— 整列一条窄列，上中下对齐。
   可翻转点 = 去掉这两条规则即恢复满宽。 */
#ed-return-sec .fitem {
  max-width: 330px;
  margin-left: auto;
  margin-right: auto;
}

#ed-return-sec .rtn-act {
  max-width: 330px;
  margin-left: auto;
  margin-right: auto;
}


/* ==========================================================================
   🆕 第233批（2026-10-14 用户需求）：「已收清款订单号变绿」在**手机浏览器**上不生效。
   根因：那一项用的是原生 <option class="is-paid" style="color:#12924a"> ——
   桌面浏览器认，**手机浏览器（iOS Safari / Android Chrome）一律忽略 option 的颜色**（各家实现，CSS 救不了）。
   ⇒ 触屏设备把「收款页订单号」那一格换成**自绘弹层**（与小程序端同一套做法，别新造一套控件）；
     桌面端仍是原生 <select>（本来就能着色，不动手感）。
   下面这几条只服务这套自绘控件。
   ========================================================================== */
.fitem__picker--pick {
  display: flex;
  align-items: center;
}

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

.fitem__arrow {
  flex: none;
  margin-left: 6px;
  color: var(--t4);
}

.picklist {
  padding: 2px 0;
}

.picklist__item {
  padding: 13px 14px;
  font-size: 16px;
  color: var(--t1);
  border-bottom: 1px solid var(--line);
}

.picklist__item:last-child {
  border-bottom: none;
}

/* 「已收清款」= 绿色（与桌面端 option.is-paid、小程序 .picklist__item--paid **同色同粗**） */
.picklist__item--paid {
  color: #12924a;
  font-weight: 600;
}

.picklist__item:active {
  background: var(--bg);
}

/* 🆕 第235批（2026-10-14 用户需求）：签字栏里「直接印出文字」的那几项（出库单的仓管员 / 打印日期）。
   与手写横线 .pc-sign__l 互斥：有值就印字、没值才画线。 */
.pc-sign__v {
  flex: 0 0 auto;
  margin-left: 4px;
  color: #111827;
  font-weight: 600;
}

/* 🆕 第237批（2026-10-14 用户需求）：打印中心表格里「备注」列的固定宽度 5cm。
   th / td 两边都挂（只挂 th 时部分内核只当「建议值」）；
   用在「完工确认单」与「客户订单（双包）」的备注列上（列定义里的 cls: 'pctab-w5'）。 */
.pctab-table th.pctab-w5,
.pctab-table td.pctab-w5 {
  width: 5cm;
}

/* ══════════════════════════════════════════════════════════════════════
   🆕 第285批（用户需求）：「操作日志 —— 系统管理页最下边查看最近 500 条」
   只作用于 #oplog-box 里的 .oplog__*，别的页面一个字节不动。
   表头 position:sticky ⇒ 滚动 500 条时列名不丢；.oplog__wrap 限高 420px 内部滚动。
   ══════════════════════════════════════════════════════════════════════ */
.oplog__wrap { max-height: 420px; overflow: auto; -webkit-overflow-scrolling: touch;
  border: 1px solid #eef0f3; border-radius: 8px; }
.oplog__tab { width: 100%; border-collapse: collapse; table-layout: fixed;
  font-size: 12px; color: #1f2937; }
.oplog__tab th, .oplog__tab td { padding: 6px 8px; border-bottom: 1px solid #f1f3f5;
  text-align: left; vertical-align: top; }
.oplog__tab thead th { position: sticky; top: 0; z-index: 1;
  background: #f7f8fa; color: #6b7280; font-weight: 600; }
.oplog__tab tbody tr:nth-child(even) { background: #fcfcfd; }
.oplog__tab th:nth-child(1), .oplog__t { width: 120px; white-space: nowrap; color: #6b7280; }
.oplog__tab th:nth-child(2) { width: 64px; }
.oplog__tab th:nth-child(3) { width: 88px; }
.oplog__tab th:nth-child(4) { width: 72px; }
.oplog__d { word-break: break-all; color: #374151; }
.oplog__foot { padding: 8px 2px 0; font-size: 12px; color: #9aa1ab; }

/* 🆕 第308批（用户）：「所有新增订单的表单页面，数量大于库存 ⇒ 数量输入框淡黄底」
   判据与染色逻辑在 app.js 的 qtyStockCheck308（事件委托：input/change 都算）。 */
.qty--over {
  /* 🔄 第310批（用户）：「帮我换成红底黄字」——原来是淡黄底黑字，现在改成**红底 + 黄字** */
  background: #d81e22 !important;
  color: #ffd400 !important;
  border-color: #a81519 !important;
  font-weight: 600 !important;
  box-shadow: 0 0 0 2px rgba(216, 30, 34, 0.28) !important;
}
