/* ============================================================
   核桃云交易系统 · 全局 UI 规范（唯一权威来源）
   ------------------------------------------------------------
   本文件是 PC 后台 / 小程序 / 云秤 APP 三端的**视觉与交互唯一依据**。
   任何页面不得自造颜色、字号、间距；新增样式必须先改本文件再使用。

   风格定位：工业实用（Industrial Practical）
   核桃墨绿 + 暖纸面 + 琥珀金强调 —— 车间强光下也能看清，不追求花哨。

   ★ 本规范由 v4.8 统一，原有PC 后台 webdemo.css 与小程序 app.wxss
     均为本规范的**投影**（数值一致、单位不同：px / rpx）。
     出现分歧以本文件为准。
   ============================================================ */

/* ============================================================
   一、色彩令牌
   ============================================================ */
:root {
  /* ---- 松针墨绿（主色系）·v4.9 已采用方案B，并提亮原 950/900 ----
     业主要求「去掉最前面两个较深的绿色」。
     实现方式：把这两档**提亮**而非删除——它们仍被侧栏渐变与深色文字引用，
     直接删会让 var() 落空、侧栏变白底白字。
     提亮后：侧栏从近黑墨绿变浅松绿，深色文字用 700，可读性反而更好。 */
  --green-950: #2f6b52;  /* 侧栏渐变浅端（提亮后） */
  --green-900: #1a6b4a;  /* 中深：正文强调、弹窗标题（提亮后） */
  --green-700: #1a6b4a;  /* 中：主按钮、链接、选中态 */
  --green-500: #17864f;  /* ★主操作色：仅用于可点击主按钮与进度条
     ★ v6.0 修正（2026-10-09 WCAG 实测）：原 #22a06b 上白字仅 3.33:1，
       达不到正文 AA（4.5:1）。提深到 #17864f 后白字 4.61:1。 */
  --green-300: #6fd0a0;  /* 浅：渐变终点、深底上的次级强调 */
  --green-100: #e0f5ea;  /* 极浅：标签底、成功态背景 */
  --accent:#e8890c;      /* 琥珀橙：仅关键动作 */
  --accent-ink:  #6b4400;

  /* ---- 暖纸面（背景系，非纯白） ---- */
  --paper: #f6f4ef;       /* 页面底色 */
  --paper-2: #efece4;     /* 次级底：输入框、斑马纹 */
  --ink: #16261f;         /* 暖调近黑，正文 */
  --ink-2: #3d4f46;       /* 次级正文 */
  --muted: #566661;       /* 辅助文字、时间戳
     ★ v6.0 修正（2026-10-09 WCAG 实测）：原 #7d8b83 在 --paper 上仅 3.24:1、
       在 --paper-2 上仅 3.02:1 —— 全站 22 页的辅助文字/时间戳都不可读。
       改 #566661 后分别为 5.51 / 5.13:1。*/

  /* ---- 语义色----
     ★ accent / accent-ink 已在上方主色系里定义（v4.9 提亮为 #e8890c），
       此处**不再重复定义**。
       坑：CSS 变量重复定义时**后者覆盖前者**，之前这里写了一份旧琥珀金
       （#f0a020），导致主色系的改动完全不生效——颜色改了没反应就是这个原因。 */
  --danger: #d84a4a;      /* 危险：删除、取消订单、失败 */
  --info: #2b6de8;        /* 信息：提示条、链接 */

  /* ---- 边框 ---- */
  --border-l: rgba(22, 38, 31, 0.12);   /* 浅底发丝边 */
  --border-d: rgba(246, 244, 239, 0.14); /* 深底发丝边 */

  /* ---- 成功呼吸灯 ---- */
  --live: #5df09f;

  /* ---- 字号变量（CSS 变量形态） ----
     ★ v4.8 修正：webdemo.css 里大量使用 var(--fs-xs) 等变量，
       但 admin/assets 下**没有 tokens.css**，这些变量从未定义，
       导致字号/圆角/阴影在生产环境全部失效（退回浏览器默认值）。
       此处按原型 assets/tokens.css 的实测值补齐。
     ★ 数值差异说明：原型 --fs-xs=11px / --fs-sm=12.5px，
       本规范 .fs-xs=12px / .fs-sm=13px。
       取本规范的值——理由：v1.50.0 业主已批「文字太小无法阅读」，
       11px 在 1280×720 工控屏上偏小。原型是设计稿，生产应更大。 */
  --fs-xs: 12px;
  --fs-sm: 13px;
  --fs-md: 14px;
  --fs-lg: 17px;
  --fs-xl: 21px;
  --fs-2xl: 27px;
  --fs-3xl: 34px;

  /* ---- 圆角与阴影变量 ---- */
  --r-sm: 6px;
  --r-md: 10px;
  --r-lg: 16px;
  --r-xl: 22px;
  --r-full: 999px;/* 胶囊（页签/徽章/进度条圆头） */
  --shadow-1: 0 2px 8px rgba(7, 35, 27, 0.10);
  --shadow-2: 0 8px 28px rgba(7, 35, 27, 0.14);
  --shadow-3: 0 24px 64px rgba(7, 35, 27, 0.22);

  /* ---- 字体 ---- */
  --font-body: "Source Han Sans SC", "Noto Sans SC", "Microsoft YaHei",
               "PingFang SC", -apple-system, sans-serif;
  --font-num: "Bebas Neue", "Arial Narrow", "Franklin Gothic Medium",
              "Impact", sans-serif;
  --font-mono: "JetBrains Mono", Consolas, "Courier New", monospace;

  /* ---- 动效 ---- */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-fast: 160ms;
  --dur-base: 320ms;
  --dur-slow: 640ms;

  /* ---- 语义别名（v4.8 统一：旧页面各自定义的局部变量收敁到此处） ----
     实测：download.html 曾自定义 --mint/--warn 两个变量，
     与主色板无对应关系 → 造成「同一语义两种颜色」。
     规范做法：语义色一律用下列别名，不再自定义。 */
  --mint: var(--green-300);        /* 深底上的正向提示（历史别名） */
  --warn: var(--accent-ink);       /* 警示文字色（历史别名） */
}

