/* 基础布局 / 安全区 / 微信·手机适配 */
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

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

body {
  background: var(--bg);
  color: var(--text);
  font-family: "PingFang SC", "Microsoft YaHei", -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 15px;
  line-height: 1.6;
  /* 防止 iOS 微信橡皮筋滚动露白 */
  overscroll-behavior-y: none;
}

#app { min-height: 100%; }

img {
  user-select: none;
  -webkit-touch-callout: none; /* 除长按识别二维码场景外，禁长按菜单干扰 */
}

/* 衬线标题（编辑感）。安卓无衬线回退已包含在 font-family 链 */
.xb-title {
  font-family: Georgia, "Songti SC", "SimSun", serif;
  font-weight: 500;
  font-size: 24px;
  margin: 8px 0;
}

.xb-sub { color: var(--muted); font-size: 13px; margin: 0 0 16px; }

.xb-page {
  padding: 16px;
  /* 全面屏底部 Home 指示条安全区 */
  padding-bottom: calc(16px + env(safe-area-inset-bottom));
  padding-top: calc(16px + env(safe-area-inset-top));
}

.xb-err {
  color: #c0392b;
  font-size: 13px;
  padding: 8px 16px;
}

/* 通用卡片 */
/* 底部标签栏占位（子页面用，避免被遮挡） */
.xb-tabbar-pad { height: calc(56px + env(safe-area-inset-bottom)); }

a { color: var(--accent); }

/* 顶部栏（自定义，避开 Vant 默认后台感） */
.xb-shell { min-height: 100%; }
.xb-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: calc(10px + env(safe-area-inset-top)) 14px 10px;
  position: sticky;
  top: 0;
  background: var(--bg);
  z-index: 10;
  border-bottom: 0.5px solid var(--border);
}
.xb-topbar-title {
  font-family: Georgia, "Songti SC", "SimSun", serif;
  font-size: 20px;
  font-weight: 500;
}
.xb-topbar-action { font-size: 22px; color: var(--text); padding: 4px; }

/* 款式库：顶部（标题+搜索+筛选）整体吸附固定（2026-10-05 用户要求），仅卡片区滚动。
   容器内 .xb-topbar 改 static（由外层统一 sticky），其他页面不受影响。 */
.xb-stickhead { position: sticky; top: 0; z-index: 10; background: var(--bg); }
.xb-stickhead .xb-topbar { position: static; }