/* ============================================================
   二、字号与行高
   ------------------------------------------------------------
   云秤端实测 density=1.00（1sp=1dp=1px），PC 端按 1280×720 基准。
   ============================================================ */

/* ---- PC 端（px） ---- */
.fs-xs  { font-size: 12px; }  /* 辅助说明、时间戳、单位 */
.fs-sm  { font-size: 13px; }  /* 表格正文、按钮 */
.fs-md  { font-size: 14px; }  /* 常规正文 */
.fs-lg  { font-size: 17px; }  /* 卡片标题 */
.fs-xl  { font-size: 21px; }  /* 页内大标题 */
.fs-2xl { font-size: 27px; }  /* 页面主标题 */
.fs-3xl { font-size: 34px; }  /* ★KPI 主数字（tabular等宽） */

.lh-tight { line-height: 1.25; }
.lh-base  { line-height: 1.6; }
.lh-loose { line-height: 1.9; }  /* 说明段落 */

/* ---- 字重：只用两级（400/500），避免花哨 ---- */
.fw-normal { font-weight: 400; }
.fw-strong { font-weight: 500; }

/* ---- 数字统一等宽，避免金额跳动 ---- */
.num {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
  letter-spacing: 0.01em;
}
.mono {
  font-family: "JetBrains Mono", Consolas, "Courier New", monospace;
  font-variant-numeric: tabular-nums;
}

/* ============================================================
   三、间距系统（4px 基准）
   ============================================================ */
.sp-0 { margin: 0; }
.sp-1 { margin: 4px; }
.sp-2 { margin: 8px; }
.sp-3 { margin: 12px; }
.sp-4 { margin: 16px; }
.sp-5 { margin: 24px; }
.sp-6 { margin: 32px; }
.sp-7 { margin: 48px; }