/* 选版大厅：双列 lookbook 网格 */
.xb-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  padding: 12px;
}
.xb-gcard {
  background: var(--surface);
  border: 0.5px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  cursor: pointer;
  transition: box-shadow .15s ease, transform .15s ease;
}
.xb-gcard-img {
  position: relative;
  width: 100%;
  aspect-ratio: 3 / 4;
  background: var(--surface-2);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.xb-gcard-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.xb-gcard-ph { color: var(--muted); font-size: 13px; }
/* V4.38 批量移除：管理模式下的勾选框（左上角圆形）+ 选中态描边 */
.xb-chk {
  position: absolute; top: 6px; right: 6px; width: 22px; height: 22px; border-radius: 50%;
  background: rgba(255,255,255,.85); border: 1.5px solid var(--border); cursor: pointer;
  display: flex; align-items: center; justify-content: center; z-index: 2;
  box-sizing: border-box;
}
.xb-chk.on { background: var(--accent); border-color: var(--accent); }
.xb-chk.on::after {
  content: ""; width: 6px; height: 11px; border: solid #fff; border-width: 0 2px 2px 0;
  transform: rotate(45deg) translate(-1px, -1px);
}
.xb-gcard-sel { outline: 2px solid var(--accent); outline-offset: -2px; }
.xb-gcard-sel .xb-gcard-img { opacity: .92; }
/* V4.38 批量移除底部操作条（**批次页专用**）。
   ⚠️⚠️ 类名必须用 `xb-batchbar`，**不能复用 `xb-selbar`** —— `xb-selbar` 已被 V4.26
   数据管理页的「勾选栏」占用（本文件后段那条白底规则），同优先级下**后写的赢**
   ⇒ 会把我这里的背景覆盖回白色（而文字色没被覆盖 → 白底白字看不见）；
   且我的 `position:sticky` 会反向污染管理页那条栏。2026-10-13 真踩过。
   配色：实色中棕 + 白字（两种主题都有对比）；bottom:12px 抬起避免底边贴视口被切。 */
.xb-batchbar {
  position: sticky; bottom: 12px; z-index: 5;
  display: flex; align-items: center; justify-content: space-between;
  margin: 10px 12px 0; padding: 10px 14px;
  background: #b5533a; border-radius: 12px;
  box-shadow: 0 6px 18px rgba(0,0,0,.28);
}
.xb-batchbar-sec { display: flex; align-items: center; gap: 12px; }
.xb-batchbar-cnt { font-size: 13px; color: #fff; }
.xb-batchbar-cnt b { font-size: 15px; font-weight: 600; color: #fff; }
.xb-batchbar-acts { display: flex; align-items: center; gap: 12px; }
.xb-batchbar-all { font-size: 13px; color: #fff; cursor: pointer; user-select: none; }
.xb-batchbar-all.on { color: rgba(255,255,255,.55); }
/* 条内按钮：深底上默认样式看不清，取消=白描边，移除=白底棕字（与棕底拉开对比） */
.xb-batchbar .xb-batchbar-cancel.van-button { color: #fff; border-color: rgba(255,255,255,.7); background: transparent; }
.xb-batchbar .xb-batchbar-del.van-button { color: #b5533a; background: #fff; border-color: #fff; font-weight: 600; }
.xb-batchbar .xb-batchbar-del.van-button.van-button--disabled { opacity: .55; }
.xb-gcard-body { padding: 8px 10px 10px; }
.xb-gcard-name {
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.xb-gcard-meta { color: var(--muted); font-size: 12px; margin-top: 2px; }
/* V4.34 卡片行内定稿胶囊：瀑布流/1/2列才会渲染（模板 gated by showQuick），
   用 flex-wrap 兜底，2列空间偏紧时自动折行而非溢出。 */
.xb-gcard-quick { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.xb-qchip {
  font-size: 11px; line-height: 1; padding: 4px 6px; border-radius: 10px;
  border: 1px solid var(--border); color: var(--muted); background: #fff;
  user-select: none; -webkit-user-select: none; cursor: pointer; white-space: nowrap;
}
/* 已勾：复用既有 stage 配色（与图片角标、统计卡一致） */
.xb-qchip.on.q-SELECTED { background: var(--sample-solid); color: var(--sample-ink); border-color: var(--sample-solid); }
.xb-qchip.on.q-SAMPLING  { background: #2f6fdb; color: #fff; border-color: #2f6fdb; }
.xb-qchip.on.q-SAMPLED  { background: #0e9aa0; color: #fff; border-color: #0e9aa0; }
.xb-qchip.on.q-REJECTED { background: var(--bulk-solid); color: #fff; border-color: var(--bulk-solid); }
/* 第一次点击的「待确认」态：橙色描边 + 轻微放大，提示"再点一次确认" */
.xb-qchip.pend { outline: 2px solid #ff6a00; outline-offset: 0; box-shadow: 0 0 0 2px rgba(255,106,0,.25); }
/* 无权限胶囊：置灰、不可点 */
.xb-qchip.dis { opacity: .4; pointer-events: none; }
.xb-cost { color: var(--accent); }
/* 状态标签。
   2026-10-06 V4.9（用户确认）：状态改名 + 配色调整——
   打样(原入选)=黄底深字(--sample-solid/--sample-ink)、做货(原淘汰)=绿底白字(--bulk-solid)；
   待定(原概念)与批次内待定保持白底灰字；「评审中」状态已删除（.st-IN_REVIEW 移除）。
   角标位置/尺寸/圆角不变；居中修正保留（字形天然偏下 0.4~0.6px，
   line-height:1 定死内容盒 + padding 下比上多 1px 光学补偿，实测偏移 ±0.125px，
   依据见 _probe/measure_badge_center.py）。 */
.xb-status {
  position: absolute;
  top: 8px;
  left: 8px;
  font-size: 11px;
  line-height: 1;
  padding: 5px 7px 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.9);
  color: var(--text);
}
.st-CONCEPT { color: var(--muted); }
.st-SELECTED { background: var(--sample-solid); color: var(--sample-ink); font-weight: 600; }
.st-SAMPLING { background: #2f6fdb; color: #fff; font-weight: 600; }
.st-SAMPLED { background: #0e9aa0; color: #fff; font-weight: 600; }
.st-REJECTED { background: var(--bulk-solid); color: #fff; font-weight: 600; }
.st-PENDING { color: var(--muted); }
/* 双勾款（打样+做货）角标并排（2026-10-06 V4.10 用户要求）：
   容器负责绝对定位，内部两个角标回到文档流，间距 4px（黄[打样] + 绿[做货]）。 */
.xb-statuswrap {
  position: absolute;
  top: 8px;
  left: 8px;
  display: flex;
  gap: 4px;
  z-index: 1;
}
.xb-statuswrap .xb-status { position: static; }
/* 评审会「进行中」高亮（原借用角标 .st-IN_REVIEW；2026-10-06 V4.9 该角标样式删除后独立定义） */
.xb-openflag { color: var(--accent); font-weight: 600; }
/* 评审页「最终定稿」多选勾选框（2026-10-06 V4.10：打样/做货是流程节点、可同时勾选，
   不应是单选按钮；勾上=实色，未勾=灰描边）。 */
/* V4.34.1：胶囊收窄（padding 5px 9px），并去掉 margin-left（间距交给容器 gap）。
   容器 .xb-stagechips 独占整行，4 枚一行排齐，不再挤在 van-cell 的值区换行错乱。 */
.xb-stagechip {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 12px;
  line-height: 1;
  padding: 5px 9px;
  border-radius: 999px;
  border: 0.5px solid var(--border);
  background: var(--surface);
  color: var(--muted);
  margin-left: 0;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
/* V4.35：标题 + 胶囊同一行的容器（标题固定左、胶囊组 flex:1 靠右） */
.xb-stagewrap { display: flex; align-items: center; gap: 10px; padding: 10px 16px 12px; flex-wrap: wrap; }
.xb-stage-k { font-size: 13px; color: var(--muted); flex: 0 0 auto; white-space: nowrap; }
/* V4.34.1：定稿胶囊独立整行容器（原塞在 van-cell 值区，4 枚会折成两行错位）；
   V4.35 改为嵌在 .xb-stagewrap 里（标题+胶囊同一行），自身 padding 归零、靠容器定位。 */
.xb-stagechips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  flex: 1 1 auto;
  align-items: center;
  justify-content: flex-end; /* V4.35.1：胶囊组靠右，与左侧标题平衡（用户反馈） */
  padding: 0;
}
.xb-stagechip-ic { font-size: 13px; }
.xb-stagechip.s-sample.on { background: var(--sample-solid); border-color: var(--sample-solid); color: var(--sample-ink); font-weight: 600; }
.xb-stagechip.s-prog.on { background: #2f6fdb; border-color: #2f6fdb; color: #fff; font-weight: 600; }
.xb-stagechip.s-bulk.on { background: var(--bulk-solid); border-color: var(--bulk-solid); color: #fff; font-weight: 600; }

/* 评审会卡片 */
.xb-scard {
  background: var(--surface);
  border: 0.5px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
  margin: 12px;
  cursor: pointer;
}
.xb-scard-head { display: flex; justify-content: space-between; align-items: baseline; }
.xb-scard-title { font-size: 16px; font-weight: 500; font-family: Georgia, "Songti SC", "SimSun", serif; }
.xb-scard-sub { color: var(--muted); font-size: 12px; margin-top: 4px; }
.xb-tag {
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--muted);
}
.xb-tag-open { color: var(--accent); }

/* 详情页画廊 */
.xb-gallery { width: 100%; }
.xb-gallery img { width: 100%; max-height: 60vh; object-fit: contain; background: var(--surface-2); }
.xb-info { padding: 14px; }
.xb-info-row { display: flex; justify-content: space-between; padding: 7px 0; border-bottom: 0.5px solid var(--border); }
.xb-info-row:last-child { border-bottom: none; }
.xb-info-k { color: var(--muted); font-size: 13px; }
.xb-info-v { font-size: 14px; }
/* 可跳转信息行（详情页「所属上款批次」→ 批次详情）：批次名 + 「跳转」小按钮 */
.xb-info-row-link { cursor: pointer; }
.xb-info-row-link:active { opacity: 0.55; }
.xb-info-row-link .xb-info-v { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.xb-goto-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 160px; }
.xb-goto-btn {
  display: inline-flex; align-items: center; flex-shrink: 0;
  font-size: 12px; line-height: 1;
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 999px;
  padding: 4px 8px;
}
.xb-goto-btn .van-icon { font-size: 11px; margin-left: 1px; }

/* 「AI 描述」（详情页）：视觉大模型生成的款式笔记；无笔记时（v-if）不渲染该块 */
.xb-note {
  margin: 0 16px 12px;
  padding: 10px 12px;
  background: var(--surface);
  border: 0.5px solid var(--border);
  border-radius: var(--radius);
}
.xb-note-h { color: var(--muted); font-size: 12px; margin-bottom: 6px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.xb-note-t { font-size: 13.5px; line-height: 1.65; }

/* ===== AI 描述 · 人工校订（2026-10-05 用户要求：AI 认错元素没法跟它沟通 → 手动改）=====
   手动改过的款打上标记，之后「补 AI 描述」自动跳过它，AI 不再覆盖。 */
.xb-note-tag {
  font-size: 10px; line-height: 1; padding: 3px 6px; border-radius: 9px;
  background: rgba(122, 92, 40, 0.1); color: #7a5c28;
}
.xb-note-tag-ai { background: rgba(0, 0, 0, 0.05); color: var(--muted); }
.xb-note-ops { display: flex; gap: 8px; margin-top: 9px; flex-wrap: wrap; }
.xb-note-btn {
  font-size: 12px; line-height: 1; padding: 7px 11px; cursor: pointer;
  border: 0.5px solid var(--border); border-radius: 15px;
  background: var(--surface); color: var(--muted);
}
.xb-note-btn:active { opacity: 0.6; }
.xb-note-btn:disabled { opacity: 0.45; cursor: default; }
.xb-note-btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.xb-note-btn-warn { color: #a34a2a; border-color: rgba(163, 74, 42, 0.4); }
.xb-note-edit {
  display: block; width: 100%; box-sizing: border-box;
  padding: 8px 9px; font-size: 13.5px; line-height: 1.6; color: var(--text);
  background: var(--bg); border: 0.5px solid var(--border); border-radius: 8px;
  resize: vertical; min-height: 84px; font-family: inherit;
}
.xb-note-edit:focus { outline: none; border-color: var(--accent); }
.xb-note-tip { font-size: 11px; color: var(--muted); margin-top: 7px; line-height: 1.5; }

/* ===== 款式详情 · 上下滑动切款（2026-10-07 V4.18 用户要求）=====
   底部「第 N / 共 M」指示：是**状态显示**不是按钮（用户明确要手势不要按钮），
   所以做得很轻，滑动时会亮起来，平时半透明不抢眼。 */
/* V4.18.1 款式详情页：整屏翻页（切上一款/下一款）**只平移内容层**，
   顶部栏 .xb-topbar 与底部 .xb-gnav 留在包装层外面保持不动
   （2026-10-07 用户要求"切款时顶栏钉住不动不消失"）。
   ⚠️ 别把 transform 挪回 .xb-shell —— 那样 .xb-gnav(position:fixed) 会变成
   "相对 .xb-shell 定位"而跟着页面一起走。 */
.xb-gbody { position: relative; }
.xb-gnav {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(12px + env(safe-area-inset-bottom));
  z-index: 20; display: flex; flex-direction: column; align-items: center; gap: 4px;
  pointer-events: none;   /* 纯指示，不挡下方内容与点击 */
}
.xb-gnav-n {
  font-size: 11px; line-height: 1; padding: 5px 10px; border-radius: 999px;
  background: rgba(0, 0, 0, 0.34); color: #fff; opacity: 0.6;
  transition: opacity 0.18s;
}
.xb-gnav.on .xb-gnav-n { opacity: 1; }
.xb-gnav-tip {
  font-size: 11px; line-height: 1; padding: 5px 10px; border-radius: 999px;
  background: rgba(0, 0, 0, 0.66); color: #fff; white-space: nowrap;
}

/* 详情页「这一款已不在款式库 / 你没权限」的错误说明（切款切到已归档的款时出现） */
.xb-gerr { padding: 30px 22px 6px; text-align: center; }
.xb-gerr-t { font-size: 15px; line-height: 1.6; }
.xb-gerr-s { font-size: 12px; color: var(--muted); margin-top: 8px; line-height: 1.6; }

/* ===== 款式详情 · 编辑款式资料弹层（V4.18，2026-10-07）===== */
.xb-editpop { display: flex; flex-direction: column; max-height: 86vh; }
.xb-editpop-h { padding: 16px 20px 8px; }
.xb-editpop-sub { font-size: 12px; color: var(--muted); margin-top: 4px; }
/* 表单本体可滚：字段多 + 手机上键盘弹起时，保存按钮必须始终够得着 */
.xb-editpop-body { flex: 1 1 auto; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.xb-editpop-tip { font-size: 11px; color: var(--muted); padding: 10px 20px 4px; line-height: 1.6; }
.xb-editpop-ops {
  flex: 0 0 auto; display: flex; flex-direction: column; gap: 8px;
  padding: 12px 16px calc(14px + env(safe-area-inset-bottom));
  border-top: 0.5px solid var(--border);
}
/* 选项值为空时的占位色（品类/季节/供应商显示「未填」） */
.xb-ph { color: var(--muted); }

/* 「AI 描述」管理区（数据管理页）：一键补笔记按钮 + 进度小字 */
.xb-ai-note-box { padding: 0 16px 8px; }
.xb-ai-note-stat { margin-top: 6px; text-align: center; color: var(--muted); font-size: 12px; }

/* 批量上传单次上限（2026-10-05）：管理页可调 1~100 张 */
.xb-batchmax {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: 10px; padding-top: 10px; border-top: 0.5px solid var(--border);
}
.xb-batchmax-l { font-size: 12px; color: var(--muted); }
.xb-batchmax-r { display: flex; gap: 4px; }
.xb-bm-btn {
  min-width: 32px; height: 26px; padding: 0 6px; cursor: pointer; line-height: 1;
  font-size: 12px; border: 0.5px solid var(--border); border-radius: 6px;
  background: var(--surface); color: var(--muted);
}
.xb-bm-btn.on { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }

/* 图片自动清理的开/关（2026-10-07 V4.15）。
   ⚠️ 与 .xb-bm-btn 视觉一致但**必须独立类名**：.xb-bm-btn 被 V3.4 测试用作
   「批量上传档位」的选择器，混用会让测试读到多余的按钮（实测踩到）。 */
.xb-sw-btn {
  min-width: 32px; height: 26px; padding: 0 6px; cursor: pointer; line-height: 1;
  font-size: 12px; border: 0.5px solid var(--border); border-radius: 6px;
  background: var(--surface); color: var(--muted);
}
.xb-sw-btn.on { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }

/* 2026-10-05 复审清理：以下 4 组样式全项目零引用（.xb-card 旧通用卡片、.xb-fab 旧浮动加号
   —— 已被 topbar 的 + 图标取代、.xb-filters —— 已改用 Vant DropdownMenu、
   .xb-chipbtn-on —— 筛选已改走 Vant）。父类 .xb-chipbtn / .xb-chipbtn-clear 仍在用，勿删。 */

/* 我的：区块标题 */
.xb-section-title {
  font-family: Georgia, "Songti SC", "SimSun", serif;
  font-size: 15px;
  color: var(--muted);
  padding: 18px 16px 6px;
}

/* 版本更新日志页 #/changelog（2026-10-07 用户要求，只读展示，所有登录角色可见）。 */
.xb-clog { padding: 12px 14px 4px; }
.xb-clog-sec { font-size: 13px; font-weight: 600; color: var(--muted); margin: 14px 4px 8px; }
.xb-clog-item { display: flex; gap: 12px; padding: 12px; background: var(--surface);
  border-radius: 12px; margin-bottom: 8px; border: 0.5px solid var(--border); }
.xb-clog-ver { flex: 0 0 auto; font-size: 13px; font-weight: 700; color: var(--accent);
  background: rgba(125, 125, 125, 0.12); padding: 3px 8px; border-radius: 8px;
  height: fit-content; white-space: nowrap; }
.xb-clog-main { flex: 1; min-width: 0; }
.xb-clog-date { font-size: 11px; color: var(--muted); margin-bottom: 4px; }
.xb-clog-pts { margin: 0; padding-left: 16px; }
.xb-clog-pts li { font-size: 13px; line-height: 1.5; color: var(--text); margin: 2px 0; }
.xb-clog-base { padding: 12px; background: var(--surface); border-radius: 12px;
  margin-bottom: 8px; border: 0.5px solid var(--border); }
.xb-clog-btitle { font-size: 14px; font-weight: 600; color: var(--text); margin-bottom: 3px; }
.xb-clog-bdesc { font-size: 13px; line-height: 1.5; color: var(--muted); }
.xb-clog-foot { text-align: center; font-size: 11px; color: var(--muted);
  padding: 16px 0 calc(16px + env(safe-area-inset-bottom)); }

/* 评审页：图片 + 圈点标注 */
.xb-imgwrap {
  position: relative;
  width: 100%;
  background: var(--surface-2);
  line-height: 0;
}
.xb-mainimg { width: 100%; display: block; }
.xb-dot {
  position: absolute;
  transform: translate(-50%, -50%);
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-size: 11px;
  line-height: 20px;
  text-align: center;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
}
.xb-dot-pending { background: var(--muted); }

/* 评审页：上一个 / 下一个 快捷条（2026-10-05 用户要求：顶栏下方吸附，不遮内容） */
.xb-review-head { border-bottom: 0.5px solid var(--border); }
.xb-review-head .xb-topbar { border-bottom: none; }
.xb-pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 12px 8px;
}
.xb-pager .van-button { min-width: 88px; }
.xb-pager .van-button__icon { font-size: 13px; }
.xb-pager-ic { font-size: 12px; margin-left: 2px; }
.xb-pager-pos { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }

/* 评审页：圈点标注入口（2026-10-05 用户要求：从讨论区下方移到图片正下方） */
.xb-annobar { padding: 10px 16px 2px; }
.xb-annobar-hint { padding-top: 6px; color: var(--accent); font-size: 12px; text-align: center; }

/* P4 决策汇总卡片 */
.xb-summary { padding: 6px 12px 4px; }
.xb-summary-title {
  font-family: Georgia, "Songti SC", "SimSun", serif;
  font-size: 17px;
  margin: 10px 2px 10px;
}
/* V4.34.1：定稿状态扩到 6 张（总款/可打样/打样中/已出样/做货/待定），
   改 6 列 + 收窄内边距与字号，保证一行放下不换行（用户 2026-10-12 要求）。 */
.xb-stat-row {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 6px;
  margin-bottom: 14px;
}
.xb-stat {
  background: var(--surface);
  border: 0.5px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 2px;
  text-align: center;
  min-width: 0;
}
.xb-stat-n { font-size: 18px; font-weight: 600; font-family: Georgia, serif; }
.xb-stat-l { font-size: 11px; color: var(--muted); margin-top: 2px; white-space: nowrap; }
/* 数字配色跟随角标色系（2026-10-06 V4.9）：打样=深琥珀、做货=绿 */
.xb-stat.st-sel .xb-stat-n { color: #9a6a05; }
.xb-stat.st-prog .xb-stat-n { color: #2f6fdb; }
.xb-stat.st-prog2 .xb-stat-n { color: #0e9aa0; }
.xb-stat.st-rej .xb-stat-n { color: #2f7d3d; }
/* 范围选择（2026-10-06 V4.9 用户要求：可选打样 / 做货 / 都选） */
.xb-scoperow { display: flex; align-items: center; gap: 8px; margin: 0 0 12px; }
.xb-scope-k { font-size: 12px; color: var(--muted); }
.xb-scope-chip {
  font-size: 12px; line-height: 1; padding: 7px 14px; border-radius: 999px;
  border: 0.5px solid var(--border); color: var(--muted);
  background: var(--surface); cursor: pointer; user-select: none;
}
.xb-scope-chip.on { background: var(--accent); color: #fff; border-color: var(--accent); }
/* 范围 chip 选中色随状态角标色系（2026-10-06 V4.9：打样=黄、做货=绿，独立多选） */
.xb-scope-chip.s-sample.on { background: var(--sample-solid); color: var(--sample-ink); border-color: var(--sample-solid); font-weight: 600; }
.xb-scope-chip.s-prog.on { background: #2f6fdb; color: #fff; border-color: #2f6fdb; font-weight: 600; }
.xb-scope-chip.s-prog2.on { background: #0e9aa0; color: #fff; border-color: #0e9aa0; font-weight: 600; }
.xb-scope-chip.s-bulk.on { background: var(--bulk-solid); color: #fff; border-color: var(--bulk-solid); font-weight: 600; }
/* ===== 批次页「状态筛选」栏（2026-10-07 用户要求）=====
   全部 / 待定 / 打样 / 做货 四枚胶囊**居中**排列；多选 + 交集语义。
   选中配色与卡片角标保持一致（待定=灰、打样=黄、做货=绿），用户一眼能对上。
   ⚠️ 刻意用独立类名 .xb-fchip（**不复用** .xb-scope-chip）：下方「决策汇总」的
      「范围」也用 .xb-scope-chip，混用会让两处选择器互相污染 ——
      V4.15 已因此让 V3.4 的档位按钮测试误判过一次（见 MEMORY）。 */
.xb-sfilter {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 6px;
  /* V4.34.1：定稿状态胶囊从 4 枚加到 6 枚后，胶囊行总宽大增，
     会顶到右侧**绝对定位**的排列按钮（截图实测已相互挤压）。
     右侧预留 48px 给按钮，胶囊永远碰不到它；
     代价是居中基准略左偏（比"胶囊压按钮"好得多）。
     V4.19.1 的"左右对称"规则就此让位于"不重叠"。 */
  padding: 11px 48px 11px 16px; background: var(--surface);
  border-top: 0.5px solid var(--border); border-bottom: 0.5px solid var(--border);
  position: relative;
}
/* V4.19（2026-10-07 用户要求）：批次页也加排列切换按钮，跟款式库页一致。
   复用全局 .xb-layoutbtn（首页同款图标按钮），这里只负责定位到筛选行**最右**：
   绝对定位 ⇒ 四枚胶囊的居中布局不被挤动（V4.19.1 起筛选行 padding 左右对称）。 */
.xb-sfilter .xb-sfilter-lay {
  position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
}
.xb-fchip {
  font-size: 12px; line-height: 1; padding: 7px 11px; border-radius: 999px;
  border: 0.5px solid var(--border); color: var(--muted);
  background: var(--surface); cursor: pointer; user-select: none; white-space: nowrap;
}
.xb-fchip b { font-weight: 400; opacity: .8; margin-left: 3px; }
.xb-fchip:active { opacity: .7; }
.xb-fchip.on { background: var(--accent); color: #fff; border-color: var(--accent); font-weight: 600; }
/* 待定：灰底+深字（白字在 soft 主题的浅灰上对比度不足 4.5:1） */
.xb-fchip.f-pending.on { background: var(--muted); color: var(--text); border-color: var(--muted); }
.xb-fchip.f-sample.on { background: var(--sample-solid); color: var(--sample-ink); border-color: var(--sample-solid); }
.xb-fchip.f-prog.on { background: #2f6fdb; color: #fff; border-color: #2f6fdb; }
.xb-fchip.f-bulk.on { background: var(--bulk-solid); color: #fff; border-color: var(--bulk-solid); }
/* 已归档款提示（2026-10-07 V4.17）：归档的款在批次里**彻底不显示**，
   所以这行负责"说清为什么数字比款数少、以及去哪恢复"，避免用户以为丢数据。 */
.xb-arc-note {
  margin: 10px 16px 0; padding: 9px 11px; font-size: 12px; line-height: 1.6;
  color: var(--muted); background: var(--surface-2);
  border: 0.5px solid var(--border); border-radius: var(--radius);
}
.xb-arc-note b { color: var(--text); }
.xb-arc-note-sub { margin-top: 2px; opacity: .9; }
.xb-export-btn { margin: 0 0 10px; }
.xb-summary-sub { text-align: center; color: var(--muted); font-size: 12px; margin: 2px 0 12px; }

/* ---------- 大文件下载进度弹层（2026-10-06 V4.10.1）----------
   背景：37MB 原图 ZIP 在服务器上行 ~1MB/s 下要传 ~40 秒。
   原实现 blob() 全下完才给结果 → 期间零反馈、断线即 Failed to fetch。
   现在用 dlprogress.js 自绘（vant.min.js 按需构建，<van-progress> 不存在）。 */
.xb-dlmask {
  position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 3000;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, 0.45); padding: 24px;
}
.xb-dlbox {
  width: 100%; max-width: 320px; background: var(--surface);
  border-radius: 14px; padding: 20px 18px 16px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.18);
}
.xb-dl-t { font-size: 15px; font-weight: 600; margin-bottom: 4px; }
.xb-dl-f {
  font-size: 12px; color: var(--muted); word-break: break-all;
  margin-bottom: 14px; line-height: 1.4;
}
.xb-dl-track {
  height: 8px; border-radius: 999px; background: var(--surface-2);
  overflow: hidden; position: relative;
}
.xb-dl-bar {
  height: 100%; width: 0; border-radius: 999px;
  background: var(--accent); transition: width 0.25s linear;
}
/* 未知大小（拿不到 Content-Length）时走来回滑动，表示"还在动" */
.xb-dl-track.indet .xb-dl-bar {
  width: 30% !important; animation: xbdlslide 1.1s ease-in-out infinite;
}
@keyframes xbdlslide {
  0% { margin-left: -30%; } 100% { margin-left: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .xb-dl-track.indet .xb-dl-bar { animation: none; width: 100% !important; opacity: 0.5; }
  .xb-dl-bar { transition: none; }
}
.xb-dl-pct {
  font-size: 13px; font-weight: 600; margin-top: 10px;
  font-variant-numeric: tabular-nums;   /* 数字等宽，进度跳动时不抖 */
}
.xb-dl-tip { font-size: 12px; color: var(--muted); margin-top: 3px; min-height: 17px; line-height: 1.4; }
.xb-dlmask.ok .xb-dl-bar { background: var(--bulk-solid); }
.xb-dlmask.err .xb-dl-bar { background: #d93025; }
.xb-dl-act { display: none; gap: 10px; margin-top: 16px; }
.xb-dl-btn {
  flex: 1; height: 40px; border-radius: 10px; font-size: 14px;
  border: 0.5px solid var(--border); background: var(--surface-2); color: var(--text);
}
.xb-dl-btn.xb-dl-ok { background: var(--accent); color: #fff; border-color: var(--accent); }
/* 清单分组标题（打样 / 做货；2026-10-06 V4.9） */
.xb-selgroup { font-size: 13px; font-weight: 500; color: var(--text); margin: 12px 2px 6px; }

/* 打样清单（明细列表） */
.xb-sellist { display: flex; flex-direction: column; gap: 8px; }
.xb-selitem {
  display: flex;
  align-items: center;
  background: var(--surface);
  border: 0.5px solid var(--border);
  border-radius: var(--radius);
  padding: 8px;
  cursor: pointer;
}
.xb-selitem-img {
  width: 52px; height: 52px; flex: 0 0 52px;
  border-radius: 8px; overflow: hidden; background: var(--surface-2);
  display: flex; align-items: center; justify-content: center;
}
.xb-selitem-img img { width: 100%; height: 100%; object-fit: cover; }
.xb-selitem-ph { color: var(--muted); font-size: 11px; }
.xb-selitem-info { margin-left: 10px; min-width: 0; }
.xb-selitem-name { font-size: 14px; font-weight: 500; }
.xb-selitem-meta { color: var(--muted); font-size: 12px; margin-top: 2px; }

/* P4 打印页（打样清单） */
.xb-print { min-height: 100%; background: #fff; color: #1f1d1a; }
.xb-print-bar {
  display: flex; align-items: center; justify-content: space-between;
  padding: calc(10px + env(safe-area-inset-top)) 14px 10px;
  border-bottom: 0.5px solid #e6e2dc; position: sticky; top: 0; background: #fbfaf7; z-index: 5;
}
.xb-print-back { font-size: 22px; }
.xb-print-hint { font-size: 12px; color: #8a8580; padding: 8px 14px; }
.xb-print-doc { padding: 20px 22px 30px; max-width: 820px; margin: 0 auto; }
.xb-print-h1 { font-family: Georgia, "Songti SC", "SimSun", serif; font-size: 26px; font-weight: 500; margin: 6px 0 4px; text-align: center; }
.xb-print-sub { text-align: center; color: #8a8580; font-size: 13px; margin-bottom: 18px; }
.xb-print-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.xb-print-table th, .xb-print-table td {
  border: 0.5px solid #d8d3cc; padding: 7px 6px; text-align: center; vertical-align: middle;
}
.xb-print-table thead th { background: #f3efe9; font-weight: 600; }
.xb-print-table td { text-align: left; }
.xb-print-table td:nth-child(1), .xb-print-table td:nth-child(2),
.xb-print-table td:nth-child(8), .xb-print-table td:nth-child(9) { text-align: center; }
/* 2026-10-13 二轮审查：原选择器里还有 `td:nth-child(10)` —— 打印表只有 **9 列**
   （图/编号/名称/品类/季节/成本/供应商/均分/结果，见 print.js 表头），
   第 10 列永不命中，留着会让后来者以为还有一列要居中。已删。 */
.xb-print-img { width: 56px; }
.xb-print-img img { width: 46px; height: 46px; object-fit: cover; border-radius: 4px; display: block; margin: 0 auto; }
.xb-pst-SELECTED { color: #9a6a05; font-weight: 600; }
.xb-pst-REJECTED { color: #2f7d3d; }
.xb-pst-PENDING { color: #8a8580; }
/* 双勾（打样+做货）：绿色加粗（已进入做货阶段；V4.10） */
.xb-pst-DUAL { color: #2f7d3d; font-weight: 600; }
.xb-print-foot { text-align: center; color: #8a8580; font-size: 11px; margin-top: 18px; }

/* ===== 电脑/平板：保持移动端显示效果（限宽居中，不被拉伸变形）=====
   ⚠️ 限宽挂在 **#app**（index.html 里所有页面的共同挂载点），而不是逐个页面容器：
      页面根容器有 .xb-shell(10个) / .xb-page(登录,注册) / .xb-print(打印) 三种，
      V1.7 只写了 .xb-shell → 登录页在电脑版撑满 1280（用户 2026-10-04 报"解决问题要全面"）。
      挂 #app 一处生效，任何新页面自动受限。 */
#app { max-width: 560px; margin: 0 auto; background: var(--bg); }
/* 2026-10-13：这里原本还有一条 `.xb-shell { min-height: 100%; }`，与第 53 行**一字不差**
   重复（当年加 PC 限宽时顺手添的，而上面这段注释正是在说"别再逐个页面容器写"）。纯冗余，删。 */

/* ===== 宽屏渐进增强（V4.36 平板/电脑适配）=====
   ⚠️ 全部锁在 min-width 断点内：手机(≤560)完全走原样式，零回退。
   限宽挂在 #app（所有页面共同挂载点），任何新页面自动受限。 */
@media (min-width: 561px) {
  body { background: #e9e6e0; }
  #app { min-height: 100vh; box-shadow: 0 0 28px rgba(0,0,0, .07); }
  /* teleport 到 body 的浮层：561~767 段沿用 560（#app 仍是 560），由下面断点逐级放宽 */
  .van-tabbar, .van-toast, .van-dropdown-item, .van-popup, .van-action-sheet {
    max-width: 560px; left: 50% !important; right: auto !important;
    transform: translateX(-50%);
  }
  .van-dropdown-item { width: 560px !important; max-width: 100vw; }
}
/* 平板竖屏 / 小屏笔记本 */
@media (min-width: 768px) {
  #app { max-width: 720px; }
  .van-tabbar, .van-toast, .van-dropdown-item, .van-popup, .van-action-sheet { max-width: 720px; }
  .van-dropdown-item { width: 720px !important; }
}
/* 平板横屏 / 笔记本：启用桌面左侧导航（B.1） */
@media (min-width: 1024px) {
  #app { max-width: 960px; }
  /* 侧栏页腾位（V4.37.1 重做）：不再用 margin-left:200/margin-right:0 —— 那会把
     #app 的自动居中干掉，内容贴左、右边大片空白（用户 2026-10-12 真机截图反馈）。
     改为 body 左 padding 200px（侧栏是 fixed，不占流），#app 照旧 margin:auto
     → 在「侧栏右侧的剩余区域」内完美居中。router.render 给这三页的 body 加 .xb-widescreen。 */
  body.xb-widescreen { padding-left: 200px; }
  /* teleport 到 body 的浮层跟着对齐：居中基准从视口中心(50vw) 变为侧栏右侧区域中心
     (200 + (100vw-200)/2 = 50vw+100px)。dropdown 面板则要与 #app 同宽同位。 */
  body.xb-widescreen .van-popup,
  body.xb-widescreen .van-action-sheet,
  body.xb-widescreen .van-toast {
    left: calc(50vw + 100px) !important;
  }
  /* V4.38.6：dropdown 的选项内容 .van-dropdown-item__content 同时挂着 .van-popup 类，
     但它是 absolute 定位、基准是**面板盒子**（.van-dropdown-item，fixed）而非视口，
     上面那条视口坐标 left 会把它推偏（实测 1440 下面板 220..1420，选项盒跑到 680..1400）。
     改回「面板内水平居中」——面板已与 #app 同宽同位，选项盒自然落在筛选栏正下方。 */
  body.xb-widescreen .van-dropdown-item .van-dropdown-item__content {
    left: 50% !important;
    transform: translateX(-50%);
  }
  body.xb-widescreen .van-dropdown-item {
    width: min(960px, calc(100vw - 200px)) !important;
    left: calc(200px + (100vw - 200px - min(960px, 100vw - 200px)) / 2) !important;
    right: auto !important; transform: none !important;
  }
  .van-tabbar, .van-toast, .van-dropdown-item, .van-popup, .van-action-sheet { max-width: 960px; }
  /* V4.37.2：表单类弹层收窄到 720（跟 960/1200 的内容区等宽会太空旷） */
  .van-toast, .van-popup, .van-action-sheet { max-width: 720px; }
  .van-dropdown-item { width: 960px !important; }
  /* B.1 V4.37.4：桌面侧栏改为路由统一管理的 #xb-sidebar（全页面常驻）。
     之前"把 van-tabbar 重定位成侧栏"的死穴：tabbar 只在三个主页渲染，
     一进详情/批次/评审页侧栏就整个消失（用户 2026-10-12 反馈）。
     现在桌面直接隐藏底部 tabbar（手机 <1024 仍是底部栏，零影响）。 */
  .van-tabbar { display: none !important; }
  .xb-tabbar-pad { display: none !important; }
  #xb-sidebar {
    position: fixed; left: 0; top: 0; bottom: 0; width: 200px; z-index: 100;
    background: var(--surface, #fff); box-shadow: 2px 0 16px rgba(0,0,0,.08);
    padding: 18px 0 14px; box-sizing: border-box;
  }
  #xb-sidebar .xb-sb-brand {
    padding: 2px 20px 14px 28px; font-size: 16px; font-weight: 600;
    color: #3a3a3a; letter-spacing: 1px;
  }
  #xb-sidebar .xb-sb-item {
    display: flex; align-items: center; position: relative;
    height: 46px; padding: 0 16px 0 28px; box-sizing: border-box;
    color: var(--ink, #333); text-decoration: none; font-size: 14px; cursor: pointer;
  }
  #xb-sidebar .xb-sb-item .van-icon { font-size: 20px; margin-right: 12px; }
  #xb-sidebar .xb-sb-item:hover { background: rgba(0,0,0,.035); }
  #xb-sidebar .xb-sb-item.on { background: rgba(0,0,0,.05); }
  #xb-sidebar .xb-sb-item.on::before {
    content: ""; position: absolute; left: 0; top: 9px; bottom: 9px; width: 3px;
    background: var(--accent, #ee0a24); border-radius: 0 3px 3px 0;
  }
  /* 款式详情底部「N / M」切款指示：居中基准从视口改为侧栏右侧区域 */
  body.xb-widescreen .xb-gnav { left: calc(50vw + 100px); }
  /* V4.37.4：款式详情桌面双栏 —— 左图右信息（手机仍是上图下信息，零改动）。
     .xb-gbody 子元素顺序：gerr / gallery / info / gtags / note / 加入批次按钮 / tabbar-pad。
     gallery 显式占左列并跨 8 行 + sticky，其余自动落到右列。 */
  .xb-gbody {
    display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    column-gap: 18px; align-items: start;
    max-width: 1500px; margin: 0 auto; padding: 0 18px; box-sizing: border-box;
  }
  .xb-gbody .xb-gerr { grid-column: 1 / -1; }
  .xb-gbody .xb-gallery {
    grid-column: 1; grid-row: 1 / span 8;
    position: sticky; top: 56px;
  }
  .xb-gbody .xb-gallery img { max-height: calc(100vh - 130px); }
  /* 右栏信息块撑满：V4.36 的 ".xb-info max-width:720 + margin:auto" 是给评审页文字块定的，
     在 grid 里 auto margin 会变 fit-content（实测右栏被压成 155px 宽）——双栏里必须覆盖 */
  .xb-gbody .xb-info { grid-column: 2; max-width: none; margin: 14px 0 0; }
  .xb-gbody .xb-gtags, .xb-gbody .xb-note, .xb-gbody .xb-gadd { grid-column: 2; }
}
/* 大桌面（V4.37.2 放宽：原 1200 上限在 1920/2560 宽屏下两边各空 300~500px，
   用户反馈"又空又碎"。改为随视口自适应、上限逐级放大；弹层（表单类）保持紧凑不跟宽。 */
@media (min-width: 1440px) {
  #app { max-width: min(1600px, calc(100vw - 240px)); }
  .van-toast, .van-popup, .van-action-sheet { max-width: 720px; }
  /* ⚠️ 2026-10-17：1024 块的 .van-dropdown-item{max-width:960px} 在这里还活着（同特异性
     后写才赢，这条在它后面所以能赢）——只放宽 width 不放宽 max-width，面板会被钳在
     960 宽，而 #app 已放宽到 1200/2000 → 面板+遮罩与内容区错位（用户真机截图反馈）。
     遮罩 .van-overlay 是 absolute inset:0 撑满面板盒，面板多窄黑幕就多小。必须同步放开。 */
  .van-dropdown-item { width: min(1600px, calc(100vw - 240px)) !important; max-width: none; }
  body.xb-widescreen .van-dropdown-item {
    width: min(1600px, calc(100vw - 240px)) !important;
    left: calc(200px + (100vw - 200px - min(1600px, calc(100vw - 240px))) / 2) !important;
    max-width: none;
  }
}
/* 超宽屏（1920+）：内容铺到 2000，避免卡片被拉得过大。
   ⚠️ 2026-10-13：瀑布流列数的 1920/2400 两条**原先写在本块里**，但下面
   （原 879/886 行）还有 @media(1024)/@media(1440) 两条同特异性的
   grid-template-columns —— 同特异性「后写的赢」，于是 1440 那条永远压住
   1920/2400，5 列/6 列从未生效。已挪到 1440 块之后（见文件后段），
   全局断点统一按 561→768→1024→1440→1920→2400 递增排列。 */
@media (min-width: 1920px) {
  #app { max-width: min(2000px, calc(100vw - 240px)); }
  .van-dropdown-item { width: min(2000px, calc(100vw - 240px)) !important; max-width: none; }
  body.xb-widescreen .van-dropdown-item {
    width: min(2000px, calc(100vw - 240px)) !important;
    left: calc(200px + (100vw - 200px - min(2000px, calc(100vw - 240px))) / 2) !important;
    max-width: none;
  }
}

/* ===== 款式库：布局切换（2026-10-05 用户要求）=====
   演进：2/3/4 → 1/2/3/4/瀑布 五个小方块 → 归拢成 1 个「布局」按钮，点一下轮换。
   原因：五个 24px 方块在手机上也难点，还把「批次」筛选项挤得紧。
   现在按钮上直接写当前模式名（"布局 · 瀑布流"），不看也知道用的是哪个。 */
.xb-colswitch { display: flex; align-items: center; padding-right: 10px; flex: none; }
.xb-layoutbtn {
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  height: 26px; padding: 0 9px; cursor: pointer; line-height: 1;
  border: 0.5px solid var(--border); border-radius: 13px;
  background: var(--surface); color: var(--muted);
  font-size: 12px; white-space: nowrap;
}
/* 2026-10-06 用户要求：去掉「布局 · 瀑布流」文字，只留图标。
   原来带文字时按钮约 60px 宽，把筛选栏的「批次」挤到换行；纯图标后约 32px。
   当前模式名放在 title/aria-label（长按提示、读屏可读）。 */
.xb-layoutbtn.ico-only { width: 30px; padding: 0; }
.xb-layoutbtn:active { opacity: 0.6; }
/* 按钮里的示意图标：按当前列数画小方块，一眼看出是几列 */
.xb-ico-cols { display: inline-flex; gap: 1.5px; align-items: center; width: 14px; height: 12px; }
.xb-ico-cols b { display: block; width: 3px; height: 12px; border-radius: 1px; background: currentColor; }
.xb-ico-cols b.c1 { width: 14px; }
.xb-ico-cols b.c2 { width: 6.5px; }
.xb-ico-cols b.c3 { width: 4px; }
.xb-ico-cols b.c4 { width: 2.5px; }
/* V4.36：5/6 列指示（容器宽 14px，越细越挤；留白靠 overflow 自然截断） */
.xb-ico-cols b.c5 { width: 1.7px; }
.xb-ico-cols b.c6 { width: 1.3px; }
/* 瀑布流：两列错落的实心块（高低不同） */
.xb-ico-cols b.cmasonry { width: 6px; height: 12px; box-shadow: 8px -2px 0 0 currentColor, 8px 3px 0 0 currentColor; }

/* 下拉筛选标题收紧字号（2026-10-05）。
   ⚠️ 2026-10-06 三次修，教训都记在这：
   ①「选中批次后整排消失」真因是 JS（模板裸调 _sessName 未加 this. → ReferenceError
      → 组件树被卸载），已修 home.js，与 CSS 无关。
   ②我一度把 item 的 flex 从 `flex:1` 改成 `flex:0 1 auto`，结果宽屏下五项各只占 32px
      挤在最左边、右侧 236px 空白（用户截图反馈"问题更大了"）。
   ③本轮发现选择器写错了：真正的 flex 子元素是 **`.van-dropdown-menu__item`**（含
      `menu__`），我写的是 `.van-dropdown-item`（Vant 另有一个同名 Popup 用这个类名），
      所以 flex:1 一直没生效。标题文字还被 `<div class="van-ellipsis">` 包着，
      省略号要作用到这一层。
   现在的正确做法：等分用 flex:1 1 0（basis:0，不被标题长短顶开），
   配 min-width:0 允许收缩到内容以下 → 宽屏均匀铺开、手机不撑破、长标题显示省略号。 */
.xb-toolbar .van-dropdown-menu__title {
  font-size: 13px; padding: 0 3px;
  max-width: 100%; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.xb-toolbar .van-dropdown-menu__item {
  flex: 1 1 0;        /* 等分铺满（basis:0，不受标题长短影响） */
  min-width: 0;       /* 可收缩到内容以下（flex 默认 min-width:auto 会顶破容器） */
}
/* 标题文字被 Vant 包在 .van-ellipsis 里，收缩/省略号要作用到这一层 */
.xb-toolbar .van-dropdown-menu__title > .van-ellipsis {
  display: block; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 2026-10-13：原本这里有 `.xb-toolbar{gap:6px}` 和 `.xb-dd{flex:1 1 auto;...}` 两条，
   但文件后段（宽屏工具条那一节）有同特异性的 `.xb-toolbar{...gap:8px}` / `.xb-dd{flex:1}`
   且位置更靠后 ⇒ 这两条是永久失效的死规则：改它没反应，排查时最坑。已删。 */
/* ===== 评审页 · 定稿记录（2026-10-05 用户要求：定稿人 / 时间 / 状态变化）=====
   数据来自 audit_log(action=item_result)，所有角色可见（含供应商）。 */
.xb-decisions {
  margin: 12px 16px 0; padding: 10px 12px;
  background: var(--surface); border: 0.5px solid var(--border); border-radius: 10px;
}
.xb-decisions-h { font-size: 12px; color: var(--muted); margin-bottom: 6px; }
.xb-dlog { display: flex; gap: 8px; padding: 5px 0; }
.xb-dlog + .xb-dlog { border-top: 0.5px solid var(--border); }
.xb-dlog-dot {
  flex: none; width: 7px; height: 7px; border-radius: 50%;
  background: var(--muted); margin-top: 6px;
}
.xb-dlog-dot.dl-SELECTED { background: var(--sample-solid); }
.xb-dlog-dot.dl-SAMPLING { background: #2f6fdb; }
.xb-dlog-dot.dl-SAMPLED  { background: #0e9aa0; }
.xb-dlog-dot.dl-REJECTED { background: var(--bulk-solid); }
.xb-dlog-dot.dl-PENDING   { background: var(--muted); }
/* 双勾（打样+做货）：圆点用黄→绿渐变表示"两段流程都走过"（V4.10） */
.xb-dlog-dot.dl-DUAL { background: linear-gradient(90deg, var(--sample-solid) 50%, var(--bulk-solid) 50%); }
.xb-dlog-main { min-width: 0; flex: 1; }
.xb-dlog-t { font-size: 13px; line-height: 1.4; word-break: break-all; }
.xb-dlog-t b { font-weight: 600; }
.xb-dlog-chg { color: var(--muted); margin: 0 3px; }
.xb-dlog-to { font-weight: 600; }
/* 记录行里「打样」「做货」两个小徽标相邻时的间距（组合状态用） */
.xb-dlog-to + .xb-dlog-to { margin-left: 3px; }
.xb-dlog-time { font-size: 11px; color: var(--muted); margin-top: 2px; }

.xb-grid-1 { grid-template-columns: 1fr; }
.xb-grid-3 { grid-template-columns: repeat(3, 1fr); }
.xb-grid-4 { grid-template-columns: repeat(4, 1fr); }
.xb-grid-3 .xb-gcard-meta, .xb-grid-4 .xb-gcard-meta,
.xb-grid-3 .xb-gcard-tags, .xb-grid-4 .xb-gcard-tags { display: none; }
.xb-grid-3 .xb-gcard-name, .xb-grid-4 .xb-gcard-name {
  font-size: 12px; line-height: 1.35; margin-top: 4px;
}
.xb-grid-3 .xb-gcard-body, .xb-grid-4 .xb-gcard-body { padding: 6px 7px 8px; }
/* V4.36：宽屏 5/6 列（HOME_COLS_CYCLE 已加 "5"/"6"）。窄屏隐藏次要信息，避免挤。
   注：masonry 默认两列在桌面会过大，另有 @media(min-width:1024px) 重排为多列（见下方）。 */
.xb-grid-5 { grid-template-columns: repeat(5, 1fr); }
.xb-grid-6 { grid-template-columns: repeat(6, 1fr); }
.xb-grid-5 .xb-gcard-meta, .xb-grid-6 .xb-gcard-meta,
.xb-grid-5 .xb-gcard-tags,  .xb-grid-6 .xb-gcard-tags { display: none; }
.xb-grid-5 .xb-gcard-name, .xb-grid-6 .xb-gcard-name {
  font-size: 12px; line-height: 1.35; margin-top: 4px;
}
.xb-grid-5 .xb-gcard-body, .xb-grid-6 .xb-gcard-body { padding: 6px 7px 8px; }

/* 「1」档单图模式 & 瀑布流：图片按原比例完整显示（不裁切，宽图最完整；
   超长图限高 72vh 防占满屏）。列表用 600px 缩略图（原比例），加载快。 */
.xb-grid-1 .xb-gcard-img, .xb-masonry .xb-gcard-img { aspect-ratio: auto; }
.xb-grid-1 .xb-gcard-img img, .xb-masonry .xb-gcard-img img {
  width: 100%; height: auto; max-height: 72vh; object-fit: contain;
}

/* 瀑布流：2 列 flex + 卡片自然高度（图片未加载时给占位高度，减少跳动） */
.xb-masonry { display: flex; gap: 10px; padding: 12px; align-items: flex-start; }
.xb-mcol { flex: 1; min-width: 0; }
.xb-mcol .xb-gcard { margin-bottom: 10px; }
.xb-masonry .xb-gcard-img { min-height: 120px; }

/* ===== V4.36 桌面适配补充 ===== */
/* 桌面（≥1024）：瀑布流默认两列会把卡片拉得过大 → 用 grid 重排多列。
   display:contents 让 .xb-mcol 包裹层消失，子卡片直接成为 .xb-masonry 的 grid item，
   无需改 JS 分列逻辑；手机端完全不受影响（只在 min-width 断点内）。 */
@media (min-width: 1024px) {
  .xb-masonry { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; align-items: start; padding: 14px; }
  .xb-masonry .xb-mcol { display: contents; }
  .xb-masonry .xb-gcard { margin-bottom: 0; }
  /* A.3 文字密集块限宽，避免 960/1200 容器里一行拉到 30+ 字难读（仅宽屏） */
  .xb-info, .xb-note, .xb-decisions { max-width: 720px; margin-left: auto; margin-right: auto; }
}
@media (min-width: 1440px) {
  .xb-masonry { grid-template-columns: repeat(4, 1fr); }
}
/* 2026-10-13：超宽屏加列 —— **必须排在 1440 之后**否则被覆盖（原因见文件前段注释）。
   断点递增排列，同特异性下后写的生效：1024→3 列 / 1440→4 列 / 1920→5 列 / 2400→6 列。 */
@media (min-width: 1920px) {
  .xb-masonry { grid-template-columns: repeat(5, 1fr); }
}
@media (min-width: 2400px) {
  .xb-masonry { grid-template-columns: repeat(6, 1fr); }
}
/* B.3 桌面 hover（@media(hover:hover) 只在真实指针设备生效，触屏不触发，手机零影响） */
@media (hover: hover) {
  .xb-gcard:hover { box-shadow: 0 4px 18px rgba(0,0,0,.14); transform: translateY(-2px); }
  .xb-layoutbtn:hover, .xb-chipbtn:hover, .xb-dc-btn:hover,
  .xb-note-btn:hover, .xb-dup-btn:hover { opacity: .82; }
}

/* ===== V4.37 B.2 宽屏双栏：批次页左列表 + 右评审详情 =====
   右栏是 iframe 内嵌 #/review/{id}?embed=1；仅 wide(≥1024) 且点过卡片才渲染 DOM，
   手机/窄屏 .xb-mdwrap/.xb-mdlist 是无样式普通块级容器 → 零影响。
   sticky 让右栏跟随滚动（左列表长列表滑动时评审页始终可见）。 */
@media (min-width: 1024px) {
  .xb-mdwrap { display: flex; align-items: flex-start; gap: 14px; }
  .xb-mdlist { flex: 1 1 auto; min-width: 0; }
  .xb-mdpane {
    flex: 0 0 460px;
    position: sticky; top: 10px;
    height: calc(100vh - 20px);
    display: flex; flex-direction: column;
    background: var(--surface);
    border: 0.5px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    box-shadow: 0 4px 18px rgba(0,0,0,.07);
  }
  .xb-mdpane-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 8px 12px; font-size: 13px; font-weight: 600;
    border-bottom: 0.5px solid var(--border);
  }
  .xb-mdpane-x { cursor: pointer; color: var(--muted); font-size: 17px; }
  .xb-mdpane-x:hover { color: var(--ink); }
  .xb-mdframe { flex: 1 1 auto; width: 100%; border: 0; background: var(--bg); }
}
/* 内嵌模式（iframe 里的评审页自身）：藏返回/跳款按钮（这两个操作在父页语境里无意义），
   顶栏留标题 + 上一个/下一个切款条照常可用。embed 只会出现在桌面 iframe 里，手机不涉及。 */
.xb-embed .xb-topbar-action { display: none; }
.xb-embed .xb-topbar { min-height: 36px; }

/* 款式库 · 工具条（电商式下拉筛选 + 列数切换） */
.xb-toolbar {
  display: flex; align-items: center; gap: 8px;
  background: var(--bg); border-bottom: 0.5px solid var(--border);
}
.xb-dd { flex: 1; min-width: 0; }
.xb-dd .van-dropdown-menu__bar { background: transparent; box-shadow: none; }
.xb-filter-note {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 6px 14px; font-size: 12px; color: var(--muted);
  background: var(--bg); border-bottom: 0.5px solid var(--border);
}

/* 批量上传 · 生成预览（2026-10-05） */
.xb-bpreview { margin: 10px 16px; padding: 10px 11px; background: var(--surface);
  border: 0.5px solid var(--border); border-radius: var(--radius); }
.xb-bpreview-t { font-size: 12px; color: var(--muted); margin-bottom: 8px; }
.xb-bp-list { display: flex; flex-wrap: wrap; gap: 8px; }
.xb-bp-item { position: relative; width: 72px; }
.xb-bp-img { width: 72px; height: 88px; object-fit: cover; border-radius: 6px;
  border: 0.5px solid var(--border); background: var(--bg); }
.xb-bp-n { font-size: 11px; color: var(--text); text-align: center; margin-top: 3px; }
.xb-bp-item .xb-chip-x { position: absolute; top: -6px; right: -6px; }

/* 批量上传 · 失败可见 / 汇总 / 重试（2026-10-07 V4.14）
   背景：用户反馈"大批量掉图却不知道掉了哪张" —— 原先失败项和成功项长得一模一样
   （缩略图用的是本地预览图，永远在），错误提示也只看得到第一条。 */
.xb-bp-bar { display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px; margin-bottom: 8px; font-size: 12px; color: var(--text); }
.xb-bp-sum { line-height: 1.5; }
.xb-bp-acts { display: flex; gap: 10px; flex-shrink: 0; }
.xb-bp-a { color: var(--accent); font-size: 12px; text-decoration: underline; }
.xb-bad { color: var(--err); font-weight: 500; }
.xb-ok { color: var(--pass); font-weight: 500; }
/* 失败：红框 + 压暗；上传中：淡出；已建：绿框 */
.xb-bp-st-fail .xb-bp-img { outline: 2px solid var(--err); outline-offset: -1px; opacity: .5; }
.xb-bp-st-fail .xb-bp-n { color: var(--err); }
.xb-bp-st-busy .xb-bp-img { opacity: .55; }
.xb-bp-st-created .xb-bp-img { outline: 2px solid var(--pass); outline-offset: -1px; }
.xb-bp-badge { position: absolute; left: -4px; top: -4px; z-index: 2;
  font-size: 10px; line-height: 1; padding: 3px 4px; border-radius: 4px;
  background: var(--muted); color: #fff; white-space: nowrap; }
.xb-bp-st-fail .xb-bp-badge { background: var(--err); }
.xb-bp-st-created .xb-bp-badge { background: var(--pass); }
.xb-bp-retry { display: block; text-align: center; margin-top: 2px;
  font-size: 11px; color: var(--accent); text-decoration: underline; }
/* 建款结果面板 */
.xb-bres { margin: 10px 16px; padding: 11px; background: var(--surface);
  border: 0.5px solid var(--err); border-radius: var(--radius); }
.xb-bres-t { font-size: 13px; color: var(--text); margin-bottom: 8px; }
.xb-bres-row { display: flex; gap: 9px; align-items: flex-start; padding: 7px 0;
  border-top: 0.5px solid var(--border); }
.xb-bres-img { width: 40px; height: 48px; object-fit: cover; border-radius: 5px;
  border: 0.5px solid var(--border); flex-shrink: 0; }
.xb-bres-x { min-width: 0; }
.xb-bres-n { font-size: 12.5px; color: var(--text); word-break: break-all; }
.xb-bres-r { font-size: 12px; color: var(--err); margin-top: 2px; line-height: 1.5; }
.xb-bres-acts { margin-top: 10px; }

/* 供应商提示：说明为什么款式库里的款比管理员看到的少 */
.xb-supplier-tip {
  margin: 8px 16px 2px; padding: 8px 11px; font-size: 12.5px; color: var(--muted);
  background: var(--surface-2); border: 0.5px solid var(--border);
  border-radius: var(--radius); line-height: 1.6;
}
.xb-supplier-tip strong { color: var(--accent); }

/* ===== 数据管理页 #/admin（管理员） ===== */
/* 在用/已归档切换条：自己实现而不用 van-segmented——
   实测 vant3 Segmented 放在 van-tabs 里点击不响应（会导致无法恢复款式），自绘更可靠。 */
.xb-seg { display: flex; gap: 6px; padding: 10px 16px 0; }
.xb-seg button {
  flex: 1; padding: 7px 0; cursor: pointer; font-size: 13px;
  border: 0.5px solid var(--border); border-radius: 8px;
  background: var(--surface); color: var(--muted);
}
.xb-seg button.on {
  background: var(--accent); border-color: var(--accent);
  color: #fff; font-weight: 500;
}
.xb-admin-row {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 16px; background: var(--surface);
  border-bottom: 0.5px solid var(--border);
}
/* 款式缩略图（2026-10-06 用户反馈「一堆编号看不出是哪些款，很难点」）。
   60×60 固定框 + object-fit:cover：竖图也只裁一点，不让行高被撑开。 */
.xb-admin-thumb {
  flex: none; width: 60px; height: 60px; border-radius: 8px;
  overflow: hidden; background: var(--surface-2);
  display: flex; align-items: center; justify-content: center;
}
.xb-admin-thumb img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  cursor: zoom-in;   /* 点一下看原图 */
}
.xb-admin-thumb-ph { font-size: 11px; color: var(--muted); }
.xb-admin-main { flex: 1; min-width: 0; }
.xb-admin-t { font-size: 14px; color: var(--text); }
.xb-admin-code { color: var(--muted); font-size: 12px; margin-left: 4px; }
.xb-admin-s { font-size: 12px; color: var(--muted); margin-top: 3px; }
.xb-admin-empty { padding: 28px 16px; text-align: center; color: var(--muted); font-size: 13px; }
.xb-admin-tip {
  margin: 10px 16px; padding: 9px 11px; font-size: 12px; line-height: 1.6;
  color: var(--muted); background: var(--surface-2);
  border: 0.5px solid var(--border); border-radius: var(--radius);
}
.xb-admin-tip b { color: var(--text); }
/* 已归档款式在批次里灰显。
   ⚠️ 2026-10-07 V4.17 起：归档款在批次里**已经彻底不返回**（见 routers.SQL_NOT_ARCHIVED），
   正常路径下不会再有元素带这个类。绑定与样式**防御性保留**：万一将来某个接口
   （例如按 item 直开评审页）仍返回归档款，卡片至少能肉眼区分出来。 */
.xb-gcard-archived { opacity: .55; }

/* 「选择型」字段的显示值：用 van-cell + span 渲染。
   ⚠️ 不用 van-field 的 readonly + value 绑定——Vant3 在 readonly 下外部 value 变化**不回显**
     （真机复现：数据已设上但输入框仍为空），2026-10-04 已改此处。 */

/* 款式库 · 筛选条（状态/品类/季节/标签/批次） */
.xb-chipbtn {
  flex: none; white-space: nowrap; cursor: pointer;
  border: 0.5px solid var(--border); background: var(--surface);
  color: var(--text); border-radius: 999px; padding: 5px 11px; font-size: 13px;
}
.xb-chipbtn-clear { color: var(--muted); }

/* 上款批次卡片 · 统计行 */
.xb-scard-stats {
  display: flex; gap: 14px; margin-top: 6px;
  color: var(--muted); font-size: 12px;
}
.xb-sstat b { color: var(--text); font-size: 14px; margin-right: 2px; }
.xb-sstat-sel b { color: var(--pass); }
.xb-sstat-rej b { color: var(--reject); }
.xb-pickv { color: var(--text); }
.xb-pickv-empty { color: var(--muted); }
.xb-pickv-req { color: var(--accent); }   /* 必选项未选时的提示 */

/* ===== 特色标签（chip）与「可选+新建」相关（2026-10-04 用户反馈新增） ===== */
.xb-tagbox { width: 100%; }
.xb-tags { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.xb-chip {
  display: inline-flex; align-items: center;
  background: var(--surface-2); color: var(--text);
  border: 0.5px solid var(--border); border-radius: 999px;
  padding: 3px 9px; font-size: 12px; line-height: 1.5;
}
.xb-chip-static { margin: 0 6px 6px 0; }
.xb-chip-x {
  font-style: normal; margin-left: 5px; cursor: pointer;
  color: var(--muted); font-size: 13px;
}
.xb-chip-x:hover { color: var(--accent); }
.xb-taginput {
  flex: 1; min-width: 90px; border: none; outline: none;
  background: transparent; font-size: 14px; padding: 3px 0;
}
.xb-count { text-align: right; color: var(--muted); font-size: 11px; margin-top: 4px; }
.xb-hottags {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  padding: 8px 16px 10px; background: var(--bg);
}
.xb-hottags-l { color: var(--muted); font-size: 12px; }
.xb-hot {
  background: var(--surface); border: 0.5px solid var(--border);
  border-radius: 999px; padding: 3px 9px; font-size: 12px; cursor: pointer;
}
.xb-hot:active { background: var(--surface-2); }
/* 详情页标签区 */
.xb-gtags { padding: 4px 16px 12px; }
.xb-gtags-l { color: var(--muted); font-size: 12px; margin-bottom: 6px; }
/* 首页卡片上的小标签 */
.xb-gcard-tags { margin-top: 5px; display: flex; flex-wrap: wrap; gap: 4px; }
.xb-tagmini {
  background: var(--surface-2); color: var(--muted);
  border-radius: 4px; padding: 1px 5px; font-size: 11px;
}
/* 建会·参与人选择 */
.xb-members-l {
  padding: 12px 16px 4px; font-size: 13px; color: var(--text);
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px;
}
.xb-mem-hint { color: var(--muted); font-size: 11px; }
.xb-mem-cnt { color: var(--accent); font-size: 12px; }
.xb-members {
  max-height: 34vh; overflow: auto; margin: 0 16px;
  background: var(--surface); border: 0.5px solid var(--border);
  border-radius: var(--radius); padding: 8px 10px;
}
.xb-members .van-checkbox { margin-bottom: 8px; }
.xb-mem-role { color: var(--muted); font-size: 11px; margin-left: 5px; }

/* 🚨 iOS Safari / 微信：输入框字号 <16px 会触发自动放大且不缩回，
   放大后 position:fixed 顶栏被推出屏幕 → 按钮点不到（2026-10-04 适配核查补）。
   Vant3 单元格输入框默认 14px，这里统一兜到 16px。 */
input, textarea, select, .van-field__control, .van-search__content {
  font-size: 16px !important;
}

/* 真正打印时放行全宽（A4 比 560px 宽，不放行会打印不全/缩成一团） */
@media print {
  #app { max-width: none; margin: 0; box-shadow: none; }
}

/* 打印时只保留清单本体 */
@media print {
  .no-print { display: none !important; }
  .xb-print-bar, .xb-print-hint { display: none !important; }
  .xb-print-doc { padding: 0; max-width: 100%; }
  body { background: #fff; }
  /* 2026-10-13 二轮审查：补 print-color-adjust: exact。
     Chrome/Edge 默认**不打印背景图形**，于是 .xb-print-table thead th 的灰底
     （#f3efe9）在打印/存 PDF 时整块丢失，表头只剩文字、和下面的数据行分不开。
     文字颜色不受影响（状态色照旧），但底色要显式声明才印得出来。 */
  body { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .xb-print-table thead th { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* ================= 日期筛选（2026-10-06 用户要求）================= */
/* 入口已并入筛选栏（作为第 6 个下拉项），这里只剩日历卡片本身的样式 */

/* 日历卡片：白色圆角卡片，浮在筛选栏下方 */
.xb-datecard {
  margin: 0 16px 10px; padding: 10px 10px 8px;
  background: var(--surface); border: 0.5px solid var(--border);
  border-radius: 12px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
}
/* 维度切换（上传日期 / 定稿日期） */
.xb-dc-tabs { display: flex; gap: 6px; margin-bottom: 4px; }
.xb-dc-tab {
  flex: 1; height: 30px; cursor: pointer; font-size: 13px;
  background: var(--bg); color: var(--muted);
  border: 0.5px solid var(--border); border-radius: 8px;
}
.xb-dc-tab.on { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 500; }

/* 自绘日历（不用 Vant Calendar —— 该 UMD 包里没有该组件） */
.xb-cal { margin-top: 2px; }
.xb-cal-head { display: flex; align-items: center; justify-content: space-between; padding: 2px 0 6px; }
.xb-cal-title { font-size: 14px; font-weight: 600; }
.xb-cal-nav {
  width: 30px; height: 30px; cursor: pointer; font-size: 18px; line-height: 1;
  color: var(--text); background: var(--bg);
  border: 0.5px solid var(--border); border-radius: 8px;
}
.xb-cal-nav:disabled { opacity: 0.3; cursor: not-allowed; }
.xb-cal-week {
  display: grid; grid-template-columns: repeat(7, 1fr);
  font-size: 11px; color: var(--muted); text-align: center; padding-bottom: 2px;
}
.xb-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.xb-cal-cell {
  position: relative; height: 34px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; color: var(--text); border-radius: 8px;
}
/* 区间中间：淡红底 + 圆角只留左右，像"一整条被选中" */
.xb-cal-cell.in { background: rgba(188, 107, 74, 0.14); border-radius: 0; }
.xb-cal-cell.in + .xb-cal-cell.in { border-radius: 0 8px 8px 0; }
.xb-cal-cell.in:not(.start):not(.end) { border-radius: 0; }
.xb-cal-cell.start, .xb-cal-cell.end { background: var(--accent); color: #fff; font-weight: 600; }
.xb-cal-cell.start { border-radius: 8px 0 0 8px; }
.xb-cal-cell.end { border-radius: 0 8px 8px 0; }
/* 单选的一天（还没点第二个）：整格高亮 */
.xb-cal-cell.start:not(.in), .xb-cal-cell.end:not(.in) { border-radius: 8px; }
.xb-cal-cell.dim { color: var(--muted); opacity: 0.4; }
.xb-cal-cell.off { opacity: 0.22; cursor: not-allowed; }

/* 快捷范围 + 提示 */
.xb-dc-quick { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
.xb-dc-quick .xb-chipbtn { padding: 4px 10px; font-size: 12px; }
.xb-dc-hint { margin-top: 6px; font-size: 11px; color: var(--muted); text-align: center; }
.xb-dc-hint.off { opacity: 0.75; }
/* 2026-10-06 用户要求：底部用「清除 / 确认」两个按钮收尾，不再是"点满两天就自动关"。
   「确认」实心主色、「清除」描边，两者等宽，右对齐。 */
.xb-dc-actions { display: flex; gap: 8px; margin-top: 10px; padding-top: 8px;
  border-top: 0.5px solid var(--border); }
.xb-dc-btn {
  flex: 1; height: 34px; cursor: pointer; font-size: 14px; line-height: 1;
  border-radius: 8px; font-family: inherit;
}
.xb-dc-btn.primary { background: var(--accent); border: 1px solid var(--accent); color: #fff; font-weight: 500; }
.xb-dc-btn.ghost { background: var(--surface); border: 0.5px solid var(--border); color: var(--muted); }
.xb-dc-btn:active { opacity: 0.7; }

/* 「日期」并入筛选栏的按钮（2026-10-06 用户要求）。
   做成独立按钮而不是 van-dropdown-item：实测该 UMD 里 DropdownItem 作为 DropdownMenu
   子组件没被正确实例化（6 项全部 w=0/h=0/opts=0，点击无反应）。
   这里直接复用 Vant 的 .van-dropdown-menu__title 视觉规范，两边看起来是一套的。 */
.xb-dditem {
  flex: 0 1 auto; display: inline-flex; align-items: center; gap: 2px;
  height: 48px; padding: 0 4px; cursor: pointer; align-self: stretch;
  color: var(--text); font-size: 13px;
}
/* 2026-10-06：筛选项被选中后标题会变长（「上传 10/01-10/05」），这里允许收缩 + 省略号，
   防止把筛选栏顶破、或与右侧图标叠在一起（用户曾截图反馈"日期ⓘ"挤成一团）。 */
.xb-dditem-t { line-height: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.xb-dditem .ico-cal { flex: none; }
/* 与 Vant 的 dropdown-menu__title 视觉对齐：那个是 flex 撑满 48px 并居中，
   这里用 align-self:stretch + 自身 flex 居中，文字基线才在同一水平线上。 */
.xb-dditem.on, .xb-dditem.has { color: var(--accent); }
/* 2026-10-13 二轮审查：这里原先还有一条完全重复的 `.xb-dditem-t { line-height: 1; }`
   （上面那条已包含 line-height:1 及其它属性），同特异性、纯冗余，删。 */
/* 小日历图标（跟「布局」按钮那种纯图标思路一致） */
.xb-dditem .ico-cal {
  width: 12px; height: 12px; flex: none; display: inline-block;
  border: 1.3px solid currentColor; border-radius: 3px; position: relative;
}
.xb-dditem .ico-cal::before,
.xb-dditem .ico-cal::after {
  content: ""; position: absolute; top: -1.3px; width: 1.3px; height: 3.5px;
  background: currentColor;
}
.xb-dditem .ico-cal::before { left: 2.6px; }
.xb-dditem .ico-cal::after { left: 6.4px; }

/* ================= 使用教程 #/guide（2026-10-06 V4.11 新增）=================
   面向第一次登录的人：只讲「你是谁 → 你该点哪里」，不讲术语、不讲实现。
   配图 = AI 扁平插画（/assets/img/guide/*.jpg，童装主题、无人物、无文字，
   jpg 共约 75KB）；仅 boss4 勾选示意与 tip 小图标保留内联 SVG。 */
.xb-guide { padding-bottom: 0; }

/* 顶部：返回箭头 + 标题 + 第几屏 */
.gd-stepnum { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* 进度点：已看过的和当前都点亮 */
.gd-dots { display: flex; gap: 5px; justify-content: center; padding: 10px 0 2px; }
.gd-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--border); transition: background .2s; }
.gd-dot.on { background: var(--accent); }

/* 每屏内容区 */
.gd-page { padding: 14px 16px 8px; }
.gd-h { font-family: Georgia, "Songti SC", "SimSun", serif; font-weight: 500; font-size: 20px; margin: 4px 0 10px; }
.gd-p { color: var(--muted); font-size: 14px; margin: 0 0 12px; }
.gd-p b { color: var(--text); }

/* 示意图容器。插画自带奶油底色与留白，容器只收紧内边距 + 让图片圆角填满 */
.gd-figwrap { background: var(--surface); border: 0.5px solid var(--border); border-radius: var(--radius); padding: 6px; margin: 0 0 14px; }
.gd-fig { display: block; width: 100%; height: auto; color: var(--text); }
.gd-cover { display: block; width: 100%; height: auto; border-radius: calc(var(--radius) - 3px); }
.gd-img { display: block; width: 100%; height: auto; border-radius: 8px; }

/* 第 1 屏：四个词 */
.gd-words { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 14px; }
.gd-word {
  background: var(--surface); border: 0.5px solid var(--border); border-radius: 10px;
  padding: 10px 12px; display: flex; flex-direction: column; gap: 2px;
}
.gd-word b { font-size: 15px; font-weight: 600; }
.gd-word span { font-size: 12px; color: var(--muted); line-height: 1.45; }

/* 强调框（第 1 屏那句口诀 / 第 3 屏末尾）。
   ⚠️ 这里刻意用固定 rgba 而不是 color-mix()：老微信 X5 内核不支持 color-mix，
   会整条规则失效 → 底色变透明、框里的字浮在背景上（与 V4.4 的 inset 同类教训）。 */
.gd-key {
  background: rgba(245, 180, 41, 0.13);
  border-left: 3px solid var(--sample-solid);
  border-radius: 8px; padding: 11px 13px;
  font-size: 13px; line-height: 1.6; color: var(--text);
}
.gd-key b { font-weight: 600; }

/* 第 2 屏：步骤条（左图右文）。图 88px —— 早先 76px 实测在手机上细节看不清
   （星星、勾都糊成一团），这里放大一档；文字列仍留足宽度。 */
.gd-step { display: flex; gap: 11px; align-items: flex-start; margin-bottom: 10px; background: var(--surface); border: 0.5px solid var(--border); border-radius: 10px; padding: 10px 12px 10px 8px; }
.gd-figbox { flex: none; width: 88px; }
.gd-figbox .gd-fig { width: 88px; }
.gd-figbox .gd-img { width: 88px; }
.gd-stepmain { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 3px; }
.gd-stepmain b { font-size: 14px; font-weight: 600; line-height: 1.45; }
.gd-stepmain span { font-size: 12.5px; color: var(--muted); line-height: 1.55; }
.gd-stepmain span b { color: var(--text); }

/* 第 3 屏：提醒条目 */
.gd-tip { display: flex; gap: 11px; align-items: flex-start; margin-bottom: 10px; background: var(--surface); border: 0.5px solid var(--border); border-radius: 10px; padding: 12px; }
.gd-icobox { flex: none; width: 38px; }
.gd-ico { display: block; width: 38px; height: 38px; color: var(--accent); }
.gd-tipmain { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 3px; }
.gd-tipmain > b { font-size: 14px; font-weight: 600; }
.gd-tipmain span { font-size: 12.5px; color: var(--muted); line-height: 1.6; }
.gd-tipmain span b { color: var(--text); font-weight: 600; }

/* 底部按钮 */
.gd-foot { padding: 10px 16px calc(16px + env(safe-area-inset-bottom)); display: flex; gap: 10px; }
.gd-foot .van-button { flex: 1; }

/* ---------- V4.23 登录/注册防护（图形验证码 + 蜜罐） ---------- */
/* 蜜罐：正常用户看不见、Tab 也聚焦不到；机器人常把表单所有字段填满 → 被后端直接拒。
   ⚠️ 用「离屏定位」而不是 display:none —— 部分爬虫会主动跳过 display:none 的字段。 */
.xb-hp {
  position: absolute;
  left: -9999px;
  top: 0;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.xb-cap-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px 0;
}

.xb-cap-img {
  height: 40px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--surface);
  cursor: pointer;
}

.xb-cap-hint { font-size: 13px; color: var(--muted); }

.xb-cap-refresh { font-size: 13px; color: var(--accent); cursor: pointer; }

/* ---------- V4.24 AI 识别进度条（款式库顶部，pending 归零自动隐藏） ---------- */
.xb-aiprog {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 8px 16px 0;
  padding: 8px 12px;
  border-radius: 10px;
  background: var(--surface);
  border: 0.5px solid var(--border);
  font-size: 13px;
  color: var(--muted);
}

.xb-aiprog b { color: var(--accent); font-weight: 600; }

/* ---------- V4.26 数据管理：勾选栏 + 分页条 ----------
   为什么自定义分页而不用 <van-pagination>：本项目的 Vant 是免构建 UMD 包，
   部分子组件未被正确实例化（V4.16 的 DropdownItem 就踩过），
   自定义按钮行为可控、也更容易写回归断言。 */
.xb-selbar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 16px;
  background: var(--surface);
  border-bottom: 0.5px solid var(--border);
  font-size: 13px;
}
.xb-selbar .xb-selall { flex: none; }
.xb-selcount { flex: 1; color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }

/* 每行左侧的勾选框（不参与点击缩略图/按钮） */
.xb-row-ck { flex: none; }

.xb-pgbar {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 16px 18px;
}
/* 分页内部的两行：第一行页信息 + 每页档位；第二行翻页按钮（右对齐） */
.xb-pgbar-line { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.xb-pgbar-right { justify-content: flex-end; }
.xb-pgbar-btn {
  min-width: 76px;
  padding: 7px 12px;
  border-radius: 8px;
  border: 0.5px solid var(--border);
  background: var(--surface);
  color: var(--accent);
  font-size: 13px;
}
.xb-pgbar-btn:disabled { color: var(--muted); opacity: 0.5; }
.xb-pgbar-info {
  color: var(--muted);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
/* 2026-10-13：`.xb-pgsize` 容器规则已删 —— 全仓模板里只有 `xb-pgsize-l` 在使用
   （admin.js:119，分页条左侧的"共 N 款"文字），容器那条是孤儿规则。 */
.xb-pgsize-l { color: var(--muted); font-size: 12px; }

/* ---------- V4.27 款式库：滚动加载状态行 ---------- */
.xb-loadmore {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 18px 16px 26px;
  color: var(--muted);
  font-size: 13px;
}

/* V4.38.7 批次页渐进渲染的手动兜底按钮（自动加载没触发时自己点） */
.xb-loadmore-btn.van-button {
  padding: 0 12px;
  height: 28px;
  line-height: 26px;
  font-size: 12px;
  color: var(--accent);
  border-color: var(--accent);
  background: transparent;
}

/* ---------- V4.27 数据管理：列表工具条（筛选 + 勾选合并成一行） ---------- */
.xb-listbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  padding: 8px 16px;
  background: var(--surface);
  border-top: 0.5px solid var(--border);
  border-bottom: 0.5px solid var(--border);
}
/* 工具条里的下拉与日期按钮：沿用首页 .xb-dd / .xb-dditem 的观感，但收窄一点 */
.xb-listbar .xb-dd { flex: none; }
.xb-listbar .xb-dditem { flex: none; }
.xb-listbar .xb-selcount { flex: 1 1 auto; }
.xb-listbar .xb-selall { flex: none; }
/* 工具条右侧的批量按钮 */
.xb-listbar-batch { flex: none; margin-left: auto; }
.xb-listbar-sep { width: 0.5px; height: 18px; background: var(--border); flex: none; }

/* AI 与清理设置（默认收起，放在列表下方） */
.xb-ai-fold {
  margin: 14px 16px 0;
  border: 0.5px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  overflow: hidden;
}
.xb-ai-fold-h {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 11px 14px;
  font-size: 13px;
  color: var(--text);
}
.xb-ai-fold-h .xb-ai-fold-caret { margin-left: auto; color: var(--muted); font-size: 12px; }
.xb-ai-fold-b { padding: 0 14px 12px; }
/* 折叠区里去掉原来的外边距，避免嵌套后过空 */
.xb-ai-fold-b .xb-ai-note-box { margin: 0; padding: 0; background: transparent; }

/* ============ V4.30 同款查重 ============ */
/* 2026-10-13：`.xb-dupcard` 及其子元素规则已删 —— V4.30 初版残留，
   全仓模板/JS 里找不到任何使用该 class 的元素（现在的疑似重复提示走 .xb-dup-warn / .xb-bp-dup）。 */
.xb-dup-thumb { width: 48px; height: 48px; border-radius: 8px; object-fit: cover; flex: 0 0 auto; background: var(--surface); }
.xb-dup-row { display: flex; align-items: center; gap: 12px; padding: 8px 0; }
.xb-dup-meta { flex: 1 1 auto; min-width: 0; }
.xb-dup-name { font-size: 14px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.xb-dup-h { display: inline-block; margin-top: 4px; font-size: 12px; color: #fff; background: var(--warning, #ed6a0c);
  padding: 1px 7px; border-radius: 8px; }
/* 批量预览格：重复嫌疑角标（橙色，复用原有角标定位） */
.xb-bp-item.xb-bp-dup .xb-bp-badge { background: var(--warning, #ed6a0c); }
/* 上传页查重提示卡 + 详情弹层（V4.30 新增，upload.js 用） */
.xb-dup-warn { display: flex; align-items: center; gap: 6px; margin: 8px 16px 0;
  padding: 9px 12px; border-radius: 10px; background: var(--warning-bg, #fff7e6);
  border: 0.5px solid var(--warning, #ed6a0c); color: var(--text); cursor: pointer; }
.xb-dup-warn-ico { color: var(--warning, #ed6a0c); flex: 0 0 auto; }
.xb-dup-warn-txt { flex: 1 1 auto; font-size: 13px; line-height: 1.4; }
.xb-dup-warn-go { color: var(--warning, #ed6a0c); flex: 0 0 auto; font-size: 13px; }
.xb-dup-warn-loading { cursor: default; }
.xb-dup-sheet { padding: 16px 16px calc(16px + env(safe-area-inset-bottom)); max-height: 70vh; overflow-y: auto; }
.xb-dup-sheet-t { font-size: 15px; font-weight: 600; color: var(--text); margin-bottom: 8px; }
.xb-dup-sheet-body { border-top: 0.5px solid var(--border); }

/* ===== V4.30 疑似重复 ===== */
/* 首页 banner */
.xb-dupbanner { display: flex; align-items: center; gap: 6px; margin: 8px 12px 0;
  padding: 9px 12px; border-radius: 10px; background: var(--warning-bg, #fff7e6);
  border: 0.5px solid var(--warning, #ed6a0c); color: var(--text); cursor: pointer; }
.xb-dupbanner-ico { color: var(--warning, #ed6a0c); flex: 0 0 auto; }
.xb-dupbanner-txt { flex: 1 1 auto; font-size: 13px; line-height: 1.4; }
.xb-dupbanner-txt b { color: var(--warning, #ed6a0c); }
.xb-dupbanner-go { color: var(--warning, #ed6a0c); flex: 0 0 auto; }
.xb-dupbanner-x { color: var(--muted); flex: 0 0 auto; }

/* 网格 / 详情 角标（橙色，与状态角标区分） */
.xb-dup-badge { background: var(--warning, #ed6a0c) !important; color: #fff !important;
  border-radius: 4px; padding: 1px 6px; font-size: 11px; line-height: 1.5; }

/* 我的页红点 */
.xb-reddot { display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  background: #ee0a24; margin-right: 6px; vertical-align: middle; }

/* 详情页疑似重复提示条 + 操作 */
.xb-dup-rel { font-size: 12px; color: var(--muted); margin-left: 6px; }
.xb-dup-rel b { color: var(--warning, #ed6a0c); }
.xb-dup-ops { display: flex; gap: 10px; padding: 6px 0 10px; }
.xb-dup-btn { font-size: 12px; border: 0.5px solid var(--warning, #ed6a0c); color: var(--warning, #ed6a0c);
  background: transparent; border-radius: 6px; padding: 5px 12px; }
.xb-dup-btn-ghost { border-color: var(--border); color: var(--muted); }

/* similar 清单页 */
.xb-sim-note { padding: 10px 16px; font-size: 12px; color: var(--muted);
  background: var(--warning-bg, #fff7e6); line-height: 1.5; }
.xb-simcard { margin: 10px 12px; background: var(--surface, #fff); border: 0.5px solid var(--border);
  border-radius: 12px; padding: 12px; }
.xb-sim-imgwrap { display: flex; align-items: center; gap: 8px; }
.xb-sim-img { width: 64px; height: 84px; object-fit: cover; border-radius: 8px;
  background: var(--surface, #fff); flex: 0 0 auto; }
.xb-sim-arrow { color: var(--warning, #ed6a0c); font-size: 18px; flex: 0 0 auto; }
.xb-sim-info { margin-top: 8px; }
.xb-sim-line { display: flex; align-items: baseline; gap: 8px; }
.xb-sim-code { font-weight: 600; font-size: 14px; }
.xb-sim-name { color: var(--muted); font-size: 13px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; flex: 1 1 auto; }
.xb-sim-match { margin-top: 4px; font-size: 13px; }
.xb-sim-match b { color: var(--warning, #ed6a0c); }
.xb-sim-score { color: var(--warning, #ed6a0c); margin-left: 6px; font-weight: 600; }
.xb-sim-ops { display: flex; gap: 10px; margin-top: 10px; justify-content: flex-end; }
/* ---- V4.31 疑似重复：批量工具条 / 勾选框 / 分页 / 大图预览 ---- */
.xb-sim-bar { display: flex; align-items: center; gap: 10px; margin: 10px 12px 0;
  padding: 10px 12px; background: var(--surface, #fff); border: 0.5px solid var(--border);
  border-radius: 12px; }
.xb-sim-cball { display: inline-flex; align-items: center; gap: 6px; flex: 1 1 auto; }
.xb-sim-cbtxt { font-size: 14px; }
.xb-sim-sel { color: var(--muted); font-size: 13px; }
.xb-sim-cb { display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 4px; border: 1px solid var(--border, #ddd);
  background: var(--surface, #fff); color: #fff; font-size: 13px; line-height: 1; }
.xb-sim-cb.on { background: var(--primary, #1989fa); border-color: var(--primary, #1989fa); }
.xb-sim-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.xb-sim-sid { color: var(--muted); font-size: 12px; }
.xb-sim-page { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: 12px; padding: 10px 12px; background: var(--surface, #fff);
  border: 0.5px solid var(--border); border-radius: 12px; }
.xb-pg-btn, .xb-pg-size { min-width: 56px; padding: 6px 10px; font-size: 13px;
  border-radius: 8px; border: 1px solid var(--border, #ddd); background: var(--surface, #fff);
  color: var(--text, #333); }
.xb-pg-btn:disabled { opacity: 0.45; }
.xb-pg-size { min-width: 44px; }
.xb-pg-size.on { background: var(--primary, #1989fa); color: #fff; border-color: var(--primary, #1989fa); }
.xb-pg-info { flex: 1 1 auto; font-size: 13px; color: var(--muted); }
.xb-pg-sizes { display: flex; gap: 6px; }
.xb-sim-preview { position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 2100;
  background: rgba(0, 0, 0, 0.92); display: flex; align-items: center;
  justify-content: center; cursor: zoom-out; }
.xb-sim-preview-img { max-width: 96vw; max-height: 88vh; object-fit: contain;
  -webkit-user-drag: none; user-select: none; }
.xb-sim-preview-tip { position: fixed; bottom: 24px; left: 0; right: 0; text-align: center;
  color: rgba(255, 255, 255, 0.75); font-size: 13px; pointer-events: none; }