.pad-1 { padding: 4px; }
.pad-2 { padding: 8px; }
.pad-3 { padding: 12px; }
.pad-4 { padding: 16px; }
.pad-5 { padding: 24px; }

/* ============================================================
   四、圆角与阴影
   ============================================================ */
.r-sm { border-radius: 6px; }
.r-md { border-radius: 10px; }
.r-lg { border-radius: 16px; }
.r-full { border-radius: 999px; }   /* 胶囊/页签 */

.shadow-1 { box-shadow: 0 2px 8px rgba(7, 35, 27, 0.10); }
.shadow-2 { box-shadow: 0 8px 28px rgba(7, 35, 27, 0.14); }
.shadow-3 { box-shadow: 0 24px 64px rgba(7, 35, 27, 0.22); }

/* ============================================================
   五、核心组件规范
   ============================================================ */

/* ---------- 5.1 按钮 ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: none;
  border-radius: var(--r-md);
  font-weight: 500;
  cursor: pointer;
  transition: transform 160ms cubic-bezier(0.16, 1, 0.3, 1),
              box-shadow 160ms, opacity 160ms;
}
.btn:active { transform: scale(0.97); }
.btn:focus-visible {
  outline: 2px solid var(--green-500);
  outline-offset: 2px;      /* ★键盘可达性：必须保留 */
}

/* 变体（语义色决定用途，不可混用） */
.btn-primary {
  background: var(--green-500);
  color: #fff;
  box-shadow: 0 4px 14px rgba(15, 157, 88, 0.35);
}
.btn-primary:hover { background: var(--green-700); }

.btn-accent {                      /* ★仅关键动作 */
  background: var(--accent);
  color: #2a1d00;
  box-shadow: 0 4px 16px rgba(240, 160, 32, 0.4);
}
.btn-ghost {
  background: #fff;
  border: 1px solid var(--border-l);
  color: var(--ink-2);
}
.btn-ghost:hover { border-color: var(--green-500); color: var(--green-700); }

.btn-danger { background: var(--danger); color: #fff; }

/* 尺寸 */
.btn-sm { padding: 6px 12px; font-size: var(--fs-xs); }
.btn-md { padding: 9px 18px; font-size: var(--fs-sm); }
.btn-lg { padding: 12px 26px; font-size: var(--fs-md); }
.btn-block { display: flex; width: 100%; }

/* ★禁用态：必须给足视觉差。
   实测教训：v1.54.0「只给按钮设 alpha，整行仍可点」——
   看着能点却用不了，是最像「设备坏了」的交互。 */
.btn[disabled],
.btn.is-disabled {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}

/* ---------- 5.2 卡片/面板 ---------- */
.panel {
  background: #fff;
  border: 1px solid var(--border-l);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
}
.panel-title {
  font-size: var(--fs-md);
  font-weight: 500;
  padding: var(--pad-3) var(--pad-4) 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.panel-title small { font-size: var(--fs-xs); color: var(--muted); font-weight: 400; }
.panel-body { padding: var(--pad-3) var(--pad-4) var(--pad-4); }

/* ---------- 5.3 状态徽章（页签） ---------- */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 10px;
  border-radius: var(--r-full);
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: 1.6;
  white-space: nowrap;
}
/* 语义映射（与后端状态枚举一一对应，不可自造） */
.pill-g  { background: var(--green-100); color: var(--green-900); } /* 进行中/已完成/已通过 */
.pill-y  { background: #fff3d6;          color: var(--accent-ink); } /* 待开始/待交货/待审核 */
.pill-r  { background: #fde8e8;           color: var(--danger); }    /* 已取消/已驳回/异常 */
.pill-b  { background: #e3ecfd;           color: var(--info); }      /* 已发货/已收货/已完成 */
.pill-d  { background: rgba(246,244,239,.16); color: var(--paper); } /* 深底徽章 */
.pill-gray{ background: var(--paper-2);   color: var(--muted); }     /* 已停用/已归档 */

/* ---------- 5.4 表格 ---------- */
table.tbl {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}
.tbl th {
  text-align: left;
  font-weight: 500;
  color: var(--muted);
  padding: 9px 12px;
  border-bottom: 1px solid var(--border-l);
  white-space: nowrap;                /* ★表头不换行 */
}
.tbl td {
  padding: 10px 12px;
  border-bottom: 1px solid rgba(22, 38, 31, 0.06);
  vertical-align: middle;
}
.tbl tbody tr:hover { background: rgba(15, 157, 88, 0.04); }
/* ★数字列右对齐 + 等宽，否则金额对不齐 */
.tbl .num, .tbl td.money {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.tbl .shrink { width: 1%; white-space: nowrap; }  /* 操作列不撑宽 */

/* ---------- 5.5 表单 ---------- */
.field { margin-bottom: var(--pad-3); }
.field label {
  display: block;
  font-size: var(--fs-xs);
  color: var(--muted);
  margin-bottom: 6px;
}
.field label .req { color: var(--danger); margin-left: 2px; }  /* 必填标记 */
.input, .select, textarea.input {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--border-l);
  border-radius: var(--r-sm);
  background: var(--paper-2);
  color: var(--ink);
  font-size: var(--fs-sm);
  font-family: inherit;
}
.input:focus, .select:focus, textarea.input:focus {
  outline: none;
  border-color: var(--green-500);
  box-shadow: 0 0 0 3px rgba(15, 157, 88, 0.12);
}
.input::placeholder, textarea.input::placeholder { color: #a9b4ad; }
/* ★必填项校验失败：红边 + 提示，不只变边框色 */
.field.has-error .input { border-color: var(--danger); }
.field .err-msg {
  font-size: var(--fs-xs);
  color: var(--danger);
  margin-top: 4px;
}
.input:disabled, .select:disabled {
  background: var(--paper);
  color: var(--muted);
  cursor: not-allowed;
}
.field-hint { font-size: var(--fs-xs); color: var(--muted); margin-top: 4px; }

/* ---------- 5.6 提示条 ---------- */
.note {
  background: #eef4fe;
  border-left: 3px solid var(--info);
  border-radius: 0 var(--r-md) var(--r-md) 0;
  padding: 10px 14px;
  font-size: var(--fs-sm);
  color: #1f3f7a;
  line-height: var(--lh-loose);
}
.note-fee {                       /* 费用/金额类提示 */
  background: #fff8ea;
  border-left-color: var(--accent);
  border: 1px dashed #e8c168;
  color: #8a6408;
}
.note-warn {
  background: #fdeeee;
  border-left-color: var(--danger);
  color: #7a1f1f;
}
.note-ok {
  background: var(--green-100);
  border-left-color: var(--green-500);
  color: var(--green-900);
}

/* ============================================================
   六、交互反馈规范（三端统一）
   ============================================================ */

/* ---------- 6.1 三态：加载 / 空 / 失败 ------
   ★ 核心纪律：失败 ≠ 空数据。
   实测事故 v1.47.1「把网络失败伪装成今日无数据」——
   用户以为是没数据，实际是没网，排查方向全错。 */
.state {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 60px 24px;
  text-align: center;
}
.state-icon {
  width: 56px; height: 56px;
  border-radius: 50%;
  margin-bottom: var(--pad-3);
  display: flex; align-items: center; justify-content: center;
}
.state-icon.loading {
  border: 3px solid rgba(15,157,88,.2);
  border-top-color: var(--green-500);
  animation: spin .9s linear infinite;
}
.state-icon.empty  { background: rgba(15,157,88,.08); border: 2px dashed rgba(15,157,88,.35); }
.state-icon.neterr { background: rgba(216,74,74,.09);  border: 3px solid rgba(216,74,74,.4); }
.state-icon.bizerr { background: rgba(240,160,32,.1);  border: 3px solid rgba(240,160,32,.45); }
@keyframes spin { to { transform: rotate(360deg); } }

/* ★减少动画偏好：尊重系统设置 */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

.state-text { font-size: var(--fs-sm); color: var(--muted); }
.state-text.is-error { font-size: var(--fs-md); color: var(--ink-2); font-weight: 500; }
.state-sub   { font-size: var(--fs-xs); color: var(--muted); margin-top: 4px; }
/* ★失败态必须给重试入口 —— 失败后用户无事可做等于功能不可用 */
.state-retry {
  margin-top: var(--pad-3);
  background: var(--green-500);
  color: #fff;
  padding: 8px 22px;
  border-radius: var(--r-full);
  font-size: var(--fs-sm);
  border: none;
  cursor: pointer;
}

/* ---------- 6.2 Toast（轻提示，2.5s自动消失） ---------- */
.wd-toast {
  position: fixed;
  left: 50%;
  bottom: 34px;
  transform: translateX(-50%);
  z-index: 180;
  background: var(--green-950);
  color: var(--paper);
  padding: 11px 22px;
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  box-shadow: var(--shadow-2);
  max-width: 80vw;
}
.wd-toast.bad { background: var(--danger); }

/* ---------- 6.3 危险操作二次确认 ---------- */
/* 判据：不可逆/涉及资金/影响他人 → 必须二次确认
   例：删除、取消订单（扣保证金）、确认收货（触发清算） */

/* ---------- 6.4 加载遮罩 ---------- */
/* ★必须遮罩可点击区，避免重复提交（防重入） */
.loading-mask {
  position: absolute; inset: 0;
  background: rgba(246,244,239,.6);
  display: flex; align-items: center; justify-content: center;
  z-index: 50;
}

/* ============================================================
   七、图片与附件展示规范（v4.8 新增 · 交货照片）
   ============================================================ */

/* ---------- 7.1 缩略图网格 ---------- */
.photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: var(--pad-2);
}
.photo-cell {
  position: relative;
  aspect-ratio: 4 / 3;
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--paper-2);
  cursor: zoom-in;                /* ★提示可放大 */
}
.photo-cell img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
/* 方位标签（正/左/右/后） */
.photo-pos {
  position: absolute; top: 6px; left: 6px;
  background: rgba(0,0,0,.45);
  color: #fff;
  font-size: var(--fs-xs);
  padding: 2px 8px;
  border-radius: var(--r-sm);
}
/* ★未加水印必须用琥珀色标出，不能和正常照片一样 */
.photo-pos.no-wm { background: rgba(240,160,32,.95); color: #2a1d00; }

/* ---------- 7.2 加载失败兜底（★必做，否则只看到一片碎图） ---------- */
.photo-fallback {
  width: 100%; height: 100%;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 6px;
  background: var(--paper-2);
  color: var(--muted);
  font-size: var(--fs-xs);
  text-align: center;
  padding: 8px;
  cursor: pointer;
}
.photo-fallback .retry-hint { color: var(--green-700); }

/* ---------- 7.3 大图预览（灯箱） ---------- */
.lightbox {
  position: fixed; inset: 0;
  background: rgba(7,35,27,.94);
  display: flex; align-items: center; justify-content: center;
  z-index: 200;
}
.lightbox img {
  max-width: 92vw; max-height: 82vh;
  object-fit: contain;
  /* ★支持滚轮缩放与拖动 */
  transition: transform 200ms cubic-bezier(.16,1,.3,1);
  cursor: grab;
  user-select: none;
}
.lightbox img.dragging { cursor: grabbing; transition: none; }
/* 缩放控制条 */
.lightbox-ctrl {
  position: absolute; bottom: 24px; left: 50%;
  transform: translateX(-50%);
  display: flex; gap: 10px; align-items: center;
  background: rgba(7,35,27,.85);
  border: 1px solid var(--border-d);
  border-radius: var(--r-full);
  padding: 6px 14px;
}
.lightbox-ctrl button {
  background: transparent;
  border: 1px solid rgba(246,244,239,.3);
  color: var(--paper);
  width: 30px; height: 30px;
  border-radius: 50%;
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
}
.lightbox-ctrl button:hover { background: rgba(246,244,239,.12); }
.lightbox-zoom { color: var(--paper); font-size: var(--fs-xs); min-width: 48px; text-align: center; }
.lightbox-cap {
  position: absolute; top: 20px; left: 50%;
  transform: translateX(-50%);
  color: var(--paper);
  font-size: var(--fs-sm);
  opacity: .9;
}
/* 水印信息条：让照片来源可追溯 */
.lightbox-wm {
  position: absolute; bottom: 74px; left: 50%;
  transform: translateX(-50%);
  color: rgba(246,244,239,.75);
  font-size: var(--fs-xs);
  text-align: center;
  white-space: pre-line;
}

/* ============================================================
   八、布局规范
   ============================================================ */

/* ---------- 8.1 PC 端侧栏 + 主区 ---------- */
.shell { display: flex; min-height: 100vh; }
.rail {
  width: 230px;
  flex: none;
  background: var(--green-950);
  color: #a9c2b3;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}
.main { flex: 1; padding: 26px 30px 60px; min-width: 0; }  /* ★min-width:0 防表格撑破 */

/* ---------- 8.2 栅格 ---------- */
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
@media (max-width: 1100px) {
  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
}

/* ---------- 8.3 KPI 卡 ---------- */
.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; }
.kpi {
  background: #fff;
  border: 1px solid var(--border-l);
  border-radius: var(--r-md);
  padding: var(--pad-4);
  box-shadow: var(--shadow-1);
}
.kpi .kpi-label { font-size: var(--fs-xs); color: var(--muted); }
.kpi .kpi-value {
  font-size: var(--fs-3xl);
  font-weight: 500;
  line-height: 1.15;
  margin-top: 4px;
  font-variant-numeric: tabular-nums;
}
.kpi .kpi-unit { font-size: var(--fs-lg); color: var(--ink-2); margin-left: 4px; }

/* ---------- 8.4 进度条 ---------- */
.bar-track {
  height: 10px;
  background: rgba(15, 157, 88, 0.12);
  border-radius: var(--r-full);
  overflow: hidden;
}
.bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--green-500), var(--green-300));
  border-radius: var(--r-full);
  transition: width 320ms cubic-bezier(0.16, 1, 0.3, 1);
}
/* ★数值必须标在旁边：只有进度条看不出是「多少 / 多少」 */
.bar-cap { font-size: var(--fs-xs); color: var(--ink-2); margin-top: 6px; }

/* ============================================================
   九、可访问性（Accessibility）
   ============================================================ */
/* ① 正文对比度 ≥ 4.5:1（工控屏强光下是硬指标）
   ② 焦点必须可见：:focus-visible 有outline
   ③ 状态不能只靠颜色区分：徽章必须带文字（色弱用户看不出红/绿）
   ④ 图标按钮必须有 aria-label 或 title
   ⑤ 表格用 th scope，表单 label 关联 for/id */

/* ============================================================
   十、禁止事项（实事故沉淀）
   ============================================================ */
/* ✗ 禁止 1：写死的假状态
     实测：登录页「串口自检 ✓网络 ✓」不做任何检测，串口断了仍显示 ✓。
     判据：界面上的「状态」必须能回答「这个值从哪来」。 */
/* ✗ 禁止 2：点得了但用不了
     实测：微信扫码按钮只设 alpha、整行仍可点。
     禁用态必须 pointer-events:none。 */
/* ✗ 禁止 3：把失败渲染成空数据
     实测：网络失败显示「今日无数据」，排查方向全错。
     失败必须有独立状态 + 重试入口。 */
/* ✗ 禁止 4：删除控件只删 UI 不删代码
     实测：btnTare/btnCat 等 GONE 死控件进 NPE，本项目已踩 4 次。 */
/* ✗ 禁止 5：占位话术残留
     如「功能开发中」「待补充」出现在正式页面 =
     让用户以为功能坏了。要么不做，要么如实说明缺什么。 */
/* ✗ 禁止 6：同一关系两套表达
     实测：st_order 同时有 designated(名称) 与 mill_id(ID)，
     名称一改关系就静默失效。 */