/* ==========================================================================
   MIRA 形象顾问后台 — HUD 设计系统
   借鉴 3D 太阳系项目的「canvas 铺底 + 悬浮玻璃面板」布局范式，
   但配色换成服装行业的高定质感：深炭黑 + 香槟金 + 冷白。

   本文件只服务 admin.html。客户问卷(index.html)与报告(report.html)继续用
   style.css，两套令牌互不干扰。

   主题切换：<html data-theme="dark|light">，深色为默认。
   ========================================================================== */

/* ============================== 主题令牌 ============================== */
:root,
[data-theme="dark"] {
  /* 底色：深炭黑（不用纯黑，避免死板），叠一层极淡的暖光营造高定橱窗氛围 */
  --bg: #14110F;
  --bg-grad-1: rgba(198, 162, 106, 0.07);
  --bg-grad-2: rgba(120, 96, 68, 0.06);
  --bg-grad-3: rgba(40, 34, 28, 0.5);

  /* 玻璃面板 */
  --panel-bg: rgba(30, 26, 23, 0.72);
  --panel-bg-solid: #1E1A17;
  --panel-border: rgba(198, 162, 106, 0.20);
  --panel-border-strong: rgba(198, 162, 106, 0.42);

  /* 文字 */
  --text: #E8E2D8;
  --text-strong: #F7F2E9;
  --muted: #A09383;
  --muted-dim: #6E6355;

  /* 香槟金主强调 */
  --accent: #C8A96A;
  --accent-soft: rgba(198, 162, 106, 0.15);
  --accent-glow: rgba(198, 162, 106, 0.32);
  --accent-ink: #14110F;/* 金色按钮上的文字色 */

  /* 语义色（深色底上要提亮） */
  --ok: #7FC9A0;
  --ok-soft: rgba(127, 201, 160, 0.15);
  --warn: #E0A96D;
  --warn-soft: rgba(224, 169, 109, 0.15);
  --danger: #E08A7D;
  --danger-soft: rgba(224, 138, 125, 0.15);
  --info: #8FB8DE;
  --info-soft: rgba(143, 184, 222, 0.15);

  --line: rgba(198, 162, 106, 0.18);
  --line-soft: rgba(198, 162, 106, 0.10);
  --hover: rgba(198, 162, 106, 0.08);

  --shadow: 0 18px 48px rgba(0, 0, 0, 0.55), 0 1px 0 rgba(255, 255, 255, 0.05) inset;
  --shadow-sm: 0 6px 20px rgba(0, 0, 0, 0.38);
  --backdrop: blur(16px) saturate(1.25);

  /* 三维地图画布底色（门店分布图·中国视角）。
     ⚠️ store-map3d.js 里 WebGL 的 clearColor 与雾色用的是同一套十六进制值
        （PALETTES.dark.bg），两边必须保持一致：
        不一致的话首帧会闪一下不同色，远端边缘还会出现一圈「脏边」。 */
  --map3d-bg: #0E1113;
  --map3d-bub: rgba(16, 21, 23, 0.90);
  --map3d-bub-hover: rgba(24, 31, 33, 0.96);
  --map3d-bub-on: rgba(38, 30, 14, 0.95);

  /* 布局尺度 */
  --radius: 14px;
  --radius-sm: 10px;
  --pad: 12px;/* 四周留白，悬浮窗的「浮」感来源 */
  --top-h: 58px;
  --left-w: 252px;
  --rail-w: 74px;/* 侧栏折叠后的图标轨宽度 */

  --serif: "Optima", "Songti SC", "STSong", "Noto Serif SC", Georgia, serif;
  --sans: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB",
    "Microsoft YaHei", "Segoe UI", Roboto, sans-serif;
  --mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
  color-scheme: dark;
}

[data-theme="light"] {
  /* 浅色：象牙白宣纸 + 淡金，高定画册的质感（不是纯白，减少刺眼） */
  --bg: #F5F1EA;
  --bg-grad-1: rgba(184, 143, 79, 0.10);
  --bg-grad-2: rgba(168, 132, 88, 0.07);
  --bg-grad-3: rgba(255, 255, 255, 0.6);

  --panel-bg: rgba(255, 253, 249, 0.80);
  --panel-bg-solid: #FFFDF9;
  --panel-border: rgba(150, 120, 72, 0.22);
  --panel-border-strong: rgba(150, 120, 72, 0.44);

  --text: #2E2820;
  --text-strong: #1A1610;
  --muted: #6F6455;
  --muted-dim: #9A8F7E;

  --accent: #9A7B36;
  --accent-soft: rgba(154, 123, 54, 0.13);
  --accent-glow: rgba(154, 123, 54, 0.16);
  --accent-ink: #FFFDF9;

  --ok: #3D7A5B;
  --ok-soft: rgba(61, 122, 91, 0.12);
  --warn: #93602F;
  --warn-soft: rgba(147, 96, 47, 0.12);
  --danger: #B4443A;
  --danger-soft: rgba(180, 68, 58, 0.12);
  --info: #3B5C99;
  --info-soft: rgba(59, 92, 153, 0.12);

  --line: rgba(150, 120, 72, 0.20);
  --line-soft: rgba(150, 120, 72, 0.12);
  --hover: rgba(154, 123, 54, 0.07);

  --shadow: 0 14px 40px rgba(90, 70, 40, 0.14), 0 1px 0 rgba(255, 255, 255, 0.6) inset;
  --shadow-sm: 0 5px 18px rgba(90, 70, 40, 0.10);
  --backdrop: blur(14px) saturate(1.15);

  /* 浅色主题下地图画布改成宣纸色（与 PALETTES.light.bg 一致），
     气泡改成半透明象牙白 —— 深底气泡浮在浅色地图上会像一块污渍。 */
  --map3d-bg: #EFEAE1;
  --map3d-bub: rgba(255, 253, 249, 0.92);
  --map3d-bub-hover: rgba(255, 251, 242, 0.98);
  --map3d-bub-on: rgba(250, 240, 214, 0.97);

  color-scheme: light;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; }
html { background: var(--bg); }
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 14.5px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
  /* 主题切换的平滑过渡 */
  transition: background-color .3s ease, color .3s ease;
}
/* 舞台底纹：两团暖光营造纵深，而不是死板的纯色 */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    radial-gradient(1000px 680px at 16% 6%, var(--bg-grad-1), transparent 62%),
    radial-gradient(880px 600px at 88% 94%, var(--bg-grad-2), transparent 60%),
    radial-gradient(700px 500px at 58% 42%, var(--bg-grad-3), transparent 70%);
  transition: opacity .3s ease;
}

a { color: var(--accent); text-decoration: none; }
h1, h2, h3, h4 { font-family: var(--serif); font-weight: 600; letter-spacing: .02em; margin: 0; }
button, input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }

/* 🆕 v1.16.2 W2-3：滚动条减半（8→4px）且颜色更浅 —— 用半透明灰褐，
   浅米底不抢眼、深色模式下也可辨，与底色始终有区分。 */
::-webkit-scrollbar { width: 4px; height: 4px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgba(150, 139, 117, .38); border-radius: 8px; }
::-webkit-scrollbar-thumb:hover { background: rgba(150, 139, 117, .6); }

/* --------------------------------------------------------------------------
   v1.16.59 需求 2：PC 端菜单栏滚动条宽度 = 原来的三分之二（4px → 2.67px）
   --------------------------------------------------------------------------
   🔴 只写 ::-webkit-scrollbar 伪元素，**绝对不要再写 scrollbar-width**：
      Chrome 121+ 一旦读到标准属性就整体忽略伪元素、退回系统约 10px 粗灰条
      （v1.16.58 连着两轮被用户指出「怎么没改」，真因就是这条残留）。
   🔴 媒体查询固定 min-width:861px —— 移动端（<=860px）继续吃上面那条全局
      4px 细线，保持「移动端不变」；展开态与收起态用的是同一个
      .sidebar__nav，因此两态会一起变细，不会出现一粗一细。 */
@media (min-width: 861px) {
  .sidebar__nav::-webkit-scrollbar { width: 2.67px; }
}

.muted { color: var(--muted); }
.tiny { font-size: 12.5px; }
.hr { height: 0; border: 0; border-top: 1px solid var(--line-soft); margin: 16px 0; }
.req { color: var(--accent); font-size: 12px; }
code { font-family: var(--mono); font-size: .92em; background: var(--accent-soft); padding: 1px 5px; border-radius: 5px; color: var(--accent); }

/* ============================== 玻璃面板 ============================== */
.panel {
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  backdrop-filter: var(--backdrop);
  -webkit-backdrop-filter: var(--backdrop);
}
/* 🔴 2026-10-22 需求 4：AI 初诊板块里的「多余圆角边框」。
   .panel 全局**没有内边距**（各视图自己加），所以面板边框会直接贴住
   标题与正文文字，看着像多了一圈框。.panel--plain = 去掉边框 / 圆角 / 阴影，
   只留内容本身（视觉分组交给内部的 .note 承担）。 */
.panel--plain {
  background: transparent; border: 0; border-radius: 0;
  box-shadow: none; backdrop-filter: none; -webkit-backdrop-filter: none;
}
.card {
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  backdrop-filter: var(--backdrop);
  -webkit-backdrop-filter: var(--backdrop);
  padding: 20px;
  transition: background-color .3s ease, border-color .3s ease;
}

/* ============================== 通用组件 ============================== */
.btn {
  appearance: none;
  border: 1px solid var(--panel-border);
  background: var(--panel-bg);
  color: var(--text);
  padding: 9px 17px;
  border-radius: 999px;
  cursor: pointer;
  transition: .18s ease;
  font-size: 14px;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.btn:hover { border-color: var(--accent); color: var(--accent); }
.btn--primary {
  background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 78%, #fff));
  border-color: transparent;
  color: var(--accent-ink);
  font-weight: 600;
}
.btn--primary:hover {
  background: var(--accent);
  color: var(--accent-ink);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.btn--accent { background: var(--accent-soft); border-color: var(--panel-border-strong); color: var(--accent); }
.btn--accent:hover { background: var(--accent); color: var(--accent-ink); }
.btn--ghost { background: transparent; }
.btn--sm { padding: 6px 13px; font-size: 13px; }
.btn--block { width: 100%; justify-content: center; }
.btn[disabled] { opacity: .5; cursor: not-allowed; }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.chiprow, .chip-row { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  border: 1px solid var(--panel-border);
  background: transparent;
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 13.5px;
  cursor: pointer;
  color: var(--muted);
  transition: .15s ease;
  user-select: none;
  line-height: 1.5;
}
.chip:hover { border-color: var(--accent); color: var(--accent); }
.chip.is-on { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 600; }

.input, .textarea {
  width: 100%;
  border: 1px solid var(--panel-border);
  background: color-mix(in srgb, var(--panel-bg-solid) 60%, transparent);
  border-radius: var(--radius-sm);
  padding: 10px 13px;
  outline: none;
  transition: .15s ease;
  color: var(--text);
}
.input::placeholder, .textarea::placeholder { color: var(--muted-dim); }
.input:focus, .textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.textarea { min-height: 92px; resize: vertical; line-height: 1.7; }
select.input { cursor: pointer; }
select.input option { background: var(--panel-bg-solid); color: var(--text); }
.field { margin-bottom: 20px; }
.field__label { font-size: 13.5px; font-weight: 600; margin-bottom: 3px; display: flex; align-items: center; gap: 6px; }
.field__unit { color: var(--muted-dim); font-weight: 400; font-size: 12.5px; }
.field__hint { font-size: 12.5px; color: var(--muted-dim); margin-bottom: 8px; line-height: 1.5; }
.otp-row { display: flex; gap: 8px; }
.otp-row .input { flex: 1; }

.errbox {
  border: 1px solid color-mix(in srgb, var(--danger) 40%, transparent);
  background: var(--danger-soft);
  color: var(--danger);
  border-radius: var(--radius-sm);
  padding: 10px 13px;
  font-size: 13px;
  margin-bottom: 12px;
  line-height: 1.6;
}
.note {
  border-left: 2px solid var(--accent);
  background: var(--accent-soft);
  padding: 12px 14px;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-size: 13.5px;
  line-height: 1.75;
  color: var(--text);
}

/* ============================== 布局骨架 ==============================
   借鉴 3D 太阳系：全部面板绝对定位浮在 stage 上，四边留 --pad 形成悬浮感。
   收起时用 transform 滑出，面板「耳朵」留在屏幕边缘可点。 */
.layout {
  position: relative;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  z-index: 1;
}

/* 中央舞台：将来 3D 骨架 / 试衣画面挂在这里，永远保持完整不被面板切割 */
.stage {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

/* ---- 顶栏 ---- */
.topbar {
  position: absolute;
  top: var(--pad);
  left: var(--pad);
  right: var(--pad);
  height: var(--top-h);
  z-index: 6;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 8px 0 16px;
}
.brand { display: flex; align-items: center; gap: 11px; min-width: 0; }
/* 品牌标记：一枚金色字母章，替代太阳系的方形 logo */
.brand-mark {
  width: 32px; height: 32px; border-radius: 9px; flex: none;
  background: linear-gradient(140deg, var(--accent), color-mix(in srgb, var(--accent) 60%, #000));
  color: var(--accent-ink);
  display: grid; place-items: center;
  font-family: var(--serif); font-size: 15px; font-weight: 700; letter-spacing: .02em;
  box-shadow: 0 0 0 1px var(--panel-border-strong), 0 4px 14px var(--accent-glow);
}
.brand-text { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
.brand-text strong { font-family: var(--serif); font-size: 15px; color: var(--text-strong); letter-spacing: .06em; }
.brand-text small { font-size: 10px; color: var(--muted-dim); font-family: var(--mono); letter-spacing: .12em; text-transform: uppercase; }
/* 中文副标题不能用 mono + 大字距，否则「形象顾问后台」会被拉成稀疏字距 */
.brand-text .brand-text__cn {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: .06em;
  text-transform: none;
  color: var(--muted);
}

.topbar__title {
  font-family: var(--serif);
  font-size: 17px;
  font-weight: 600;
  color: var(--text-strong);
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding-left: 14px;
  border-left: 1px solid var(--line);
}
.topbar__spacer { flex: 1 1 auto; min-width: 8px; }

/* 顶栏门店切换器样式已移至文件末尾：改为自绘下拉面板（#store-menu），
   原生 select 只作无障碍回退。旧方案留在这里会与新块打架，故删除。 */

.topbar__actions { display: flex; gap: 8px; flex-wrap: nowrap; flex: 0 0 auto; align-items: center; }
.topbar__menu {
  display: none;
  width: 36px; height: 36px;
  border: 1px solid var(--panel-border);
  border-radius: 10px;
  background: transparent;
  color: var(--text);
  cursor: pointer;
  align-items: center; justify-content: center;
  flex: 0 0 auto;
}
.topbar__menu:hover { color: var(--accent); border-color: var(--accent); }

/* ---- 左侧导航 ---- */
.sidebar {
  position: absolute;
  top: calc(var(--pad) + var(--top-h) + 10px);
  bottom: var(--pad);
  left: var(--pad);
  width: var(--left-w);
  z-index: 5;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition: width .26s cubic-bezier(.4,0,.2,1), transform .28s cubic-bezier(.4,0,.2,1), opacity .2s ease;
}
.sidebar.is-collapsed {
  transform: translateX(calc(-100% - var(--pad) - 6px));
  opacity: 0;
  pointer-events: none;
}

.sidebar__mark {
  display: none;
  width: 34px; height: 34px;
  border-radius: 11px;
  background: linear-gradient(150deg, var(--accent), color-mix(in srgb, var(--accent) 62%, #000));
  color: var(--accent-ink);
  font-family: var(--serif);
  font-size: 16px; font-weight: 700;
  align-items: center; justify-content: center;
  flex: 0 0 auto;
  box-shadow: 0 4px 14px var(--accent-glow);
}

.sidebar__brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 15px 16px 13px;
  border-bottom: 1px solid var(--line-soft);
  flex: none;
}
.sidebar__logo {
  font-family: var(--serif); font-size: 16px; letter-spacing: .2em;
  color: var(--accent); white-space: nowrap; font-weight: 600;
}
.sidebar__name { font-size: 13px; color: var(--muted); white-space: nowrap; flex: 1; }
.sidebar__collapse {
  margin-left: auto; width: 28px; height: 28px;
  border: 1px solid var(--panel-border); border-radius: 8px;
  background: transparent; color: var(--muted);
  cursor: pointer; display: grid; place-items: center;
  transition: .15s ease; flex: 0 0 auto;
}
.sidebar__collapse:hover { color: var(--accent); border-color: var(--accent); }
.sidebar__collapse svg { transition: transform .22s ease; }
.sidebar__collapse:hover svg { transform: rotate(180deg); }

.sidebar__nav { padding: 12px 10px; display: flex; flex-direction: column; gap: 3px; flex: 1; overflow-y: auto; }
.sidebar__foot {
  padding: 12px 16px 16px;
  border-top: 1px solid var(--line-soft);
  display: flex; flex-direction: column; gap: 7px;
  flex: none;
}
/* ⚠️ 这里**不要**写 .sidebar__who { flex-direction: column }。
   账号区是「头像在左 + 文字在右」的左右结构，写成 column 会让头像跑到上方
   （旧版本就是这样，截图里头像浮在「当前账号」上面）。
   左右布局由下面 990 行附近的 .sidebar__who 统一定义。 */
.sidebar__who-k { font-size: 11px; color: var(--muted-dim); font-family: var(--mono); letter-spacing: .1em; text-transform: uppercase; }
.sidebar__who #who { font-weight: 600; word-break: break-all; color: var(--text-strong); font-size: 12.5px; }

/* ============================================================
   ⚠️ 优先级铁律：style.css 仍被 index/report 共用，其后台规则多为
   「.sidebar xxx」/「.tblxxx」形式（带父级+ 0,1,0）。
   本文件的覆盖选择器若不带 .sidebar 前缀，优先级只有 0,1,0，
   同为 0,1,0 时按源码顺序后者胜——但style.css 在前，
   所以凡是 style.css 里带父级前缀的规则，这里必须同样带上父级前缀。
   ============================================================ */

/* 导航项
   ⚠️ 关键：style.css 里是 `.sidebar .subnav__btn.menu-item`（优先级 0,3,0）。
   覆盖它必须写全同样的三个类（0,3,0）+ 本文件后加载 → 才能赢。
   只写 `.sidebar .menu-item`（0,2,0）会输给它，颜色永远停在旧令牌。 */
.sidebar .subnav__btn.menu-item,
.sidebar .menu-item {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  text-align: left;
  border: 0;
  background: transparent;
  padding: 10px 12px;
  border-radius: 10px;
  cursor: pointer;
  color: var(--muted);
  font-size: 14px;
  transition: .16s ease;
  white-space: nowrap;
  position: relative;
}
/* 悬停/ 选中态：同样要带满 `.sidebar .subnav__btn.menu-item` 才能压过 style.css */
.sidebar .subnav__btn.menu-item:hover,
.sidebar .menu-item:hover { background: var(--hover); color: var(--text-strong); }
.sidebar .subnav__btn.menu-item.is-on,
.sidebar .menu-item.is-on {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
  box-shadow: none;
}
.sidebar .subnav__btn.menu-item.is-on::before,
.sidebar .menu-item.is-on::before {
  content: "";
  position: absolute;
  left: 0; top: 9px; bottom: 9px;
  width: 2px;
  border-radius: 2px;
  background: var(--accent);
  box-shadow: 0 0 8px var(--accent-glow);
}
/* 图标：继承 currentColor 跟随文字，style.css 里写死的 --ink-3 需覆盖 */
.sidebar .menu-ico,
.sidebar .subnav__btn .menu-ico { display: inline-flex; flex: 0 0 auto; color: currentColor; opacity: .8; }
.sidebar .menu-item.is-on .menu-ico,
.sidebar .subnav__btn.menu-item.is-on .menu-ico { color: var(--accent); opacity: 1; }
.menu-txt { overflow: hidden; text-overflow: ellipsis; }
.menu-caret { margin-left: auto; font-size: 10px; color: var(--muted-dim); transition: transform .18s ease; }
.menu-item--parent.is-on .menu-caret { transform: rotate(90deg); color: var(--accent); }
.menu-group { display: flex; flex-direction: column; }
/* ⚠️ 二级菜单与一级项之间要有呼吸：一级项有选中底纹时，
   二级若紧贴其下沿就会出现「两块矩形拼成一块」的观感。
   加一点上边距把两层在纵向上分开。 */
.sidebar .menu-sub { display: flex; flex-direction: column; padding-left: 22px; gap: 2px; margin: 4px 0 2px; }
/* 必须带 .sidebar 前缀：style.css 里有`.sidebar .menu-item--sub`
   且其 .is-on 是白底黑字，不覆盖会导致深色主题下出现刺眼白块 */
/* 🔴 2026-10-23 需求 9：改成 flex 容器 —— 二级项原来是 display:block，
   `.menu-badge` 上的 `margin-left:auto` 完全失效，统计数字紧贴在
   「商品列表」文字后面。改成 flex + auto 后数字被推到最右，
   并且与一级项（客户档案 / 报告记录 / 问卷记录）的右边缘对齐
   （两边右内边距都是 12px）。 */
.sidebar .menu-item--sub {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; border: 0; background: transparent;
  padding: 7px 12px 7px 16px; border-radius: 8px; cursor: pointer;
  color: var(--muted); font-size: 13px; transition: .15s ease;
  position: relative;
}
.sidebar .menu-item--sub:hover { background: var(--hover); color: var(--text); }
/* 🔴 二级项选中态**不要底纹**（用户明确要求）。
   为什么：一级项选中是 --accent-soft 底纹，二级项紧跟其下若也是同色底纹，
   两块矩形严丝合缝地贴在一起，看起来连成一整片，分不出两层。
   改为只留左侧刻度 + 主色文字，用「颜色 + 刻度」表达选中，
   一级的底纹边界因此始终清晰可见。
   ⚠️ 必须显式写 background: transparent —— 不能只是删掉这一行：
     style.css L390 有 `.sidebar .menu-item--sub.is-on { background: var(--surface) }`，
     同为 (0,3,0) 且本文件后加载，删掉声明就等于把白底放出来。 */
.sidebar .menu-item--sub.is-on {
  background: transparent;
  color: var(--accent);
  font-weight: 600;
  box-shadow: none;
}
.sidebar .menu-item--sub.is-on:hover { background: var(--hover); }
/* 二级项左侧的小刻度，替代传统缩进线 */
.sidebar .menu-item--sub.is-on::before {
  content: "";
  position: absolute; left: 7px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 13px; border-radius: 2px;
  background: var(--accent);
  box-shadow: 0 0 7px var(--accent-glow);
}

/* ============================================================
   图标栏（rail）折叠态—— 恢复用户原有的收起模式
   收起时侧栏压成一条窄轨：每个一级菜单的图标都在，
   文字/角标/二级菜单全部隐藏，悬停出名称气泡，
   带子菜单的一级项（顾问管理 / 门店管理）悬停时向右弹浮层。
   ============================================================ */
.layout.left-collapsed .sidebar {
  width: var(--rail-w);
  flex-basis: var(--rail-w);
  /* 折叠态必须放开裁切：二级菜单浮层要能伸出图标栏，
     否则会被 overflow:hidden 切掉。展开态菜单项本就在内缩位置，不受影响。 */
  overflow: visible;
}
.layout.left-collapsed .sidebar__brand {
  padding: 12px 0 11px;
  justify-content: center;
}
.layout.left-collapsed .sidebar__mark,
.layout.left-collapsed .sidebar__logo,
.layout.left-collapsed .sidebar__name { display: none; }
/* 折叠态顶部只保留「展开」按钮，不显示任何 Logo */
.layout.left-collapsed .sidebar__collapse {
  margin-left: 0;
  width: 34px; height: 34px;
  border-radius: 10px;
  background: var(--hover);
}
.layout.left-collapsed .sidebar__collapse svg { transform: rotate(180deg); }
.layout.left-collapsed .sidebar__collapse:hover svg { transform: rotate(0deg); }
/* 底部账号区：折叠态**只保留当前登录账号的头像**（居中），
   文字信息全部隐藏。⚠️ 不要再用 ::after 补一个竖排「MIRA」落款——
   收起态宽度只有 74px，任何额外字样都会挤成脏东西。 */
.layout.left-collapsed .sidebar__foot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
  padding: 10px 0 12px;
}
/* 折叠态：保留头像，隐藏账号文字 */
.layout.left-collapsed .sidebar__foot .sidebar__who-main { display: none; }
.layout.left-collapsed .sidebar__foot .sidebar__avatar {
  width: 34px; height: 34px;
  font-size: 15px;
  cursor: default;
}
/* 折叠态头像悬停 → 向右弹账号气泡（与菜单项 data-tip 气泡同一套语言） */
.layout.left-collapsed .sidebar__foot .sidebar__who { position: relative; }
.layout.left-collapsed .sidebar__foot .sidebar__avatar::after {
  content: attr(data-who);
  position: absolute;
  left: calc(100% + 12px);
  top: 50%;
  transform: translateY(-50%);
  padding: 6px 10px;
  border-radius: 8px;
  background: var(--panel-bg-solid);
  border: 1px solid var(--panel-border-strong);
  color: var(--text-strong);
  font-size: 12.5px;
  white-space: nowrap;
  box-shadow: var(--shadow-sm);
  opacity: 0;
  visibility: hidden;
  transition: opacity .15s ease;
  pointer-events: none;
  z-index: 9;
}
.layout.left-collapsed .sidebar__foot .sidebar__avatar:hover::after { opacity: 1; visibility: visible; }
.layout.left-collapsed .sidebar__nav { padding: 10px 8px; align-items: center; gap: 4px; overflow: visible; }
/* 分组标题（业务/试衣间/组织）在折叠态隐藏文字，
   改由 .menu-group 之间的分隔线表达层级。 */
.layout.left-collapsed .sidebar .menu-label { display: none; }
.layout.left-collapsed .sidebar .menu-group { width: 100%; }
.layout.left-collapsed .sidebar .menu-group + .menu-group {
  border-top: 1px solid var(--line-soft);
  padding-top: 6px;
  margin-top: 2px;
}
/* 一级菜单项：只留图标、居中 */
.layout.left-collapsed .sidebar .subnav__btn.menu-item,
.layout.left-collapsed .sidebar .menu-item {
  justify-content: center;
  gap: 0;
  padding: 11px 0;
  width: 46px;
}
.layout.left-collapsed .sidebar .menu-txt,
.layout.left-collapsed .sidebar .menu-badge,
.layout.left-collapsed .sidebar .menu-caret,
.layout.left-collapsed .sidebar .menu-tag-soon,
.layout.left-collapsed .sidebar .menu-ico--ext { display: none; }
/* 二级菜单：折叠态默认收起，hover 父级时向右弹出 */
.layout.left-collapsed .sidebar .menu-sub {
  display: none;
  position: absolute;
  left: calc(100% + 12px);
  top: 0;
  min-width: 158px;
  padding: 6px;
  gap: 2px;
  z-index: 8;
  background: var(--panel-bg-solid);
  border: 1px solid var(--panel-border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
}
.layout.left-collapsed .sidebar .menu-group { position: relative; }
.layout.left-collapsed .sidebar .menu-group:hover .menu-sub { display: flex; }
.layout.left-collapsed .sidebar .menu-item--sub { white-space: nowrap; }
/* 悬停名称气泡（用 data-tip，一级菜单在 HTML 里标注） */
.layout.left-collapsed .sidebar .menu-item[data-tip] { position: relative; }
.layout.left-collapsed .sidebar .menu-item[data-tip]::after {
  content: attr(data-tip);
  position: absolute;
  left: calc(100% + 12px);
  top: 50%;
  transform: translateY(-50%);
  padding: 6px 10px;
  border-radius: 8px;
  background: var(--panel-bg-solid);
  border: 1px solid var(--panel-border-strong);
  color: var(--text-strong);
  font-size: 12.5px;
  white-space: nowrap;
  box-shadow: var(--shadow-sm);
  opacity: 0;
  visibility: hidden;
  transition: opacity .15s ease;
  pointer-events: none;
  z-index: 9;
}
.layout.left-collapsed .sidebar .menu-item[data-tip]:hover::after { opacity: 1; visibility: visible; }
/* 带子菜单的父级：气泡压在浮层之上会打架，故父级 hover 时不显示气泡 */
.layout.left-collapsed .sidebar .menu-group:hover .menu-item--parent::after { opacity: 0; visibility: hidden; }

/* ---- 中心内容区 ---- */
.content {
  position: absolute;
  top: calc(var(--pad) + var(--top-h) + 10px);
  bottom: var(--pad);
  left: calc(var(--pad) + var(--left-w) + 10px);
  right: var(--pad);
  z-index: 4;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 4px 2px 24px;
  transition: left .28s cubic-bezier(.4,0,.2,1), right .28s cubic-bezier(.4,0,.2,1);
}
.layout.left-collapsed .content { left: calc(var(--pad) + var(--rail-w) + 10px); }

/* 移动端遮罩 */
.nav-scrim {
  position: fixed; inset: 0;
  background: rgba(0, 0, 0, .5);
  opacity: 0; pointer-events: none;
  transition: opacity .22s ease;
  z-index: 4;
}
.layout.nav-open .nav-scrim { opacity: 1; pointer-events: auto; }

/* ---- 旧 style.css 的后台布局规则兜底覆盖 ----
   style.css 仍被 index.html / report.html 共用，里面的 `.layout.is-collapsed …`
   一族规则（宽 72px / 隐藏文字 / 折叠钮绝对定位）会在后台命中。
   本文件的 rail 规则写在后面且带 .layout.left-collapsed 前缀，优先级更高；
   这里只需保证「展开态」不被旧规则误伤。 */
.layout:not(.left-collapsed) .sidebar { width: var(--left-w); }
.layout:not(.left-collapsed) .sidebar .menu-item--sub,
.layout:not(.left-collapsed) .sidebar .menu-sub,
.layout:not(.left-collapsed) .sidebar__foot,
.layout:not(.left-collapsed) .sidebar .menu-txt { display: revert; }
/* 🔴 2026-10-23 需求 9：上面那条 `.menu-item--sub { display: revert }`
   会把它打回按钮的 UA 默认值（inline-block）→ `.menu-badge` 的
   `margin-left:auto` 再次失效，统计数字又贴回文字旁边。
   这条写在后面、特异性相同 → 赢，把展开态的二级项钉死在 flex。 */
.layout:not(.left-collapsed) .sidebar .menu-item--sub { display: flex; }
.layout:not(.left-collapsed) .sidebar__collapse { position: static; transform: none; }

/* ============================== 页面部件 ============================== */
.wrap { max-width: 560px; margin: 0 auto; padding: 0 18px 72px; }
.page-head { padding: 30px 0 20px; text-align: center; }
.page-head__brand {
  font-family: var(--serif); font-size: 12px; letter-spacing: .34em;
  color: var(--accent); text-transform: uppercase;
}
.page-head__title { font-size: 26px; margin: 10px 0 8px; color: var(--text-strong); }
.page-head__desc { color: var(--muted); font-size: 14px; }

/* 统计卡：金色数字 + 等宽标签，科技仪表感 */
.statgrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  margin-bottom: 18px;
}
.stat {
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  padding: 14px 16px;
  backdrop-filter: var(--backdrop);
  -webkit-backdrop-filter: var(--backdrop);
  position: relative;
  overflow: hidden;
  transition: border-color .16s ease, transform .16s ease;
}
.stat:hover { border-color: var(--panel-border-strong); }
.stat::after {
  /* 右上角一抹极淡的暖光，避免大面积死板。
     透明度要很低——浅色主题下过亮会像一块脏印。 */
  content: "";
  position: absolute; top: -34px; right: -34px;
  width: 96px; height: 96px;
  background: radial-gradient(circle, var(--accent-glow), transparent 72%);
  opacity: .5;
  pointer-events: none;
}
.stat__k {
  font-size: 10.5px; color: var(--muted-dim);
  font-family: var(--mono); letter-spacing: .12em; text-transform: uppercase;
}
.stat__v {
  font-family: var(--serif);
  font-size: 27px;
  line-height: 1.25;
  color: var(--text-strong);
  font-variant-numeric: tabular-nums;
}
.stat__u {
  font-size: 12px;
  font-family: var(--mono);
  color: var(--muted-dim);
  margin-left: 5px;
  letter-spacing: .04em;
}
.stat__note { font-size: 11.5px; color: var(--muted-dim); margin-top: 3px; }
.stat__bar {
  height: 3px;
  border-radius: 3px;
  background: var(--line-soft);
  overflow: hidden;
  margin-top: 8px;
}
.stat__bar > i {
  display: block;
  height: 100%;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--accent), color-mix(in srgb, var(--accent) 40%, transparent));
  box-shadow: 0 0 10px var(--accent-glow);
  transition: width .5s cubic-bezier(.4, 0, .2, 1);
}

/* ---- 仪表盘式统计卡：左侧环形进度 + 右侧数据，替代老式纯数字块 ---- */
.stat--ring {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 15px 16px;
}
.stat__dial {
  --pct: 0deg;
  --tone: var(--accent);
  flex: none;
  width: 62px;
  height: 62px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  position: relative;
  background:
    conic-gradient(var(--tone) var(--pct), var(--line-soft) 0);
  transition: background .6s cubic-bezier(.4, 0, .2, 1);
}
.stat__dial::before {
  content: "";
  position: absolute;
  inset: 5px;
  border-radius: 50%;
  background: var(--panel-bg-solid);
  box-shadow: inset 0 0 0 1px var(--line-soft);
}
.stat__dial-n {
  position: relative;
  font-family: var(--mono);
  font-size: 15px;
  font-weight: 600;
  color: var(--text-strong);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
}
.stat__dial-n i { font-size: 9px; font-style: normal; color: var(--muted-dim); margin-left: 1px; }
.stat__body { min-width: 0; flex: 1 1 auto; }
.stat--model {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
}
.stat__model {
  font-family: var(--mono);
  font-size: 14px;
  color: var(--accent);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.toolbar {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: 14px;
  padding: 12px 14px;
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  backdrop-filter: var(--backdrop);
  -webkit-backdrop-filter: var(--backdrop);
}
.toolbar .input { max-width: 240px; }
/* HUD 工具条：左侧一道金色竖脊 + 竖排小标签，暗示"控制台" */
.toolbar--hud {
  border-left: 2px solid var(--accent);
  position: relative;
}
.toolbar__label {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--accent);
  padding-right: 12px;
  margin-right: 2px;
  border-right: 1px solid var(--line);
  align-self: stretch;
  display: flex;
  align-items: center;
}

/* ---- 区块标题：金色短竖条 + 衬线标题 + 说明 ---- */
.sec-head { display: flex; align-items: baseline; gap: 10px; margin: 4px 0 12px; }
.sec-head__t {
  font-size: 15.5px;
  color: var(--text-strong);
  padding-left: 10px;
  border-left: 2px solid var(--accent);
  line-height: 1.3;
}
.sec-head__d { font-size: 11.5px; color: var(--muted-dim); }

/* ---- 工作流三连卡：把「投放→问卷→诊断」显性化，填补空白也体现专业流程 ---- */
.flow {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 10px;
}
.flow__step {
  display: flex;
  gap: 12px;
  padding: 14px 15px;
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  backdrop-filter: var(--backdrop);
  -webkit-backdrop-filter: var(--backdrop);
  position: relative;
  overflow: hidden;
  transition: border-color .16s ease;
}
.flow__step:hover { border-color: var(--panel-border-strong); }
.flow__step::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 1px;
  background: linear-gradient(90deg, var(--accent), transparent 70%);
  opacity: .35;
}
.flow__no {
  flex: none;
  font-family: var(--mono);
  font-size: 17px;
  font-weight: 600;
  color: var(--accent);
  opacity: .55;
  line-height: 1.1;
  letter-spacing: -.02em;
}
.flow__b { min-width: 0; }
.flow__b b { display: block; font-family: var(--serif); font-size: 14px; color: var(--text-strong); margin-bottom: 3px; }
.flow__b p { margin: 0; line-height: 1.6; }
.flow__acts { display: flex; gap: 6px; margin-top: 9px; flex-wrap: wrap; }

/* ---- 客户档案卡列表：替代老式表格行，顾问一眼扫完 ---- */
.dcard-list {
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.dcard {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 16px 12px 12px;
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  backdrop-filter: var(--backdrop);
  -webkit-backdrop-filter: var(--backdrop);
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: border-color .16s ease, transform .16s ease, box-shadow .16s ease;
}
.dcard::before {
  /* 左侧状态色条：已出报告=金，待诊断=琥珀 */
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 2px;
  background: var(--warn);
  opacity: .75;
}
.dcard.is-done::before { background: var(--accent); }
.dcard:hover {
  border-color: var(--panel-border-strong);
  transform: translateX(2px);
  box-shadow: var(--shadow-sm);
}
.dcard__swatch {
  --h: 40;
  flex: none;
  width: 46px;
  height: 46px;
  border-radius: 12px;
  display: grid;
  place-items: center;
  font-family: var(--serif);
  font-size: 18px;
  font-weight: 600;
  color: hsl(var(--h) 30% 90%);
  /* 同一色相内做明暗变化（不跨色相），保证整列都是协调的服装色系 */
  background: linear-gradient(155deg, hsl(var(--h) 26% 46%), hsl(var(--h) 22% 30%));
  box-shadow: inset 0 0 0 1px hsl(var(--h) 34% 66% / .30), 0 3px 10px rgba(0, 0, 0, .22);
}
.dcard__main { flex: 1 1 auto; min-width: 0; }
.dcard__top { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.dcard__name { font-family: var(--serif); font-size: 15.5px; color: var(--text-strong); font-weight: 600; }
.dcard__no { font-family: var(--mono); font-size: 11px; color: var(--muted-dim); letter-spacing: .04em; }
/* 🔴 2026-10-22 需求 16：问卷编号（Q-00005）。与档案编号并排显示，
   用极淡的底色把「这是编号不是正文」圈出来；配色走主题变量（--hover/--line-soft，
   与 .dchip 同源），深浅两套模式自动跟随，不写死颜色。 */
.dcard__qno {
  font-family: var(--mono); font-size: 11px; color: var(--muted-dim); letter-spacing: .04em;
  background: var(--hover); border: 1px solid var(--line-soft); border-radius: 4px; padding: 0 5px;
}
.dcard__flag {
  font-size: 10.5px;
  font-family: var(--mono);
  letter-spacing: .06em;
  padding: 1px 8px;
  border-radius: 20px;
  border: 1px solid transparent;
}
.dcard__flag.ok { color: var(--ok); background: var(--ok-soft); border-color: color-mix(in srgb, var(--ok) 34%, transparent); }
.dcard__flag.wait { color: var(--warn); background: var(--warn-soft); border-color: color-mix(in srgb, var(--warn) 34%, transparent); }
.dcard__chips { display: flex; gap: 5px; flex-wrap: wrap; margin-top: 5px; }
/* 🆕 需求 6：客户档案头像 + 编号 */
.person-avat { width: 46px; height: 46px; border-radius: 12px; overflow: hidden; flex: none; background: var(--hover); position: relative; }
.person-avat img { width: 100%; height: 100%; object-fit: cover; display: block; }
.person-ini { width: 100%; height: 100%; display: grid; place-items: center; font-family: var(--serif); font-size: 18px; font-weight: 600; color: hsl(var(--h) 30% 90%); background: linear-gradient(155deg, hsl(var(--h) 26% 46%), hsl(var(--h) 22% 30%)); box-shadow: inset 0 0 0 1px hsl(var(--h) 34% 66% / .30); }
.dcard__no { background: var(--hover); border: 1px solid var(--line-soft); border-radius: 4px; padding: 0 5px; margin-left: 6px; }
/* 🆕 需求 6：详情页头像 */
/* 🔴 2026-10-23 需求 13：头像改成**圆角正方形**。
   旧值是 border-radius:50%（正圆），而外层 .dhero__av 本身就是 16px 圆角方
   → 圆图套在方框里，用户看到的就是「两层头像」（一个圆 + 一个方角）。
   这里给 14px（外层 16px 减去自身 2px 边框），图片刚好填满圆角方。 */
.person-ava-detail { width: 48px; height: 48px; border-radius: 14px; overflow: hidden; flex: none; background: var(--hover); border: 2px solid var(--line); }
.person-ava-detail img { width: 100%; height: 100%; object-fit: cover; display: block; }
.person-ini-detail { width: 48px; height: 48px; border-radius: 14px; display: grid; place-items: center; font-family: var(--serif); font-size: 20px; font-weight: 600; color: #fff; background: linear-gradient(155deg, hsl(var(--h) 26% 46%), hsl(var(--h) 22% 30%)); flex: none; }
/* 🆕 需求 3：商品卡片重做（参考顾问列表卡片） */
.sku-card { flex-direction: column; height: auto; }
.sku-card__hero { position: relative; width: 100%; height: 200px; overflow: hidden; background: var(--hover); }
/* 🔴🔴 v1.16.13 修复（用户报障 @image#1：非正方形主图被截掉一部分）：
   旧值是 `object-fit: cover` —— 卡片舞台固定 200px 高、宽度撑满，
   竖图 / 宽图都会被**裁掉两侧或上下**，用户看到的就是「图不完整」。
   项目铁律：商品图一律 `contain` + 白底（`.sku-mup__slot img` / `.mcell img`
   早已如此，唯独这张列表卡漏了）。改 contain 后不足的区域由白底补齐。
   ⚠️ 白底必须写死 `#fff`（不是 var(--panel-bg)）—— 图片本身多是白底商品图，
      深色模式下若用面板底色会形成明显的深色边框，看着像「图被贴了黑边」。 */
.sku-card__img { width: 100%; height: 100%; object-fit: contain; background: #fff; display: block; }
.sku-card__img--empty { display: grid; place-items: center; width: 100%; height: 100%; font-family: var(--serif); font-size: 32px; color: var(--muted-dim); background: var(--panel-bg); }
.sku-card__body { padding: 10px 14px; flex: 1; display: flex; flex-direction: column; gap: 7px; }
.sku-card__top { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.sku-card__name { font-family: var(--serif); font-size: 15px; color: var(--text-strong); font-weight: 600; }
.sku-card__no { font-family: var(--mono); font-size: 11px; color: var(--muted-dim); letter-spacing: .04em; }
.sku-card__meta { display: flex; gap: 6px; flex-wrap: wrap; }
.sku-card__flag { font-size: 10px; font-family: var(--mono); letter-spacing: .06em; padding: 1px 7px; border-radius: 20px; border: 1px solid transparent; }
.sku-card__flag.ok { color: var(--ok); background: var(--ok-soft); border-color: color-mix(in srgb, var(--ok) 34%, transparent); }
.sku-card__flag.wait { color: var(--warn); background: var(--warn-soft); border-color: color-mix(in srgb, var(--warn) 34%, transparent); }
.sku-card__chips { display: flex; gap: 5px; flex-wrap: wrap; margin-top: 6px; }
.sku-card__acts { padding: 8px 14px 12px; display: flex; gap: 6px; border-top: 1px solid var(--line-soft); margin-top: auto; }
/* 🆕 需求 3：列表模式头图缩略图 */
/* 🔴 v1.16.13：与网格卡同一口径 —— `contain` + 白底，非正方形图完整显示不裁切。 */
.sku-list__thumb { width: 70px; height: 70px; border-radius: 8px; overflow: hidden; flex: none; background: #fff; }
.sku-list__thumb img { width: 100%; height: 100%; object-fit: contain; display: block; }
.sku-list__thumb--empty { display: grid; place-items: center; width: 70px; height: 70px; border-radius: 8px; background: var(--panel-bg); font-size: 20px; color: var(--muted-dim); font-family: var(--serif); }
.dchip {
  font-size: 11px;
  color: var(--muted);
  background: var(--hover);
  border: 1px solid var(--line-soft);
  padding: 1px 7px;
  border-radius: 6px;
}
.dcard__contact { font-size: 11.5px; color: var(--muted-dim); margin-top: 4px; font-family: var(--mono); }
.dcard__side { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 7px; }
.dcard__date { font-size: 11px; color: var(--muted-dim); font-family: var(--mono); }
.dcard__acts { display: flex; gap: 6px; }

/* ---- 侧栏分组标题 / 角标 / 账号卡 ---- */
.menu-label {
  display: block;
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--muted-dim);
  padding: 14px 12px 5px;
  opacity: .8;
}
.menu-label:first-child { padding-top: 4px; }
.menu-badge {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--muted);
  background: var(--hover);
  border: 1px solid var(--line-soft);
  border-radius: 20px;
  padding: 0 7px;
  line-height: 17px;
  flex: none;
}
.sidebar .menu-item.is-on .menu-badge { color: var(--accent); border-color: var(--panel-border-strong); background: transparent; }
.menu-tag-soon {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 8.5px;
  letter-spacing: .14em;
  color: var(--info);
  background: var(--info-soft);
  border: 1px solid color-mix(in srgb, var(--info) 30%, transparent);
  border-radius: 5px;
  padding: 1px 5px;
  flex: none;
}
/* v1.16.37：「MIRA 虚拟试衣」外链角标（顶替原来的 SOON 徽标） */
.menu-ico--ext {
  margin-left: auto;
  opacity: .62;
  display: inline-flex;
  align-items: center;
}
.sidebar .menu-item:hover .menu-ico--ext { opacity: 1; color: var(--accent); }
.sidebar__who { display: flex; align-items: center; gap: 10px; }
.sidebar__avatar {
  flex: none;
  width: 32px; height: 32px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  font-family: var(--serif);
  font-size: 14px;
  font-weight: 700;
  color: var(--accent-ink);
  background: linear-gradient(140deg, var(--accent), color-mix(in srgb, var(--accent) 55%, #000));
  box-shadow: 0 0 0 1px var(--panel-border-strong);
}
.sidebar__who-main { display: flex; flex-direction: column; min-width: 0; line-height: 1.35; flex: 1 1 auto; }
/* 邮箱可能很长：一律**单行 + 末尾省略号**，绝不换行 ——
   换行会把下方的角色名挤出可视区，看起来像布局塌了。
   🔴 flex 子项默认 min-width:auto（= 文本全部宽度），不写 min-width:0
      的话 ellipsis 根本不会生效 —— 容器会被长邮箱直接顶宽。 */
.sidebar__who-main > #who {
  font-size: 11.5px;
  color: var(--text);
  line-height: 1.3;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.sidebar__role {
  font-size: 10.5px;
  color: var(--accent);
  font-family: var(--mono);
  letter-spacing: .06em;
  white-space: nowrap;
}

/* 表格：悬浮玻璃表，hover 时浮起高亮行 */
.tbl-wrap {
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  overflow: hidden;
  backdrop-filter: var(--backdrop);
  -webkit-backdrop-filter: var(--backdrop);
  box-shadow: var(--shadow-sm);
}
.tbl { width: 100%; border-collapse: collapse; font-size: 14px; }
.tbl th {
  text-align: left; font-weight: 600; font-size: 11px;
  color: var(--muted-dim);
  font-family: var(--mono); letter-spacing: .1em; text-transform: uppercase;
  padding: 11px 14px;
  border-bottom: 1px solid var(--panel-border);
  background: var(--accent-soft);
  white-space: nowrap;
}
.tbl td { padding: 12px 14px; border-bottom: 1px solid var(--line-soft); vertical-align: middle; }
.tbl tr:last-child td { border-bottom: 0; }
.tbl tbody tr { transition: background .14s ease; }
.tbl tbody tr:hover { background: var(--hover); cursor: pointer; }

.tag {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: 11.5px;
  border: 1px solid var(--panel-border);
  color: var(--muted);
  letter-spacing: .02em;
}
.tag--done { background: var(--ok-soft); border-color: color-mix(in srgb, var(--ok) 40%, transparent); color: var(--ok); }
.tag--wait { background: var(--warn-soft); border-color: color-mix(in srgb, var(--warn) 40%, transparent); color: var(--warn); }
.tag--warn { background: var(--danger-soft); border-color: color-mix(in srgb, var(--danger) 40%, transparent); color: var(--danger); }
.tag--brief { background: var(--info-soft); border-color: color-mix(in srgb, var(--info) 40%, transparent); color: var(--info); }
.tag--full { background: var(--accent-soft); border-color: var(--panel-border-strong); color: var(--accent); }

/* 子标签页 */
/* 🆕 2026-10-22 需求 4：tab 行与下方内容的间距全局放大（4px → 18px）。
   用户原话：「tab 按钮一行与下方内容之间需要增大间距，不要紧挨着，不要有拥挤感。
   这个间距应该是全局的」——AI 自媒体栏目与 AI 素材中心都有同一问题
   （tab 下方横线与内容间距过小）。.subtabs 是后台 7 处视图共用的类，
   改这一条即全局生效；各视图内部没有补偿用的负 margin，放大不会挤压布局。 */
.subtabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 18px;
}
.subtab {
  border: 0;
  background: transparent;
  padding: 9px 15px;
  cursor: pointer;
  color: var(--muted-dim);
  font-size: 14px;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: .16s ease;
}
.subtab:hover { color: var(--text); }
.subtab.is-on { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }

.subnav {
  display: flex; gap: 4px;
  background: var(--accent-soft);
  border: 1px solid var(--panel-border);
  border-radius: 999px;
  padding: 4px;
  margin-bottom: 18px;
  width: fit-content;
}
.subnav__btn {
  border: 0; background: transparent;
  padding: 7px 18px; border-radius: 999px;
  cursor: pointer; color: var(--muted);
  font-size: 13.5px; transition: .15s ease;
}
.subnav__btn.is-on {
  background: var(--panel-bg-solid);
  color: var(--accent);
  font-weight: 600;
  box-shadow: var(--shadow-sm);
}

/* 个人详情分区 */
.psec {
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  padding: 15px 17px;
  margin-bottom: 14px;
  backdrop-filter: var(--backdrop);
  -webkit-backdrop-filter: var(--backdrop);
}
.psec__h {
  font-family: var(--serif); font-size: 15px; font-weight: 600;
  margin-bottom: 11px;
  display: flex; align-items: center; gap: 8px;
  color: var(--text-strong);
  padding-bottom: 9px;
  border-bottom: 1px solid var(--line-soft);
}
.psec__h .tiny { font-weight: 400; }
.pgrid { display: grid; grid-template-columns: 92px 1fr; gap: 7px 12px; font-size: 13.5px; }
.pgrid dt { color: var(--muted-dim); font-size: 12.5px; }
.pgrid dd { margin: 0; color: var(--text); word-break: break-word; }
.kv { display: grid; grid-template-columns: 96px 1fr; gap: 7px 12px; font-size: 13.5px; }
.kv dt { color: var(--muted-dim); }
.kv dd { margin: 0; color: var(--text); word-break: break-word; }

.grid2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px; }
.minicard {
  background: color-mix(in srgb, var(--panel-bg-solid) 50%, transparent);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
}
.minicard__k { font-size: 11.5px; color: var(--muted-dim); font-family: var(--mono); letter-spacing: .08em; text-transform: uppercase; }
.minicard__v { font-size: 15px; font-weight: 600; color: var(--text-strong); }

.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 8px; }
.tile {
  background: var(--accent-soft);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
}
.tile b { display: block; font-size: 11.5px; color: var(--muted-dim); font-weight: 500; margin-bottom: 3px; }
.tile span { font-size: 14px; color: var(--text-strong); }

/* 标签编辑器 */
.taged { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.tagpill {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--accent-soft);
  border: 1px solid var(--panel-border);
  border-radius: 999px;
  padding: 3px 6px 3px 11px;
  font-size: 12.5px;
  color: var(--text);
}
.tagpill button {
  border: 0; background: transparent; color: var(--muted-dim);
  cursor: pointer; font-size: 13px; line-height: 1; padding: 0 3px;
}
.tagpill button:hover { color: var(--danger); }
.taged-add { display: flex; gap: 6px; }
.taged-add .input { max-width: 200px; }

.pvisits { display: flex; flex-direction: column; gap: 8px; }
.pvisit {
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  padding: 11px 13px;
  background: var(--accent-soft);
}
.pvisit b { font-size: 13.5px; color: var(--text-strong); }
.pvisit .tiny { color: var(--muted-dim); }

/* ---- 历史诊断报告：一行一条 + 右侧操作（2026-10-23 需求 10） ----
   旧版是「标题一行 + 按钮另起一行」的两行结构，报告编号 / 档案编号 /
   类型 / 时间四项信息塞不下。改成左右两栏：左边信息一行排开，右边按钮。 */
.pvisit--row {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
}
.pvisit__main {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  flex: 1 1 auto; min-width: 0;
}
.pvisit__no {
  font-family: var(--mono); font-size: 12.5px; color: var(--text-strong);
  flex: none;
}
.pvisit__arch {
  font-family: var(--mono); font-size: 11.5px; color: var(--muted-dim);
  max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pvisit__time { font-size: 12px; color: var(--muted); flex: none; }
.pvisit__side { display: flex; gap: 6px; flex-wrap: wrap; flex: 0 0 auto; margin-left: auto; }
/* 报告类型标签（与报告记录模块的 .rl-tag 同族同色，两处口径一致） */
.rl-tag {
  display: inline-block; padding: 1px 7px; border-radius: 999px;
  font-size: 11.5px; line-height: 1.6; border: 1px solid transparent; white-space: nowrap;
}
.rl-tag--initial { background: #FBF3E0; color: #8A6410; border-color: #E8D6AC; }
.rl-tag--followup { background: #E7F3EA; color: #2F6B41; border-color: #BFDECB; }
.pedit-row { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; flex-wrap: wrap; }
.pedit-row .input { max-width: 220px; }

.panel { }
.panel__h {
  font-family: var(--serif); font-size: 15px; font-weight: 600;
  color: var(--text-strong); margin-bottom: 10px;
  display: flex; align-items: center; gap: 8px;
}

/* ====================== 详情抽屉：分区化信息架构 ======================
   旧版把所有字段平铺成一个长 kv 列表（二十多项从上到下），
   现在按「名片 → 交付 → 体态 → 照片 → 基本 → 色彩 → 偏好」分区，
   每区用卡片 + 小标题分组，字段用「标签在上、值在下」的网格，便于扫读。 */
.dsheet { display: flex; flex-direction: column; gap: 14px; }

/* 名片区：头像 + 姓名 + 编号 + 状态 */
.dhero {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 18px;
  border-radius: var(--radius);
  border: 1px solid var(--panel-border);
  background:
    radial-gradient(120% 140% at 0% 0%, var(--accent-soft), transparent 62%),
    var(--panel-bg);
  backdrop-filter: var(--backdrop);
  -webkit-backdrop-filter: var(--backdrop);
}
.dhero__av {
  width: 54px; height: 54px;
  border-radius: 16px;
  display: grid; place-items: center;
  font-family: var(--serif);
  font-size: 22px; font-weight: 600;
  color: var(--accent-ink);
  background: linear-gradient(150deg, var(--accent), color-mix(in srgb, var(--accent) 58%, #000));
  box-shadow: 0 6px 18px var(--accent-glow);
  flex: 0 0 auto;
}
.dhero__m { min-width: 0; flex: 1; }
.dhero__n { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.dhero__name { font-family: var(--serif); font-size: 19px; color: var(--text-strong); }
.dhero__no { font-family: var(--mono); font-size: 12px; color: var(--muted-dim); }
/* 🔴 2026-10-22 需求 16：抽屉名片里的问卷编号（与档案编号并排，同 .dchip 配色） */
.dhero__qno {
  font-family: var(--mono); font-size: 12px; color: var(--muted-dim);
  background: var(--hover); border: 1px solid var(--line-soft); border-radius: 4px; padding: 0 6px;
}
.dhero__sub { margin-top: 5px; font-size: 12.5px; color: var(--muted); display: flex; gap: 10px; flex-wrap: wrap; }

/* 分区卡 */
.dsec {
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  background: var(--panel-bg);
  backdrop-filter: var(--backdrop);
  -webkit-backdrop-filter: var(--backdrop);
  overflow: hidden;
}
.dsec__h {
  display: flex; align-items: center; gap: 9px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--line-soft);
  background: color-mix(in srgb, var(--panel-bg-solid) 45%, transparent);
}
.dsec__ico {
  width: 24px; height: 24px; border-radius: 8px;
  display: grid; place-items: center;
  background: var(--accent-soft);
  color: var(--accent);
  flex: 0 0 auto;
}
.dsec__t { font-size: 14px; font-weight: 600; color: var(--text-strong); letter-spacing: .02em; }
.dsec__d { margin-left: auto; font-size: 11.5px; color: var(--muted-dim); }
.dsec__b { padding: 14px 16px; }
.dsec__b > * + * { margin-top: 10px; }
.dsec .btn--sm { margin-top: 0; }
/* 🆕 需求 2：商品详情板块之间要有间距，不紧挨着 */
.dsec + .dsec { margin-top: 14px; }

/* 字段网格：标签在上、值在下，比 dt/dd 竖排更好扫读 */
.fgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
  gap: 8px;
}
.fgrid--wide { grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); }
.f {
  background: color-mix(in srgb, var(--panel-bg-solid) 55%, transparent);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  padding: 9px 11px;
  min-width: 0;
}
.f__k {
  display: block;
  font-size: 11px;
  color: var(--muted-dim);
  font-family: var(--mono);
  letter-spacing: .06em;
  margin-bottom: 4px;
}
.f__v { display: block; font-size: 13.5px; color: var(--text-strong); word-break: break-word; line-height: 1.5; }
.f__v--dim { color: var(--muted); font-weight: 400; }
/* 跨整行的长文本字段（如补充说明） */
.f--full { grid-column: 1 / -1; }

/* 指标小方块（BMI / 腰臀比 …） */
.metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(122px, 1fr));
  gap: 8px;
}
.metric {
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  background: linear-gradient(160deg, var(--accent-soft), transparent 78%);
}
.metric__k { font-family: var(--mono); font-size: 10.5px; letter-spacing: .1em; color: var(--muted-dim); text-transform: uppercase; }
/* 🔴 v1.16.58 需求 3（用户明令）：以后改/加样式都要留行间距，别让两行紧挨着。
   这里把指标卡三行的行距统一拉开，卡片之间、卡片行与围度数据行之间另见 .bm-layout__data。 */
.metric__v { font-family: var(--serif); font-size: 19px; color: var(--text-strong); line-height: 1.4; margin-top: 7px; }
.metric__d { font-size: 11.5px; line-height: 1.55; color: var(--accent); margin-top: 6px; }

/* 色彩档案：三色并排，色块直观 */
.swatches { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 8px; }
.swatch {
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.swatch__bar { height: 34px; background: var(--accent-soft); border-bottom: 1px solid var(--line-soft); }
.swatch__t { padding: 8px 10px; }
.swatch__k { font-size: 11px; color: var(--muted-dim); font-family: var(--mono); letter-spacing: .06em; }
.swatch__v { font-size: 13.5px; color: var(--text-strong); word-break: break-word; }

/* 分区里的说明性空态 */
.dempty { font-size: 12.5px; color: var(--muted-dim); padding: 4px 0; }
.panel--good { border-color: color-mix(in srgb, var(--ok) 40%, transparent); }

/* ============================================================
   人体形象（body-figure.js）
   尺寸分区左侧的人体：2D 插画速写 + 3D 参数化网格（three.js）。

   配色是「陶土/石膏体模」而非金属色 —— 服装行业的人体展示惯例，
   也避免了金属高光在深色背景上显得廉价。
   ============================================================ */

/* 插画三色：受光面 / 中间调 / 暗面。深色主题下压暗，浅色主题下提亮，
   保证两种主题都像「一张纸上的速写」。 */
[data-theme="dark"] {
  --bf-lit: #E4D3BC;
  --bf-mid: #C9B294;
  --bf-dark: #8C7355;
  --bf-line: rgba(232, 226, 216, .30);
  --bf-ink: #F0E7D9;
}
[data-theme="light"] {
  --bf-lit: #FDFAF4;
  --bf-mid: #EFE0CB;
  --bf-dark: #C0A484;
  --bf-line: rgba(78, 56, 34, .34);
  --bf-ink: #3E2E1E;
}

.bodyfig { display: flex; flex-direction: column; gap: 10px; }
.bodyfig__bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.bf-tabs { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; flex: 1; }
.bf-seg {
  display: inline-flex; padding: 3px; gap: 2px;
  border: 1px solid var(--panel-border); border-radius: 10px;
  background: var(--hover);
}
.bf-seg--solo { background: transparent; border-color: transparent; padding: 0; }
.bf-seg__b {
  border: 0; background: transparent; cursor: pointer;
  font-size: 12px; color: var(--muted);
  padding: 5px 12px; border-radius: 8px;
  transition: .14s ease; white-space: nowrap;
}
.bf-seg__b:hover { color: var(--text-strong); }
.bf-seg__b.is-on { background: var(--panel-bg-solid); color: var(--accent); box-shadow: 0 1px 4px rgba(0,0,0,.14); }
.bf-seg__b[aria-pressed="true"]:not(.is-on) { color: var(--muted-dim); }

.bodyfig__stage {
  position: relative;
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  background:
    radial-gradient(110% 62% at 50% 4%, color-mix(in srgb, var(--accent) 8%, transparent), transparent 60%),
    var(--panel-bg);
  padding: 8px; overflow: hidden;
}
.bf-canvas { display: flex; justify-content: center; }
.bf-canvas[hidden] { display: none; }

/* 双视图并排：正视 + 侧视，像体态评估报告的排法 */
.bf-dual {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 6px; width: 100%; align-items: end;
}
.bf-dual__cell { min-width: 0; display: flex; justify-content: center; }
.bf-svg { width: 100%; max-width: 300px; height: auto; display: block; }
.bf-svg--side { max-width: 220px; }

/* 插画元素 */
.bf-body path { stroke: none; }
.bf-head { stroke: none; }
/* 轮廓线：压在最上层，让剪影干净 */
.bf-outline path {
  stroke: var(--bf-ink); stroke-width: 1.5; stroke-opacity: .62;
  stroke-linejoin: round; stroke-linecap: round;
}
/* 暗面：右侧体积感 */
.bf-shade { fill: var(--bf-dark); opacity: .42; }
/* 内部结构线（胸线/腰线/臀线），比轮廓线更淡 */
.bf-line { fill: none; stroke: var(--bf-line); stroke-width: 1.2; stroke-linecap: round; }
.bf-dot { fill: var(--bf-line); }
/* 地面投影 */
.bf-floor { fill: var(--bf-dark); opacity: .3; }

/* 围度标注 */
.bf-guide line { stroke: var(--accent); stroke-width: 1.2; stroke-dasharray: 5 4; opacity: .8; }
.bf-guide .bf-pt { fill: var(--accent); stroke: none; }
/* ⚠️ 尺寸线文字必须够醒目：图上直接读数值与右侧指标卡对照是本功能的核心目的，
   20px 灰色在缩放后几乎看不清。改为深色 + 细描边压在任何底色上都可读。 */
.bf-svg .bf-t {
  font-size: 21px; font-family: var(--sans); font-weight: 600;
  fill: var(--bf-ink);
  paint-order: stroke fill;
  stroke: color-mix(in srgb, var(--bf-lit) 88%, transparent);
  stroke-width: 4px;
  stroke-linejoin: round;
}
.bf-svg .bf-t--mid { text-anchor: middle; }
/* 身高标注线在头顶上方，视觉上属于「辅助线」而非围度线 */
.bf-guide--h line { opacity: .5; }
.bf-guide--h .bf-t { fill: var(--muted); font-weight: 500; }
/* 侧视手臂：侧视图里手臂与躯干深度重叠，改用一条极淡的斜线暗示位置，
   不再画独立手臂轮廓（原来那条矩形硬边会在躯干上叠出白框）。 */
.bf-arm-hint { fill: none; stroke: var(--bf-line); stroke-width: 1.1; stroke-opacity: .5; stroke-dasharray: 4 4; }

.bodyfig__meta { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; justify-content: space-between; }
.bf-badges { display: flex; gap: 6px; flex-wrap: wrap; }
.bf-badge {
  font-size: 11px; padding: 3px 9px; border-radius: 999px;
  background: var(--hover); color: var(--muted); border: 1px solid var(--line-soft);
}
.bf-badge--warn { color: #B4453B; border-color: color-mix(in srgb, #B4453B 34%, transparent); }
.bf-ratio { display: flex; gap: 14px; font-size: 11.5px; color: var(--muted-dim); flex-wrap: wrap; }
.bf-ratio b { color: var(--text-strong); font-family: var(--mono); }

/* ---- 3D（three.js WebGL 画布） ---- */
.bf-canvas--3d { padding: 0; }
.bf3-stage {
  flex: 1 1 auto;
  width: 100%;
  position: relative; height: 380px; overflow: hidden;
  cursor: grab; touch-action: none; outline: none;
  background:
    radial-gradient(70% 46% at 50% 88%, color-mix(in srgb, var(--accent) 10%, transparent), transparent 66%),
    linear-gradient(180deg, color-mix(in srgb, #fff 3%, transparent), transparent 46%),
    var(--panel-bg);
}
.bf3-stage:active { cursor: grabbing; }
.bf3-stage:focus-visible { box-shadow: inset 0 0 0 2px var(--accent); }
.bf3-canvas-el { display: block; width: 100%; height: 100%; }

/* 载入中 / 失败提示 */
.bf3-loading {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center; gap: 10px;
  font-size: 12.5px; color: var(--muted-dim);
  background: var(--panel-bg);
}
.bf3-loading[hidden] { display: none; }
.bf3-loading--err { color: #B4453B; padding: 0 20px; text-align: center; line-height: 1.6; }
.bf3-spin {
  width: 13px; height: 13px; border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-top-color: var(--accent);
  animation: bfs .8s linear infinite;
}
@keyframes bfs { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .bf3-spin { animation: none; } }

.bf3-hint {
  position: absolute; left: 50%; bottom: 10px; transform: translateX(-50%);
  font-size: 11px; color: var(--muted-dim);
  background: color-mix(in srgb, var(--panel-bg-solid) 82%, transparent);
  padding: 3px 12px; border-radius: 999px; border: 1px solid var(--line-soft);
  pointer-events: none; white-space: nowrap;
}

/* 抽屉里的尺寸分区：左形象 + 右数据 */
.sizelayout { display: grid; grid-template-columns: minmax(220px, 290px) 1fr; gap: 16px; align-items: start; }
.sizelayout__fig { min-width: 0; }
.sizelayout__data { min-width: 0; }
@media (max-width: 720px) {
  .sizelayout { grid-template-columns: 1fr; }
  .bf-dual { grid-template-columns: 1fr; }
  .bf3-stage { height: 300px; }
}

/* AI 流式输出：终端感 */
.streambox {
  background: color-mix(in srgb, var(--panel-bg-solid) 88%, #000);
  color: var(--text);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-sm);
  padding: 14px 16px;
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.7;
  max-height: 240px;
  overflow-y: auto;
  white-space: pre-wrap;
  word-break: break-all;
}
.shots-view { display: flex; gap: 10px; flex-wrap: wrap; }
.shots-view img {
  width: 120px; height: 160px;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid var(--panel-border);
  background: var(--accent-soft);
}
.shots-view figcaption { font-size: 11.5px; color: var(--muted-dim); text-align: center; margin-top: 4px; }
figure { margin: 0; }

.share-box { }
.share-code {
  font-family: var(--mono);
  font-size: 17px;
  letter-spacing: .18em;
  color: var(--accent);
}
/* ---- 报告交付区（抽屉内） ---- */
.share {
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-sm);
  background: linear-gradient(160deg, var(--accent-soft), transparent 70%);
  padding: 12px 14px;
}
.share__top { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.share__pw { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.share__pw-k { font-family: var(--mono); font-size: 10.5px; letter-spacing: .1em; color: var(--muted-dim); text-transform: uppercase; }
.share-code--none { font-size: 13px; letter-spacing: .04em; color: var(--muted-dim); }
.share__state {
  margin-left: auto;
  font-size: 11.5px;
  padding: 2px 9px;
  border-radius: 999px;
  border: 1px solid transparent;
  white-space: nowrap;
}
.share__state.is-on { color: var(--ok); background: var(--ok-soft); border-color: color-mix(in srgb, var(--ok) 32%, transparent); }
.share__state.is-off { color: var(--muted-dim); background: var(--hover); border-color: var(--line-soft); }
.share__link {
  margin-top: 9px;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--muted);
  background: color-mix(in srgb, var(--panel-bg-solid) 60%, transparent);
  border: 1px solid var(--line-soft);
  border-radius: 8px;
  padding: 7px 10px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.share__acts { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 11px; }
.share .dempty { margin-top: 9px; }

/* 权限勾选 */
.chk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 6px 14px; }
.chk {
  display: flex; align-items: center; gap: 8px;
  font-size: 13.5px; color: var(--muted);
  padding: 4px 0; cursor: pointer;
}
.chk:hover { color: var(--text); }
.chk input { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; }

/* 多选弹层 */
.pick-list {
  display: flex; flex-direction: column; gap: 6px;
  max-height: 260px; overflow: auto;
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-sm);
  padding: 8px;
  background: var(--accent-soft);
}
.pick-item {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 9px; border-radius: 8px; cursor: pointer;
  transition: background .14s ease;
}
.pick-item:hover { background: var(--hover); }
.pick-item input { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; }

/* ============================== 抽屉 / 弹窗 ============================== */
.scrim {
  position: fixed; inset: 0;
  background: rgba(0, 0, 0, .55);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  opacity: 0; pointer-events: none;
  transition: .22s ease;
  z-index: 40;
}
.scrim.is-on { opacity: 1; pointer-events: auto; }
.drawer {
  position: fixed;
  top: 10px; right: 10px; bottom: 10px;
  width: min(720px, calc(100% - 20px));
  background: var(--panel-bg);
  backdrop-filter: var(--backdrop);
  -webkit-backdrop-filter: var(--backdrop);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  z-index: 50;
  transform: translateX(calc(100% + 20px));
  transition: transform .3s cubic-bezier(.22,.8,.2,1);
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow);
}
.drawer.is-on { transform: translateX(0); }
.drawer__head {
  padding: 15px 18px;
  border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 12px;
  flex: none;
}
.drawer__head strong { font-family: var(--serif); font-size: 17px; color: var(--text-strong); }
.drawer__body { flex: 1; overflow-y: auto; padding: 18px 20px 40px; }

.modal { position: fixed; inset: 0; z-index: 60; display: flex; align-items: center; justify-content: center; padding: 20px; }
.modal__scrim { position: absolute; inset: 0; background: rgba(0, 0, 0, .58); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); }
.modal__box {
  position: relative;
  background: var(--panel-bg);
  backdrop-filter: var(--backdrop);
  -webkit-backdrop-filter: var(--backdrop);
  width: min(680px, 100%);
  max-height: 88vh;
  overflow: hidden;
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
}
/* 🔴 必须显式声明 background —— 不能只写 padding/border。
   style.css L340 有 `.modal__head { background: var(--surface) }`，
   而 `--surface` 是**客户页的浅色令牌**（#FFFFFF），后台主题没有覆盖它。
   两条规则同为 (0,1,0)，本文件虽后加载，但之前这里**根本没写 background**，
   于是浅色背景照原样生效 → 深色主题下弹窗标题栏变成一块白底，
   上面的浅色标题文字完全看不清（用户截图反馈）。
   现在带 `.modal` 前缀（0,2,0）显式置透明，继承 .modal__box 的主题底色。 */
.modal .modal__head {
  padding: 14px 20px;
  border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 12px;
  flex: none;
  background: transparent;
}
.modal__head strong { font-family: var(--serif); font-size: 16px; color: var(--text-strong); }
.modal__body { flex: 1; overflow-y: auto; padding: 18px 20px 28px; }

/* ============================== 登录 ============================== */
.loginbox { max-width: 420px; margin: 6vh auto 0; }
.tabs {
  display: flex; gap: 4px;
  background: var(--accent-soft);
  border: 1px solid var(--panel-border);
  border-radius: 999px;
  padding: 4px;
  margin-bottom: 18px;
}
.tabs button {
  flex: 1; border: 0; background: transparent;
  padding: 8px; border-radius: 999px;
  cursor: pointer; color: var(--muted);
  font-size: 13.5px; transition: .15s ease;
}
.tabs button.is-on {
  background: var(--panel-bg-solid);
  color: var(--accent);
  font-weight: 600;
  box-shadow: var(--shadow-sm);
}
.stack { display: flex; flex-direction: column; gap: 12px; }

/* ============================== Toast / Spinner ============================== */
.toast {
  position: fixed;
  left: 50%; bottom: 34px;
  transform: translate(-50%, 14px);
  background: var(--panel-bg-solid);
  color: var(--text-strong);
  border: 1px solid var(--panel-border-strong);
  padding: 10px 20px;
  border-radius: 999px;
  font-size: 14px;
  /* 🆕 v1.16.50 第 1 项：灯箱 z-index 是 1300（.st-lb）、图片查看器是 1400（.plb），
     原来 toast 只有 200 —— 在灯箱里点「保存到素材库 / 下载」后成功提示被完全盖住，
     用户以为没生效。这里一次性提到所有浮层之上。 */
  z-index: 9999;
  opacity: 0;
  transition: .24s ease;
  box-shadow: var(--shadow);
  max-width: 86vw;
  text-align: center;
}
.toast.is-in { opacity: 1; transform: translate(-50%, 0); }
.toast--err { background: var(--danger-soft); border-color: var(--danger); color: var(--danger); }
.toast--ok { background: var(--ok-soft); border-color: var(--ok); color: var(--ok); }
/* M3 用：部分成功的中间态（既不是全绿也不是彻底失败） */
.toast--warn { background: var(--warn-soft); border-color: var(--warn); color: var(--warn); }

.spinner {
  display: inline-block;
  width: 14px; height: 14px;
  border: 2px solid var(--accent-soft);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin .7s linear infinite;
  vertical-align: -2px;
  margin-right: 6px;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ============================== 3D 舞台挂载点 ==============================
   预留给「3D 骨架 / 3D 试衣」。现在显示占位提示，接3D 时只需把
   画布 append 到 #stage 即可，无需再动布局。 */
.stage__placeholder {
  position: absolute;
  inset: 0;
  display: none;                 /* 功能上线后由 JS 打开 */
  place-items: center;
  pointer-events: none;
  z-index: 1;
}
.stage__placeholder.is-on { display: grid; }
.stage__hint {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .2em;
  color: var(--muted-dim);
  text-transform: uppercase;
  border: 1px dashed var(--panel-border);
  border-radius: 999px;
  padding: 8px 18px;
  background: var(--panel-bg);
  backdrop-filter: var(--backdrop);
  -webkit-backdrop-filter: var(--backdrop);
}
#stage { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
#stage canvas { display: block; width: 100%; height: 100%; touch-action: none; }

/* ============================== 响应式 ============================== */
@media (max-width: 1080px) {
  :root { --left-w: 218px; }
}

/* 移动端：面板改抽屉，工具条转底部横排（竖排在窄屏太吃高度） */
@media (max-width: 860px) {
  :root { --pad: 8px; }
  .sidebar {
    position: fixed;
    top: 0; left: 0; bottom: 0;
    height: 100%;
    width: 264px;
    border-radius: 0 var(--radius) var(--radius) 0;
    transform: translateX(-100%);
    transition: transform .28s cubic-bezier(.4,0,.2,1);
    box-shadow: var(--shadow);
  }
  .layout.nav-open .sidebar { transform: translateX(0); }
  /* 🔴 v1.16.54 第 9 项：遮罩必须**压在内容区之上**才能接住点击。
     .content 与 .nav-scrim 原来同为 z-index:4，而 content 在 DOM 中更靠后，
     于是整个内容区一直盖在遮罩上面 —— 点右侧空白处的 click 全被 content 吃掉，
     抽屉收不起来。遮罩抬到 6、抽屉抬到 7（仍在 topbar 的 9 之下）。 */
  .nav-scrim { z-index: 6; }
  .layout.nav-open .sidebar { z-index: 7; }
  /* 移动端抽屉靠 .nav-open 驱动，rail（图标栏）折叠态必须整体失效：
     否则从桌面带过来的 left-collapsed 会让抽屉只剩一列图标、点不到二级菜单。 */
  .layout.left-collapsed .sidebar,
  .layout:not(.left-collapsed) .sidebar { width: 264px; flex-basis: 264px; }
  .layout.left-collapsed .content { left: var(--pad); }
  .layout.left-collapsed .sidebar__brand { padding: 15px 16px 13px; justify-content: flex-start; flex-direction: row; gap: 10px; }
  .layout.left-collapsed .sidebar__logo { display: inline; }
  .layout.left-collapsed .sidebar__collapse { display: none; }
  .layout.left-collapsed .sidebar__nav { padding: 12px 10px; align-items: stretch; }
  .layout.left-collapsed .sidebar .menu-label { display: block; }
  .layout.left-collapsed .sidebar .menu-txt,
  .layout.left-collapsed .sidebar .menu-badge,
  .layout.left-collapsed .sidebar .menu-caret,
  .layout.left-collapsed .sidebar__foot,
  /* 折叠态账号区只留头像，但移动端抽屉永远是展开态，
     必须把账号文字放回来，否则「当前账号 / 角色」在手机上全没了 */
  .layout.left-collapsed .sidebar__foot .sidebar__who-main { display: revert; }
  .layout.left-collapsed .sidebar__foot .sidebar__avatar::after { content: none; }
  .layout.left-collapsed .sidebar .menu-item--parent[data-tip]::after { display: none; }
  .layout.left-collapsed .sidebar .subnav__btn.menu-item,
  .layout.left-collapsed .sidebar .menu-item { justify-content: flex-start; gap: 11px; padding: 10px 12px; width: 100%; }
  .layout.left-collapsed .sidebar .menu-group { position: static; }
  .layout.left-collapsed .sidebar .menu-group + .menu-group { border-top: 0; padding-top: 0; margin-top: 0; }
  .layout.left-collapsed .sidebar .menu-sub {
    display: flex;
    position: static;
    left: auto; top: auto;
    min-width: 0;
    padding: 0 0 0 22px;
    background: none; border: 0; box-shadow: none;
  }
  .layout.left-collapsed .sidebar .menu-group:hover .menu-sub { display: flex; }
  .sidebar.is-collapsed { transform: translateX(-100%); opacity: 1; pointer-events: auto; }
  .topbar__menu { display: inline-flex; }
  .topbar__actions .btn { padding: 6px 11px; font-size: 12.5px; }
  .topbar__title { font-size: 15px; }
  /* 窄屏顶栏空间极紧：品牌区只留字母章，标题独占剩余空间。
     否则 brand与 title 会叠在一起（实测「MIRA」压住「问卷记录」）。 */
  .topbar { gap: 10px; padding: 0 6px 0 10px; }
  /* ⚠ brand 必须 flex:none。.brand 有 min-width:0 且默认可收缩，
     414px 下会被压得比 32px 的字母章还窄 → 字母章溢出 brand 盒子、
     直接压在 topbar__title 上（实测重叠）。改为不收缩，
     空间不够时由 title 自己省略号截断。 */
  .brand { gap: 0; flex: 0 0 auto; }
  .brand-text { display: none; }
  .topbar__title { padding-left: 10px; }
  .content {
    left: var(--pad);
    right: var(--pad);
    top: calc(var(--pad) + var(--top-h) + 8px);
    bottom: var(--pad);
  }
  .content { padding-bottom: 16px; }
}

@media (max-width: 640px) {
  .drawer { width: calc(100% - 12px); top: 6px; right: 6px; bottom: 6px; }
  .kv, .pgrid { grid-template-columns: 80px 1fr; }
  .tbl-wrap { overflow-x: auto; }
  .tbl { min-width: 700px; }
  .statgrid { grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); }
  .stat__v { font-size: 23px; }
  .content { padding-bottom: 16px; }
  /* 客户卡在窄屏改为纵向堆叠：操作按钮独占一行，避免挤压 */
  .dcard { flex-wrap: wrap; gap: 10px; padding: 12px; }
  .dcard__side { flex-direction: row; align-items: center; width: 100%; justify-content: space-between; }
  .dcard__swatch { width: 40px; height: 40px; font-size: 16px; }
  .toolbar__label { display: none; }
  /* 超窄屏：只留图标按钮的文字标签，标题独占一行空间 */
  .topbar__actions .btn { padding: 6px 9px; font-size: 12px; }
  .topbar__title { font-size: 14px; }
  .brand-mark { width: 28px; height: 28px; font-size: 13px; }
}

/* 动效降级：尊重系统「减少动态效果」偏好 */
@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
  .spinner { animation: none; border-top-color: var(--accent); }
}


/* ══════════════ 客户档案卡片：信息密度补齐 ══════════════
   ⚠⚠ 改版背景：HUD 改版把客户列表从 6 列表格换成了卡片流，
      但卡片只放了 头像/姓名/手机号/标签 + 右侧一列小字，
      中间空出大片留白，性别、年龄、身高体重、体型、需求、备注全没了。
      旧表格的列是：姓名 / 手机号 / 标签 / 到店次数 / 最近到店 / 操作。
      现在不仅要补回旧字段，还要把「到店记录」里归属客户的关键值
      （体型/场景/预算/来源）显性化 —— 顾问判断客户价值靠的就是这些。

   布局：色卡 | 主区（身份行 + 键值区 + 标签 + 备注）| 数值区 | 操作 */
.dcard--person {
  align-items: stretch;
  gap: 16px;
  padding: 12px 16px 12px 14px;
}

/* 主区纵向居中，数值区右侧对齐 —— 之前 align-items:center 会让多行内容看着散 */
.dcard--person .dcard__main {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
}

.dcard--person .dcard__swatch {
  align-self: center;
}

/* 身份行：姓名 + 性别 + 年龄 + 状态旗标 */
.dcard__sex,
.dcard__age {
  font-size: 10.5px;
  font-family: var(--mono);
  letter-spacing: .04em;
  padding: 1px 7px;
  border-radius: 6px;
  color: var(--muted);
  background: var(--hover);
  border: 1px solid var(--line-soft);
}

.dcard__age { color: var(--info); border-color: color-mix(in srgb, var(--info) 30%, transparent); }

/* 键值区：标签用弱化色，值用正文色，成对出现，扫读友好 */
.dcard__kv {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 8px;
  margin-top: 1px;
}

.dcard__kv-k {
  font-size: 10.5px;
  color: var(--muted-dim);
  font-family: var(--sans);
  letter-spacing: .08em;
}

.dcard__kv-k::after {
  /* 键后面的冒号由 CSS 生成，避免 HTML 里散落文案 */
  content: "：";
  margin-left: -2px;
}

.dcard__kv-v {
  font-size: 12px;
  color: var(--text);
  margin-right: 8px;
}

.dcard__kv-v--num { font-family: var(--mono); letter-spacing: .02em; }

/* 备注：单行截断，全文进 title */
.dcard__note {
  font-size: 11.5px;
  color: var(--muted);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}

/* 数值区：三块固定宽的计数块，右对齐成竖列 */
.dcard__stats {
  flex: none;
  display: grid;
  grid-auto-flow: column;
  gap: 1px;
  align-self: center;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
  border-radius: 9px;
  overflow: hidden;
}

.dstat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  min-width: 62px;
  padding: 6px 8px;
  background: var(--panel-bg);
}

.dstat__k {
  font-size: 10px;
  color: var(--muted-dim);
  letter-spacing: .1em;
}

.dstat__v {
  font-size: 12px;
  color: var(--text-strong);
  font-family: var(--mono);
  white-space: nowrap;
}

.dcard--person .dcard__side {
  align-self: center;
}

/* 空态 / 错误态（原来用 <tr><td colspan> ，卡片流下不合法） */
.dcard-empty {
  padding: 26px 16px;
  text-align: center;
  color: var(--muted);
  font-size: 12.5px;
  background: var(--panel-bg);
  border: 1px dashed var(--panel-border);
  border-radius: var(--radius);
}

/* 窄屏：数值区换行到主区下方，避免挤压正文 */
@media (max-width: 900px) {
  .dcard--person { flex-wrap: wrap; }
  .dcard--person .dcard__main { flex: 1 1 260px; }
  .dcard--person .dcard__stats { order: 3; flex: 1 1 auto; }
  .dcard--person .dcard__side { order: 4; margin-left: auto; }
}

@media (max-width: 640px) {
  .dcard--person { gap: 10px; }
  .dcard--person .dcard__stats { grid-auto-flow: row; grid-template-columns: repeat(3, 1fr); }
  .dstat { min-width: 0; }
}

/* ⚠⚠ 键值必须**成对不可分割**。
   之前键和值是两个平级 span 放在同一个 flex 容器里，
   窄屏换行时会在「键」和「值」之间断开 —— 截图里出现
   「需求：」孤零零占一行、内容掉到下一行且从中间折断。
   解法：每对包进 .dkv（inline-flex，键与值同 nowrap）。 */
.dcard__kv { display: flex; flex-wrap: wrap; gap: 3px 14px; margin-top: 1px; }

.dkv {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  min-width: 0;
}

/* 「需求」是长文本：允许它换行占满整行，但键要吸顶在首行 */
.dkv--wide {
  flex: 1 1 100%;
  align-items: flex-start;
}

/* 键「需求」是两个汉字，被压到只剩一个字宽时浏览器会**逐字竖排**
   （截图里「需」「求：」上下堆叠）。必须 nowrap 锁住。 */
.dkv--wide .dcard__kv-k { padding-top: 1px; white-space: nowrap; flex: none; }

/* 所有键都不许内部折行 */
.dcard__kv-k { white-space: nowrap; flex: none; }

.dkv--wide .dcard__kv-v {
  /* 多行时行距收紧，避免需求行把卡片撑得过高 */
  line-height: 1.5;
  word-break: break-word;
}

/* 短键值（手机/身体）内部不折行 */
.dkv > .dcard__kv-v { white-space: nowrap; }
.dkv--wide > .dcard__kv-v { white-space: normal; }

/* ============================================================
   到店登记弹窗（顾问代填问卷）
   字段多、层级长，用分段（wsec）+ 网格（fgrid）组织，避免一长条表单。
   ⚠️ 这一整块必须放在**所有媒体查询之后**：插到某个 @media 中间
      会把后面的规则全吞进那个断点，窄屏样式直接失效。
   ============================================================ */
.modal__box--wide { width: min(880px, calc(100vw - 32px)); max-height: calc(100vh - 48px); }
.wsec { margin: 0 0 18px; padding-bottom: 16px; border-bottom: 1px solid var(--line-soft); }
.wsec:last-of-type { border-bottom: 0; margin-bottom: 8px; }
.wsec__t {
  display: flex; align-items: center; gap: 8px;
  font-size: 13px; font-weight: 600; color: var(--text-strong);
  margin: 0 0 10px;
}
.wsec__no {
  font-family: var(--mono); font-size: 10.5px;
  color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  border-radius: 4px; padding: 1px 5px; flex: none;
}
.wsec__b { display: flex; flex-direction: column; gap: 12px; }
.wbtns { display: flex; gap: 10px; flex-wrap: wrap; padding-top: 4px; }
.fgrid--wide .f .chiprow { flex-wrap: wrap; }
.fgrid--wide .palette { max-width: 100%; }

/* 问卷卡片上的来源 / 门店标签 */
.dchip--src { border-color: color-mix(in srgb, var(--info) 40%, transparent); color: var(--info); }
.dchip--store { border-color: color-mix(in srgb, var(--accent) 45%, transparent); color: var(--accent); }

@media (max-width: 720px) {
  .store-switch { max-width: 168px; height: 32px; }
  .store-switch__k { display: none; }
  .modal__box--wide { width: calc(100vw - 16px); }
  .fgrid--wide { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
  /* 顶栏在窄屏已经很挤：门店切换只留门店名，隐藏「门店」二字标签与图标 */
  .store-switch { max-width: 132px; padding: 0 8px; gap: 5px; }
  .store-switch__ico { display: none; }
}

/* ============================================================
   门店地图选点（自写迷你 slippy map）
   ⚠ 为什么自写而不用 Leaflet：① 底图必须是国内合规瓦片（高德），
     Leaflet 默认是海外 OSM，换瓦片要改它的 layer 配置；
     ② 引入 140KB 第三方库只为「选点」不值当；
     ③ 纯 img 平铺更容易控制「瓦片加载失败 → 降级手工填地址」的路径。
   ============================================================ */
.stm {
  position: relative;
  width: 100%;
  height: 320px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  /* ⚠️ 之前写死深色渐变：浅色主题下瓦片加载中/缺失时是一块突兀的黑，
     而且（更糟）深色主题下用户看到一片亮色时会误以为「地图坏了」——
     实际那是高德在无数据区返回的米白空白瓦片。背景跟随主题令牌后，
     瓦片没到货时的观感与所在主题一致。 */
  background: var(--panel-bg-solid);
  border: 1px solid var(--panel-border-strong);
  cursor: grab;
  user-select: none;
  touch-action: none;
}
.stm.is-drag { cursor: grabbing; }
.stm-tiles { position: absolute; inset: 0; }
.stm-t {
  position: absolute;
  width: 256px; height: 256px;
  display: block;
  /* 🔴 三重保险拦掉浏览器的「原生图片拖拽」：
     draggable=false（JS 里设）是第一道，这里 -webkit-user-drag + pointer-events 是第二三道。
     漏掉就会出现：按住拖地图时光标下挂一个**灰色半透明幽灵矩形**，
     且 mousemove 被原生拖拽吞掉 → 地图完全不跟手、看起来「点一下就白了」。 */
  -webkit-user-drag: none;
  -khtml-user-drag: none;
  user-select: none;
  pointer-events: none;
}
/* 新瓦片加载中的占位：主题底色 + 细网格纹理。
   没有它，网络慢时用户看到的是一整片突兀的白（浅色主题）
   或黑（深色主题），会误以为「地图坏了」。 */
.stm-t.is-loading {
  background:
    repeating-linear-gradient(0deg, transparent 0 31px, color-mix(in srgb, var(--line) 55%, transparent) 31px 32px),
    repeating-linear-gradient(90deg, transparent 0 31px, color-mix(in srgb, var(--line) 55%, transparent) 31px 32px),
    var(--panel-bg-solid);
}
.stm-pin {
  position: absolute;
  width: 26px; height: 26px;
  margin: -25px 0 0 -13px;   /* 尖端对准真实坐标 */
  border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg);
  background: linear-gradient(140deg, var(--accent), color-mix(in srgb, var(--accent) 55%, #000));
  box-shadow: 0 0 0 2px rgba(0, 0, 0, .45), 0 6px 16px rgba(0, 0, 0, .5);
  pointer-events: none;
}
.stm-pin::after {
  content: '';
  position: absolute; left: 50%; top: 50%;
  width: 7px; height: 7px; margin: -3.5px 0 0 -3.5px;
  border-radius: 50%; background: #1a1206;
}
.stm-ctrls { position: absolute; right: 8px; top: 8px; display: flex; flex-direction: column; gap: 4px; }
.stm__btn {
  width: 28px; height: 28px;
  border-radius: 7px;
  border: 1px solid var(--panel-border-strong);
  background: var(--panel-bg-solid);
  color: var(--text-strong);
  font-size: 15px; line-height: 1;
  cursor: pointer;
  display: grid; place-items: center;
  padding: 0;
}
.stm__btn:hover { border-color: var(--accent); color: var(--accent); }
.stm__badge {
  position: absolute; left: 8px; bottom: 8px;
  padding: 3px 8px;
  border-radius: 6px;
  /* ⚠️ 原来是写死的 rgba(8,12,14,.72)（近黑）+ var(--muted) 文字：
     深色主题下 --muted 是浅灰，能看；切到浅色主题后 --muted 变成深灰，
     压在近黑底上直接糊成一团。改成跟随主题的实底 + 描边。 */
  background: var(--panel-bg-solid);
  border: 1px solid var(--panel-border-strong);
  color: var(--muted);
  font-family: var(--mono); font-size: 10.5px;
  pointer-events: none;
  max-width: calc(100% - 60px);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.stm-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 8px; }

/* 🆕 v1.16.6 R6：门店门头照片上传占位框（横幅比例，与品牌 Logo 同一套交互语言：
   点占位选文件、传后即时预览、右上角黑底白叉清除）。 */
.st-photo { display: flex; align-items: flex-start; gap: 10px; flex-wrap: wrap; }
.st-photo__pv {
  position: relative; width: 200px; height: 120px; border-radius: 10px; padding: 0;
  display: grid; place-items: center; overflow: hidden;
  border: 1px dashed var(--line); background: color-mix(in srgb, var(--panel-bg-solid) 58%, transparent);
  color: var(--muted-dim); cursor: pointer; font: inherit;
  transition: border-color .16s ease, color .16s ease;
}
.st-photo__pv:hover { border-color: var(--accent); color: var(--accent); }
.st-photo__pv.is-filled { border-style: solid; border-color: var(--line-soft); cursor: zoom-in; }
.st-photo__pv.is-filled:hover { border-color: var(--accent); }
/* 🔴🔴 v1.16.13 修复（用户报障 @image#3 前半：门头照预览显示不全）：
   与商品图同一铁律 —— `contain` + 白底，缺的区域白色补齐，不裁切。
   占位框本身就是 200×120 横幅比例，与「建议横图」的上传要求一致。 */
.st-photo__pv img { width: 100%; height: 100%; object-fit: contain; background: #fff; display: block; }
.st-photo__ph { display: flex; flex-direction: column; align-items: center; gap: 4px; font-size: 12px; }
.st-photo__ph i { font-style: normal; font-size: 22px; font-weight: 300; line-height: 1; }
.st-photo__ph em { font-style: normal; }
.st-photo__x {
  position: absolute; top: 3px; right: 3px; z-index: 2;
  width: 22px; height: 22px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(0, 0, 0, .82); color: #fff;
  font-size: 15px; line-height: 1; cursor: pointer; user-select: none;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .35);
  transition: background .14s ease, transform .14s ease;
}
.st-photo__x:hover { background: #000; transform: scale(1.08); }

/* ============================================================
   门店分布图（three.js 中国地图）
   ============================================================ */
.stm3 {
  position: relative;
  width: 100%;
  height: min(560px, 68vh);
  min-height: 380px;
  border-radius: var(--radius);
  overflow: hidden;
  /* ⚠️ 原来写死 #0e1113：浅色主题下 WebGL 还没出首帧时是一整块黑，
     与页面割裂。改跟主题走（与 store-map3d.js 的 PALETTES[theme].bg 一致）。 */
  background: var(--map3d-bg);
  border: 1px solid var(--panel-border-strong);
}
.stm3-canvas { display: block; width: 100%; height: 100%; cursor: grab; }
.stm3-canvas:active { cursor: grabbing; }
.stm3-loading, .stm-fallback {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  padding: 22px;
  text-align: center;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.9;
  background: var(--map3d-bg);
}
.stm3-bubbles { position: absolute; inset: 0; pointer-events: none; }
.stm3-bub {
  position: absolute;
  top: 0; left: 0;
  pointer-events: auto;
  display: flex; flex-direction: column; gap: 1px;
  padding: 5px 9px;
  max-width: 190px;
  border-radius: 8px;
  background: var(--map3d-bub);
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  box-shadow: var(--shadow-sm);
  color: var(--text-strong);
  font-size: 12px;
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
  transition: border-color .15s ease, background .15s ease;
}
.stm3-bub:hover { background: var(--map3d-bub-hover); border-color: var(--accent); }
.stm3-bub b { font-size: 12.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; }
.stm3-bub span {
  font-size: 10.5px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis;
}
.stm3-bub.is-active { border-color: var(--accent); background: var(--map3d-bub-on); }
.stm3-bub.is-active b { color: var(--accent); }
.stm3-bub.is-off { border-color: color-mix(in srgb, var(--muted-dim) 40%, transparent); opacity: .7; }
.dcard--store .dcard__swatch--pin { font-size: 15px; }
.warn { color: var(--warn, #d9a441); }
#st-map-spin.is-on { border-color: var(--accent); color: var(--accent); }

/* ============================================================
   顶栏门店切换器：自绘下拉面板
   ⚠⚠ 为什么不用原生 <select>：
      原生下拉弹层是**操作系统绘制**的（macOS 白底、Win10 蓝底），
      深炭黑主题下就是一个刺眼的蓝白方块，无法与香槟金调性统一，
      而且各系统/各浏览器样式都不一样，改不动。
      → 隐藏原生 select（保留在 DOM 作无障碍回退），自绘 #store-menu。
   ⚠ 必须带全父级前缀 `.topbar .store-switch ...` 覆盖：
      style.css 里后台规则选择器权重更高，裸类名会输给它
      （深色主题下出现旧令牌色的症状）。
   ⚠ 这一整块必须放在**所有媒体查询之后**：插到某个 @media 中间
      会把后续规则吞进断点里。
   ============================================================ */
.topbar .store-switch {
  position: relative;
  display: flex;
  align-items: center;
  flex: 0 1 auto;
  min-width: 0;
  max-width: 250px;
}
.topbar .store-switch__btn {
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  min-width: 0;
  height: 34px;
  padding: 0 10px 0 11px;
  border-radius: 999px;
  background: var(--hover);
  border: 1px solid var(--panel-border-strong);
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
  transition: border-color .15s ease, background .15s ease;
}
.topbar .store-switch__btn:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, var(--hover)); }
.topbar .store-switch__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.topbar .store-switch__btn.is-open { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, var(--hover)); }
.topbar .store-switch__ico { flex: none; color: var(--accent); }
.topbar .store-switch__k {
  flex: none;
  font-size: 11px;
  color: var(--muted-dim);
  font-family: var(--mono);
  letter-spacing: .08em;
}
.topbar .store-switch__name {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-strong);
}
.topbar .store-switch__caret {
  flex: none;
  color: var(--muted);
  transition: transform .18s ease;
}
.topbar .store-switch__btn.is-open .store-switch__caret { transform: rotate(180deg); }

/* 原生 select 只做无障碍/表单回退，完全不可见也不可聚焦 */
.topbar .store-switch__sel {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
  opacity: 0;
  pointer-events: none;
}

.topbar .store-menu {
  position: absolute;
  top: calc(100% + 7px);
  left: 0;
  z-index: 60;
  min-width: 240px;
  max-width: 380px;
  max-height: 320px;
  overflow-y: auto;
  padding: 5px;
  border-radius: 13px;
  background: var(--panel-bg-solid, var(--panel-bg));
  border: 1px solid var(--panel-border-strong);
  box-shadow: 0 16px 40px -12px rgba(0, 0, 0, .62), 0 0 0 1px rgba(255, 255, 255, .025) inset;
  animation: storeMenuIn .13s ease-out;
}
.topbar .store-menu[hidden] { display: none; }
@keyframes storeMenuIn {
  from { opacity: 0; transform: translateY(-5px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .topbar .store-menu { animation: none; }
}
.topbar .store-menu__item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 10px;
  border: 0;
  border-radius: 9px;
  background: transparent;
  color: var(--text);
  font-family: inherit;
  font-size: 12.5px;
  text-align: left;
  cursor: pointer;
  transition: background .12s ease;
}
.topbar .store-menu__item:hover { background: var(--hover); }
.topbar .store-menu__item:focus-visible { outline: 2px solid var(--accent); outline-offset: -1px; }
.topbar .store-menu__nm { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.topbar .store-menu__cd {
  flex: none;
  padding: 1px 6px;
  border-radius: 6px;
  background: var(--hover);
  border: 1px solid var(--panel-border);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .05em;
  color: var(--muted-dim);
}
.topbar .store-menu__ck { flex: none; margin-left: auto; color: var(--accent); opacity: 0; }
.topbar .store-menu__item.is-on { background: color-mix(in srgb, var(--accent) 13%, transparent); color: var(--text-strong); font-weight: 600; }
.topbar .store-menu__item.is-on .store-menu__ck { opacity: 1; }
.topbar .store-menu__item.is-on .store-menu__cd { border-color: color-mix(in srgb, var(--accent) 40%, transparent); }

/* 移动端：面板贴右对齐，避免溢出屏幕 */
@media (max-width: 640px) {
  .topbar .store-switch { max-width: 46vw; }
  .topbar .store-menu { min-width: 176px; max-width: 62vw; }
  .topbar .store-switch__k { display: none; }
}

/* ============================================================
   高德 Web服务 Key 配置（2026-10-10）
   ⚠ 这一整块必须放在**所有媒体查询之后**：插到某个 @media 中间，
     后续规则会被吞进断点，深色主题下就会出现旧令牌色（已踩）。
   ============================================================ */
.st-keybar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 8px 14px;
  border-bottom: 1px solid var(--panel-border);
  background: var(--hover);
}
.st-keybar .dot {
  display: inline-block;
  width: 7px; height: 7px;
  border-radius: 50%;
  margin-right: 7px;
  vertical-align: 1px;
}
.st-keybar .dot--ok { background: #4E9A6B; }
.st-keybar .dot--warn { background: var(--warn, #d9a441); }

/* Key 按钮：未配置时用强调色勾一下，避免顾问以为不需要 Key 就一直不填 */
.btn--key {
  border-color: color-mix(in srgb, var(--accent) 42%, transparent);
  color: var(--accent);
  font-weight: 600;
}
.btn--key.is-on {
  border-color: color-mix(in srgb, var(--accent) 26%, transparent);
  color: var(--muted);
  font-weight: 500;
  opacity: .9;
}
.btn--key.is-on:hover { color: var(--accent); border-color: var(--accent); }

/* 表单提示行里的文字链接 */
.lnk {
  border: 0;
  background: none;
  padding: 0 0 0 6px;
  color: var(--accent);
  font-size: inherit;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.lnk:hover { filter: brightness(1.12); }

#amapkey-state code {
  font-family: var(--mono);
  font-size: 11.5px;
  padding: 1px 5px;
  border-radius: 5px;
  background: var(--hover);
  border: 1px solid var(--panel-border);
}
#amapkey-state .ok { color: #4E9A6B; }
#amapkey-state .warn { color: var(--warn, #d9a441); }
#mapkey-modal .field__hint a { color: var(--accent); }

/* 底图整体取不到时的兜底提示（不能只留一片黑让顾问猜） */
.stm-warn {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  max-width: 78%;
  padding: 8px 12px;
  border-radius: 10px;
  background: rgba(8, 12, 14, .88);
  border: 1px solid var(--panel-border-strong);
  color: var(--text);
  font-size: 12px;
  line-height: 1.6;
  text-align: center;
  pointer-events: none;
}
/* 加载失败的瓦片：留个占位色，别让已失败的分块被反复复用时闪白 */
.stm-t.is-bad { background: #16211f; }

/* ============================================================
   问卷操作区（编辑补填 / 建立客户档案）
   ============================================================ */
.dacts {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--panel-border);
}
.dacts .dacts__n { margin-left: 2px; }
.dhero { display: flex; gap: 12px; align-items: flex-start; flex-wrap: wrap; }
.dhero__acts { flex: 1 1 100%; }

/* 编辑弹窗：标签在上、控件在下（比左右挤压更好点） */
.subedit__ctl { min-width: 0; }
.subedit__ctl .input, .subedit__ctl .textarea { width: 100%; }
.subedit__ctl .field__hint { margin-top: 3px; }
#subedit-msg:empty { display: none; }
.fgrid .f .req { color: var(--accent); }

/* ============================================================
   人体尺寸线数值可读性补丁
   ⚠️ SVG 字号随 viewBox 等比缩放：双视图并排时每张图只有单视图一半宽，
      21px 的标注文字实际渲染出来只有 ~11px，数值几乎看不清。
      双视图下放大字号补偿，单视图保持原尺寸。
   ⚠️ 这一块必须放在**所有媒体查询之后**（第 1404 行放在中间会被
      后续规则吞进断点，深色主题下退回旧值 —— 已踩过一次）。
   ============================================================ */
.bf-dual .bf-svg .bf-t { font-size: 33px; stroke-width: 5px; }
.bf-dual .bf-svg .bf-guide line { stroke-width: 1.6; }
/* ⚠️ 端点半径 r 是 SVG **几何属性**，CSS 改不了（写进 CSS 是无效声明）。
   要放大只能改属性，见 body-figure.js 里 gline/sg 的 r 参数。 */
/* 窄屏双视图并排时图更小，再补一档 */
@media (max-width: 720px) {
  .bf-dual .bf-svg .bf-t { font-size: 40px; }
}

/* ============================================================
   通用主题弹窗（uiDialog / uiConfirm / uiPrompt）
   用途：替代 window.confirm / window.prompt —— 原生弹框由浏览器绘制，
        不跟随页面主题，深色后台里会跳出一个系统白框。
   ⚠️ 这一块必须放在**所有媒体查询之后**（项目铁律），否则会被断点吞掉。
   ============================================================ */
/* 抽屉 50 / 常规弹窗 60 —— 通用确认框要能叠在它们之上（例如从弹窗里再触发确认） */
.ui-dialog { z-index: 90; }
.uid-text {
  font-size: 13.5px;
  line-height: 1.9;
  color: var(--text);
  /* 文案里的 \n\n 直接换行呈现：比拼 <br> 安全，用户数据不会变成 HTML */
  white-space: pre-line;
}
.uid-acts { display: flex; gap: 10px; justify-content: flex-end; margin-top: 18px; }
.uid-msg { font-size: 12.5px; line-height: 1.7; color: var(--danger); margin-top: 8px; }
.uid-msg:empty { display: none; }

/* 危险操作按钮（删除 / 停用 / 覆盖档案）。
   ⚠️ 必须放在 .btn 系列之后：同为 (0,1,0)，靠源码顺序取胜。 */
.btn--danger {
  border: 1px solid color-mix(in srgb, var(--danger) 45%, transparent);
  background: var(--danger-soft);
  color: var(--danger);
}
.btn--danger:hover {
  border-color: var(--danger);
  background: color-mix(in srgb, var(--danger) 22%, transparent);
}

/* ============================================================
   门店分布图 · 视角切换 + 城市视角（高德瓦片 + 门店标记）
   ⚠️ 这一块必须放在**所有媒体查询之后**（项目铁律），否则会被断点吞掉。
   ============================================================ */

/* 分段控件（中国视角 / 城市视角）。
   用 display:inline-flex 挂在 .sec-head 里 —— .sec-head 是 baseline 对齐的 flex，
   外层再套一层 inline-flex 才不会把按钮拉到标题的基线上歪掉。 */
.seg {
  display: inline-flex;
  align-items: stretch;
  padding: 2px;
  gap: 2px;
  border-radius: 9px;
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
}
.seg__btn {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 12.5px;
  line-height: 1;
  padding: 6px 12px;
  border-radius: 7px;
  cursor: pointer;
  white-space: nowrap;
  transition: background .15s ease, color .15s ease;
}
.seg__btn:hover { color: var(--text-strong); }
.seg__btn.is-on {
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
}

/* 城市视角：左侧地图 + 右侧门店列表。窄屏自动改成上下堆叠。 */
.dz-wrap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 12px;
  align-items: start;
}
/* 分布图要比「添加门店」的选点框高不少，不然几只标记就挤成一团 */
.stm--dist { height: min(560px, 66vh); min-height: 360px; cursor: grab; }
.stm--dist.is-drag { cursor: grabbing; }

.dz-side {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}
.dz-cities { display: flex; flex-wrap: wrap; gap: 6px; }
.dz-cities .chip { font-size: 11.5px; padding: 3px 9px; }

.dz-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: min(470px, 56vh);
  overflow: auto;
}
.dz-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 11px;
  border-radius: 9px;
  border: 1px solid var(--panel-border);
  background: var(--panel-bg);
  color: var(--text);
  text-align: left;
  cursor: pointer;
  font: inherit;
  transition: border-color .15s ease, background .15s ease;
}
.dz-item:hover { border-color: var(--accent); background: var(--hover); }
.dz-item.is-active {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
.dz-item.is-dim { opacity: .55; }
.dz-item__n { font-size: 13px; font-weight: 600; color: var(--text-strong); }
.dz-item__a {
  font-size: 11.5px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dz-item__g { font-size: 10.5px; color: var(--muted-dim); font-family: var(--mono); }

/* 门店标记：一层容器 + 若干按钮式标记。
   ⚠️ 容器 pointer-events:none，只有标记本身可点 ——
      否则标记层会盖在地图上，把拖动平移整个吃掉。 */
.stm-marks { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.stm-mk {
  position: absolute;
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 5px;
  max-width: 168px;
  padding: 3px 9px 3px 5px;
  transform: translate(-50%, -100%);
  border-radius: 8px;
  border: 1px solid color-mix(in srgb, var(--accent) 50%, transparent);
  background: color-mix(in srgb, var(--panel-bg-solid) 92%, transparent);
  color: var(--text-strong);
  font: inherit;
  font-size: 11.5px;
  line-height: 1.4;
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .38);
  transition: border-color .15s ease, background .15s ease;
}
.stm-mk i {
  flex: none;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 30%, transparent);
}
.stm-mk b { font-weight: 500; overflow: hidden; text-overflow: ellipsis; }
.stm-mk:hover { border-color: var(--accent); z-index: 2; }
.stm-mk.is-active {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 18%, var(--panel-bg-solid));
}
.stm-mk.is-active b { color: var(--accent); font-weight: 600; }
.stm-mk.is-off { opacity: .62; }
.stm-mk.is-off i { background: var(--muted-dim); box-shadow: none; }

@media (max-width: 900px) {
  .dz-wrap { grid-template-columns: minmax(0, 1fr); }
  .dz-list { max-height: 300px; }
}

/* ==================== 树形权限编辑器（2026-10-11） ==================== */
.perm-tree {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: color-mix(in srgb, var(--panel-bg-solid) 55%, transparent);
}
.perm-tree .pt-group { display: flex; flex-direction: column; gap: 6px; }
.perm-tree .pt-l1 { font-size: 13.5px; }
.perm-tree .pt-l1 b { font-weight: 600; }
.perm-tree .pt-kids {
  display: flex; flex-direction: column; gap: 6px;
  margin-left: 20px; padding-left: 12px;
  border-left: 2px solid var(--line);
}
.perm-tree .pt-leaf { display: flex; flex-direction: column; gap: 4px; }
.perm-tree .pt-l2 { font-size: 13px; }
.perm-tree .pt-acts {
  display: flex; flex-wrap: wrap; gap: 6px 16px;
  margin-left: 20px; padding: 4px 0 2px;
}
.perm-tree .pt-act { font-size: 12.5px; color: var(--muted); }
.perm-tree .chk { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; }

/* ==================== 表单分区小标题（顾问表单：员工信息 / 登录账号 / 权限与归属） ==================== */
.sec-sub {
  margin: 20px 0 10px; padding-top: 14px;
  border-top: 1px dashed var(--line);
  font-size: 12px; font-weight: 700; letter-spacing: .06em;
  color: var(--muted);
}

/* ==================== 门店「查看员工」弹层 ==================== */
.staff-list { display: flex; flex-direction: column; gap: 8px; max-height: 340px; overflow: auto; }
.staff-row {
  display: flex; flex-direction: column; gap: 2px;
  padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 8px;
  background: color-mix(in srgb, var(--panel-bg-solid) 55%, transparent);
}

/* ==================== 商品 SKU 库 ==================== */

/* 多选芯片组（颜色 / 场合 / 季节 / 身形 / 修饰点） */
.chipset { display: flex; flex-wrap: wrap; gap: 6px; }
.chipset .chip { display: inline-flex; align-items: center; gap: 5px; }
/* 色号圆点：给颜色 chip 一个真实色块，避免只靠文字分不清「焦糖」和「驼色」 */
.chip i, .dchip--color i {
  width: 11px; height: 11px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--ink) 18%, transparent);
  flex: 0 0 auto; display: inline-block;
}
.dchip--color { display: inline-flex; align-items: center; gap: 5px; }
.dchip--warn { border-color: color-mix(in srgb, var(--warn) 45%, transparent); color: var(--warn); }

/* 卡片主图（商品图走 signedUrl，占位用默认头像图） */
.dcard__swatch--img {
  object-fit: cover; padding: 0;
  background: color-mix(in srgb, var(--line) 40%, transparent);
}

/* 颜色 / 身形 / 场合 展示行 */
.sku-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.sku-kvline { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }

/* 规格矩阵：行=颜色，列=尺码 */
.vmx { overflow: auto; max-height: 320px; border: 1px solid var(--line); border-radius: 10px; }
/* 🔴 v1.16.54 第 8 项③ 之一：**取消 min-width: 480px**。
   台账里很多款只有一个「均码」，2 列内容 150px 不到，被 480px 的硬底撑出
   一段假的横向滚动 —— 用户原话「若尺码只有一个均码，按理不应该可以左右滑动了」。
   改成 min-width:0 + 单元格自身 min-width：列少时铺满容器不出滚动条，
   列多（XS~XXXL）时自然宽度超标才出滚动条。 */
.tbl--vmx { min-width: 0; width: 100%; }
.tbl--vmx th, .tbl--vmx td { text-align: center; padding: 6px 8px; font-size: 12px; min-width: 58px; }
/* 🔴 v1.16.54 第 8 项③ 之二：**颜色列固定**。
   旧选择器写的是 `tbody td:first-child`，而台账的颜色单元格是
   `<th class="vmx__color">`（第一列是行表头，不是 td）—— 规则从来没命中，
   横拖时颜色列跟着一起滚走。同时必须补 background，否则 sticky 元素的
   底层内容会透出来（这是 sticky 表格最经典的坑）。 */
.tbl--vmx thead th:first-child,
.tbl--vmx tbody tr > :first-child {
  text-align: left; position: sticky; left: 0; z-index: 2;
  background: var(--panel-bg-solid);
  box-shadow: 1px 0 0 var(--line-soft);
}
.tbl--vmx thead th:first-child { z-index: 3; }
.tbl--vmx td.is-out { color: var(--muted); opacity: .55; }
/* 矩阵里的库存输入框：窄、居中、无边框感 */
.vminput {
  width: 100%; max-width: 62px; text-align: center;
  padding: 3px 4px; font-size: 12px;
  border: 1px solid var(--line); border-radius: 6px;
  background: transparent; color: inherit;
}
/* 🆕 v1.16.4 R7：规格矩阵勾选框（勾 = 该颜色×尺码 SKU 在售） */
.mxchk { width: 15px; height: 15px; accent-color: var(--accent, #8a7a66); cursor: pointer; vertical-align: middle; }
.mxrow { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; }
.cdot {
  display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 5px;
  border: 1px solid color-mix(in srgb, var(--ink) 18%, transparent);
}

/* 图片素材网格 */
.mgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); gap: 10px; }
.mcell {
  margin: 0; padding: 6px;
  border: 1px solid var(--line); border-radius: 10px;
  background: color-mix(in srgb, var(--panel-bg-solid) 45%, transparent);
}
.mcell.is-primary { border-color: var(--accent); box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 45%, transparent); }
/* 🆕 v1.16.6 R7：详情抽屉商品图同样完整显示（contain + 白底），不裁切。
   🆕 v1.16.6 R3-4：主图 / 副图标题居中（旧版靠左，用户要求居中）。 */
.mcell img { width: 100%; height: 96px; object-fit: contain; background: #fff; border-radius: 6px; display: block; }
.mcell figcaption { font-size: 11px; color: var(--muted); margin-top: 5px; text-align: center; }
.mcell__acts { display: flex; gap: 5px; margin-top: 6px; flex-wrap: wrap; }
/* 🆕 v1.16.4 R12：详情抽屉素材格子化 —— 右上角删除图标 + 空位上传占位 */
.mcell { position: relative; }
.mcell__x {
  position: absolute; top: 5px; right: 5px; width: 20px; height: 20px;
  border: none; border-radius: 50%; cursor: pointer; padding: 0;
  background: color-mix(in srgb, var(--danger, #c0392b) 82%, black);
  color: #fff; font-size: 13px; line-height: 20px;
}
.mcell__x:hover { filter: brightness(1.15); }
.mcell--add {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  min-height: 120px; border: 1px dashed var(--line); border-radius: 8px;
  background: color-mix(in srgb, var(--panel-bg-solid) 45%, transparent);
  color: var(--muted); cursor: pointer; padding: 8px;
}
.mcell--add:hover { border-color: var(--accent); color: var(--accent); }
.mcell--add span { font-size: 22px; line-height: 1; }
.mcell--add em { font-style: normal; font-size: 11px; }
.mcell--ro { cursor: default; opacity: .55; }
.mcell--ro:hover { border-color: var(--line); color: var(--muted); }
.mcell img { cursor: zoom-in; }
/* 🆕 v1.16.6 R3：副图生成中的占位格 + 下方「停止生成」按钮。
   生成中禁止点格子上传（避免与生成结果打架），但仍可点停止。 */
.mcell--add.is-generating { cursor: default; border-style: dashed; border-color: var(--accent); color: var(--accent); }
.mcell--add.is-generating:hover { border-color: var(--accent); }
.mcell__stop {
  margin-top: 6px; padding: 2px 10px; font-size: 11px; line-height: 1.7;
  border: 1px solid color-mix(in srgb, var(--danger, #c0392b) 45%, transparent);
  border-radius: 20px; cursor: pointer;
  background: color-mix(in srgb, var(--danger, #c0392b) 12%, transparent);
  color: var(--danger, #c0392b); font-family: inherit;
}
.mcell__stop:hover { background: var(--danger, #c0392b); color: #fff; }

/* 版本记录行 */
.ver-row {
  display: flex; flex-direction: column; gap: 5px; align-items: flex-start;
  padding: 9px 10px; margin-bottom: 8px;
  border: 1px solid var(--line); border-radius: 8px;
  background: color-mix(in srgb, var(--panel-bg-solid) 50%, transparent);
}

/* 品类树 */
.ctree { border: 1px solid var(--line); border-radius: 10px; padding: 6px 8px; }
.ctree__node { margin-bottom: 8px; }
.ctree__row {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 8px; border-radius: 6px; font-size: 13px;
}
.ctree__row span:first-child { flex: 1; }
.ctree__row--l1 { font-weight: 700; background: color-mix(in srgb, var(--line) 30%, transparent); }
.ctree__row--l2 { padding-left: 18px; cursor: pointer; }
.ctree__row--l2:hover { background: var(--hover); }
.ctree__row--l3 { padding-left: 34px; }
.ctree__caret { display: inline-block; width: 14px; font-style: normal; color: var(--muted); }
.ctree__caret.is-leaf { opacity: .4; }
.ctree__kids { border-left: 1px dashed var(--line); margin-left: 20px; }

/* 色卡 */
.ccard { display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: 8px; }
.ccard__i {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 7px 4px; border: 1px solid var(--line); border-radius: 8px;
  font-size: 11px; color: var(--muted);
}
.ccard__i i {
  width: 100%; height: 34px; border-radius: 5px;
  border: 1px solid color-mix(in srgb, var(--ink) 15%, transparent);
}
.ccard__i em { font-style: normal; }
/* 🆕 v1.16.4 R3：色卡分组小标题 + 自定义色删除角标 */
.pal-cap { margin: 10px 0 4px; }
/* 🆕 v1.16.6 R2：删除角标从「淡红底红叉」改成「黑底白叉」——
   旧版 18px 半透明红底在浅色卡上几乎看不见（用户反馈「看不清」）。
   现在 20px、纯黑底、白色 ×、带一圈浅描边，深色/浅色主题下都醒目。 */
.ccard__x {
  position: absolute; top: 3px; right: 3px; width: 20px; height: 20px;
  border: 1px solid rgba(255, 255, 255, .35); border-radius: 50%; cursor: pointer;
  background: rgba(0, 0, 0, .88);
  color: #fff; font-size: 14px; line-height: 1; padding: 0;
  display: grid; place-items: center;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .4);
  transition: background .14s ease, transform .14s ease;
}
.ccard__x:hover { background: #000; transform: scale(1.1); }
/* 🆕 v1.16.6 R2：色名输入框「重名 / 重色值」的提示方式 —— 由底部淡色 toast 改为输入框本身红框。
   旧版只弹一个半透明 toast，颜色淡、位置远，用户经常没看见。 */
.input.is-bad { border-color: var(--danger, #c0392b) !important; box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger, #c0392b) 16%, transparent); }
.pal-err { color: var(--danger, #c0392b); font-size: 12px; margin: 6px 0 0; }
.palette__cap { width: 100%; flex: none; font-size: 11px; color: var(--muted); margin: 4px 0 2px; }

/* AI 调用台 */
.aiform { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.aick { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; }
.aihits { display: flex; flex-direction: column; gap: 8px; }
.aihit {
  padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px;
  background: color-mix(in srgb, var(--panel-bg-solid) 45%, transparent);
  cursor: pointer;
}
.aihit:hover { border-color: var(--accent); }
.aihit__top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.aihit__score {
  font-size: 11px; padding: 1px 8px; border-radius: 999px;
  background: var(--accent); color: var(--accent-ink); font-weight: 700;
}
.aihit__why { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 7px; }
/* 命中理由 chip：不可点，只是说明，所以用虚线边框与交互 chip 区分开 */
.chip--why {
  cursor: default; font-size: 11px; padding: 2px 9px;
  border-style: dashed; border-color: color-mix(in srgb, var(--accent) 40%, transparent);
}
.chip--why:hover { border-color: color-mix(in srgb, var(--accent) 40%, transparent); color: inherit; }

/* ============================================================
   顾问卡片 / 门店卡片（2026-10-12）
   背景：`.c-cards` `.c-card*` `.c-ava*` 当初只写了 DOM、漏了样式，
         <img> 便按 SVG 固有尺寸铺开（实测 1148×1531），把整页撑成
         一大片黑；同时默认头像因颜色值双重编码渲染成纯黑。
         这里补齐全部样式，并统一成「一行多张的卡片」形态。
   ============================================================ */

/* ---- 头像基础：填满容器并裁切（表格/卡片各自覆盖尺寸） ---- */
.c-ava {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 22%;      /* 人像脸部偏上，裁切时不切掉脸 */
  background: var(--bg-soft);
}
/* 表单里的头像预览：3:4，与「建议 3:4 半身职业照」的提示一致 */
.c-ava--big {
  width: 132px;
  height: 176px;
  border-radius: 12px;
  border: 1px solid var(--panel-border);
}
/* 表格单元格里的头像：固定小方图，不许撑高表格行 */
.tbl .c-ava {
  width: 34px;
  height: 34px;
  border-radius: 9px;
  border: 1px solid var(--panel-border);
}

/* ---- 顾问卡片：上图（头像媒体区）下文（信息区），一行多张 ---- */
.c-cards {
  display: grid;
  /* auto-fit：人数少时卡片自动摊开铺满，不会右侧留一排空轨道 */
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px;
}
.c-card {
  display: flex;
  flex-direction: column;
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  overflow: hidden;              /* 让媒体区贴着圆角走 */
  backdrop-filter: var(--backdrop);
  -webkit-backdrop-filter: var(--backdrop);
  transition: border-color .16s ease, transform .16s ease, box-shadow .16s ease;
}
.c-card:hover {
  border-color: var(--panel-border-strong);
  transform: translateY(-2px);
  box-shadow: var(--shadow-sm);
}
.c-card--owner { border-color: color-mix(in srgb, var(--accent) 42%, transparent); }

.c-card__ava {
  position: relative;
  aspect-ratio: 4 / 5;           /* 媒体区固定比例，卡片高度才可控 */
  overflow: hidden;
  background: linear-gradient(160deg, var(--bg-soft), color-mix(in srgb, var(--bg-soft) 72%, var(--panel-border)));
}
.c-card__ava .c-ava { position: absolute; inset: 0; }

/* 无头像时：淡淡的底色 + 居中圆形色块写姓氏首字。
   直接铺满 4:5 的实心色块会显得很"重"，做成徽章形态更轻盈。 */
.c-card__ini {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: linear-gradient(165deg, color-mix(in srgb, var(--bg-soft) 42%, transparent), transparent 70%);
}
.c-card__ini b {
  width: 92px;
  height: 92px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-family: var(--serif);
  font-size: 38px;
  font-weight: 600;
  line-height: 1;
  color: hsl(var(--h) 30% 92%);
  background: linear-gradient(155deg, hsl(var(--h) 26% 46%), hsl(var(--h) 22% 30%));
  box-shadow: inset 0 0 0 1px hsl(var(--h) 34% 66% / .30);
}

/* 角色徽标：右上角压角（类比商品卡片的「在售」角标） */
.c-card__role {
  position: absolute;
  top: 10px;
  right: 10px;
  font-size: 10.5px;
  font-family: var(--mono);
  letter-spacing: .06em;
  padding: 2px 9px;
  border-radius: 999px;
  color: var(--text);
  background: color-mix(in srgb, var(--panel-bg-solid) 78%, transparent);
  border: 1px solid var(--panel-border);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.c-card__role.is-owner {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: transparent;
}

.c-card__info { padding: 11px 13px 2px; }
.c-card__head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.c-card__name { font-family: var(--serif); font-size: 15px; font-weight: 600; color: var(--text-strong); }
.c-card__code { font-family: var(--mono); font-size: 10.5px; color: var(--muted-dim); letter-spacing: .05em; }
.c-card__sub { font-size: 11.5px; color: var(--muted); margin-top: 3px; }
.c-card__meta { display: flex; flex-direction: column; gap: 4px; margin-top: 9px; }
.c-card__mi { display: flex; align-items: baseline; gap: 7px; font-size: 12px; min-width: 0; }
.c-card__mi i {
  flex: none;
  width: 30px;
  font-style: normal;
  font-size: 10.5px;
  color: var(--muted-dim);
}
.c-card__mi em {
  font-style: normal;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 按钮沉底：同排卡片等高时按钮对齐在同一基线 */
.c-card__acts {
  display: flex;
  gap: 7px;
  padding: 10px 13px;
  margin-top: auto;
  border-top: 1px solid var(--line-soft);
}

/* ---- 门店卡片：一行多张的长方形卡片，卡片内三段分区 ---- */
.scards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 14px;
}
.scard {
  display: flex;
  flex-direction: column;
  padding: 14px 15px 13px;
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  backdrop-filter: var(--backdrop);
  -webkit-backdrop-filter: var(--backdrop);
  transition: border-color .16s ease, transform .16s ease, box-shadow .16s ease;
}
.scard:hover {
  border-color: var(--panel-border-strong);
  transform: translateY(-2px);
  box-shadow: var(--shadow-sm);
}
.scard--off { opacity: .74; }

/* 🆕 v1.16.6 R6：卡片头改为「缩略图 + 名称/地址 + 编号 + 状态角标」，
   所以 align-items 从 baseline 改 center（缩略图与文字基线对齐会错位）。
   🔴🔴 v1.16.14 修复（用户报障：门头照把门店名称和地址挤得换行）：
   旧值 `flex-wrap: wrap` 让头部在空间不足时**折行**——实测 360px 宽的卡片里
   头部被折成三行（缩略图一行 / 名称+地址一行 / 编号+角标一行），头部高达 126px，
   视觉上就是「门头照把名称地址挤得换行」。
   现改 `flex-wrap: nowrap`：三块**恒定同一行**，空间不足时只让中间的
   名称/地址块收缩（见 .scard__idwrap 的 flex:1 1 0），地址超长显示省略号。
   ⚠️ nowrap 下必须保证「不可收缩块」（缩略图/编号/角标）都有 flex:none，
      否则它们也会被压扁。 */
.scard__head { display: flex; align-items: center; gap: 10px; flex-wrap: nowrap; }
.scard__name {
  font-family: var(--serif); font-size: 15px; font-weight: 600; color: var(--text-strong);
  /* 🔴 v1.16.14：超长门店名收口为省略号，不再顶破头部（nowrap 下必须能裁） */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.scard__code {
  font-family: var(--mono); font-size: 10.5px; color: var(--muted-dim); letter-spacing: .05em;
  flex: none;   /* 🔴 v1.16.14：编号是短固定串，nowrap 下不允许被压扁 */
}
.scard__flags { margin-left: auto; display: inline-flex; gap: 6px; flex: none; }
/* 🆕 v1.16.6 R6：门店门头照片缩略图（无照片时显示首字色块）
   🔴🔴 v1.16.13 修复（用户报障 @image#3 后半：缩略图与门头照比例不一致）：
   门头照上传框是 **200×120（5:3 横幅）**，而这里旧值是 48×48 正方形 ——
   同一张横图在列表里被压成方块，用户看着「不是同一张图」。
   现改为与上传框**同比例缩小**：宽 64px、高按 5:3 = 38.4 → 取 39px，
   `contain` + 白底（横图完整显示；竖图也不会被裁，只是左右留白）。
   ⚠️ 宽高比必须与 `.st-photo__pv`（200/120）保持一致，改一处必须改另一处。 */
.scard__thumb {
  flex: none; width: 64px; height: 38px; border-radius: 8px; overflow: hidden;
  display: grid; place-items: center;
  border: 1px solid var(--line-soft);
  background: #fff;
}
.scard__thumb img { width: 100%; height: 100%; object-fit: contain; display: block; }
.scard__thumb--ph {
  font-family: var(--serif); font-weight: 700; font-size: 19px;
  background: linear-gradient(140deg, var(--accent), color-mix(in srgb, var(--accent) 55%, #000));
  color: var(--accent-ink); border-color: transparent;
}
/* 名称 + 地址竖排（地址从原来的独立行收进头部，紧贴名称下方）
   🔴🔴 v1.16.14 修复：`flex: 1 1 auto` → `flex: 1 1 0`。
   `basis:auto` 时 flex 的收缩基准是**内容固有宽度**——门店名/地址越长，
   这块的「理想宽度」越大，nowrap 下就会把右侧的编号与状态角标顶出去。
   改成 `basis:0` 后它只按**剩余空间**分配，永远可被压到 0，
   真正的超长内容由内部 `overflow:hidden` 收口成省略号。
   同时补 `overflow: hidden`（块自身裁剪，配合 min-width:0 双保险）。 */
.scard__idwrap {
  min-width: 0; overflow: hidden;
  display: flex; flex-direction: column; gap: 2px; flex: 1 1 0;
}
/* 🔴 v1.16.14：地址由 `display:flex` 改 **block**。
   旧写法 flex 容器里直接放「📍 + 文本」，📍 与文本是两个匿名 flex item，
   文本节点的 text-overflow:ellipsis 不生效（只能硬换行或溢出）。
   改 block 后图标用 inline-block 内联，超长地址正确截断显示省略号。 */
.scard__addr-inline {
  display: block;
  font-size: 12px; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.scard__addr-inline .scard__pin {
  font-size: 11px; display: inline-block; margin-right: 4px;
}
.scard__flag {
  font-size: 10.5px;
  font-family: var(--mono);
  letter-spacing: .06em;
  padding: 1px 8px;
  border-radius: 999px;
  border: 1px solid transparent;
  white-space: nowrap;
}
.scard__flag.ok { color: var(--ok); background: var(--ok-soft); border-color: color-mix(in srgb, var(--ok) 34%, transparent); }
.scard__flag.off { color: var(--danger); background: var(--danger-soft); border-color: color-mix(in srgb, var(--danger) 34%, transparent); }
.scard__flag.wait { color: var(--warn); background: var(--warn-soft); border-color: color-mix(in srgb, var(--warn) 34%, transparent); }

.scard__addr {
  display: flex;
  gap: 6px;
  align-items: flex-start;
  margin-top: 10px;
  padding-bottom: 11px;
  border-bottom: 1px solid var(--line-soft);
  font-size: 12.5px;
  color: var(--text);
  line-height: 1.6;
}
.scard__pin { flex: none; font-size: 12px; opacity: .85; }

/* 等宽列：标签与取值上下对齐，不会因内容长短而挤成一团 */
.scard__stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px 14px;
  padding: 11px 0;
}
.scard__stat { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.scard__stat i { font-style: normal; font-size: 10.5px; color: var(--muted-dim); }
.scard__stat b {
  max-width: 170px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-strong);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.scard__note {
  margin: -3px 0 9px;
  font-size: 11.5px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.scard__acts {
  display: flex;
  gap: 7px;
  flex-wrap: wrap;
  margin-top: auto;
  padding-top: 11px;
  border-top: 1px solid var(--line-soft);
}

/* ---- 卡片流的窄屏收拢（放在全部 @media 之后，保证覆盖生效） ---- */
@media (max-width: 860px) {
  .c-cards { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 12px; }
  .scards { grid-template-columns: 1fr; gap: 11px; }
}
@media (max-width: 560px) {
  .c-cards { grid-template-columns: 1fr; }
}

/* ---------- 品类树：行内操作按钮 ----------
   按钮平时藏起来（一行三个按钮 × 30 行会把树撑得很吵），hover 才显。
   ⚠️ 触摸设备没有 hover，必须用 @media (hover: none) 让它们常显，
      否则手机上永远点不到「编辑 / 删除」。 */
.ctree__label { flex: 1; display: flex; align-items: center; gap: 8px; min-width: 0; }
.ctree__label > span:first-child { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ctree__acts { display: flex; gap: 4px; flex: none; opacity: 0; transition: opacity .15s; }
.ctree__row:hover .ctree__acts, .ctree__row:focus-within .ctree__acts { opacity: 1; }
@media (hover: none) { .ctree__acts { opacity: 1; } }

.mini {
  border: 1px solid var(--line); background: transparent; color: var(--muted);
  font: inherit; font-size: 11.5px; line-height: 1; padding: 4px 7px;
  border-radius: 6px; cursor: pointer; white-space: nowrap;
}
.mini:hover { color: var(--text); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.mini--danger:hover { color: #fff; background: var(--danger); border-color: var(--danger); }

/* ---------- 开关：属性是否参与检索打分 ----------
   这一格原本只是「参与 / 不参与」的文字，用户会当成按钮去点、点了毫无反应。
   改成真开关：可点、有点击反馈、落库，语义一眼可见。 */
.switch { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; user-select: none; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch i {
  width: 30px; height: 17px; border-radius: 9px; flex: none; position: relative;
  background: color-mix(in srgb, var(--line) 90%, transparent); transition: background .15s;
}
.switch i::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 13px; height: 13px;
  border-radius: 50%; background: #fff; transition: transform .15s;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .25);
}
.switch input:checked + i { background: var(--accent); }
.switch input:checked + i::after { transform: translateX(13px); }
.switch em { font-style: normal; font-size: 12px; color: var(--muted); min-width: 32px; }
.switch input:checked ~ em { color: var(--text); }
.switch input:focus-visible + i { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ==================================================================
   AI 自媒体助手（M4）
   ⚠️ 这一整块必须放在**所有媒体查询之后**：插到某个 @media 中间，
      文件后半段的响应式规则会反过来覆盖这里，表现为"手机上样式又变回去"。
   ------------------------------------------------------------------ */

/* 加载态 / 空状态 —— 每个列表都得有，否则网络慢时看到的是一片空白 */
.md-load { display: flex; align-items: center; gap: 8px; padding: 18px 2px; color: var(--muted); font-size: 12.5px; }
.md-empty { padding: 26px 16px; text-align: center; border: 1px dashed var(--line); border-radius: 12px; background: var(--panel-soft); }

/* 配置详情的键值对 */
.md-kvs { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px 18px; margin-top: 12px; }
.md-kv { display: flex; align-items: baseline; gap: 10px; font-size: 13px; border-bottom: 1px solid var(--line); padding-bottom: 7px; }
.md-kv__k { color: var(--muted); font-size: 12px; flex: none; min-width: 74px; }
.md-kv__v { color: var(--text); word-break: break-all; }

/* 复选框组 */
.md-checks { display: flex; flex-wrap: wrap; gap: 10px 16px; }
.md-check { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text); cursor: pointer; }
.md-check input { accent-color: var(--accent); width: 15px; height: 15px; }
.md-check input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* 通用列表条目（选题 / 资产 / 词条共用一套骨架） */
.md-item { display: flex; align-items: flex-start; gap: 14px; padding: 13px 14px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel-soft); margin-bottom: 10px; }
.md-item__main { flex: 1; min-width: 0; }
.md-item__t { font-size: 14px; font-weight: 600; color: var(--text); line-height: 1.5; }
.md-item__d { font-size: 12.5px; color: var(--muted); margin-top: 3px; line-height: 1.6; }
.md-item__why { margin-top: 4px; }
.md-item__score { flex: none; text-align: center; min-width: 54px; }
.md-item__score b { display: block; font-size: 19px; color: var(--accent); line-height: 1.2; }
.md-item__ops { flex: none; display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end; max-width: 230px; }

/* 稿件工作区：左侧列表 + 右侧编辑 */
.md-work { display: grid; grid-template-columns: 268px 1fr; gap: 14px; align-items: start; }
.md-work__side { border: 1px solid var(--line); border-radius: 12px; background: var(--panel-soft); overflow: hidden; }
.md-side__hd { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--line); font-size: 13px; font-weight: 600; color: var(--text); }
.md-li { display: block; width: 100%; text-align: left; padding: 10px 12px; border: 0; border-bottom: 1px solid var(--line); background: transparent; color: var(--text); cursor: pointer; font: inherit; }
.md-li:hover { background: var(--hover); }
.md-li.is-on { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.md-li:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.md-li__t { display: block; font-size: 13px; line-height: 1.45; }
.md-li__m { display: block; margin-top: 3px; }
.md-work__main { min-width: 0; }

/* 稿件头部工具条 */
.md-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.md-head__t { font-size: 16px; font-weight: 600; color: var(--text); }

/* 正文 / 侧栏分区 */
.md-split { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 14px; align-items: start; }
.md-split__l { min-width: 0; }
.md-split__r { min-width: 0; display: flex; flex-direction: column; gap: 12px; }
.md-ta { min-height: 340px; font-family: var(--mono); font-size: 13px; line-height: 1.75; resize: vertical; }

/* 侧栏小卡片（合规 / 配图 / 排版 / 历史） */
.md-box { border: 1px solid var(--line); border-radius: 12px; background: var(--panel-soft); padding: 12px 13px; }
.md-box--bad { border-color: color-mix(in srgb, var(--danger) 55%, transparent); }
.md-box__h { font-size: 13px; font-weight: 600; color: var(--text); margin-bottom: 9px; }

/* 合规命中项 */
.md-hit { border-top: 1px solid var(--line); padding-top: 9px; margin-top: 9px; display: flex; flex-direction: column; gap: 5px; align-items: flex-start; }
.md-hit:first-of-type { border-top: 0; padding-top: 0; margin-top: 0; }
.md-hit__top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* 配图网格 —— 🔴 <img> 必须给尺寸约束，否则按固有尺寸铺开会把整页顶掉 */
.md-imgs { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 10px; }
.md-img { border: 1px solid var(--line); border-radius: 10px; padding: 7px; background: var(--panel-bg, transparent); display: flex; flex-direction: column; gap: 6px; }
.md-img img { width: 100%; height: 92px; object-fit: cover; border-radius: 7px; display: block; background: var(--hover); }
.md-img__ph { width: 100%; height: 92px; border-radius: 7px; background: var(--hover); display: flex; align-items: center; justify-content: center; color: var(--muted-dim); font-size: 11.5px; }
.md-img__ops { display: flex; gap: 6px; flex-wrap: wrap; }

/* 生成历史 */
.md-run { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 6px 0; border-top: 1px solid var(--line); }
.md-run:first-child { border-top: 0; }

/* 流式输出区 */
.md-stream { margin-bottom: 12px; }
.md-stream .streambox { max-height: 240px; }

/* 发布卡片 */
.md-pubs { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 12px; }
.md-pub { border: 1px solid var(--line); border-radius: 12px; background: var(--panel-soft); padding: 12px 13px; }
.md-pub__h { display: flex; align-items: center; gap: 8px; font-size: 14px; color: var(--text); }
.md-pub__ops { display: flex; gap: 6px; flex-wrap: wrap; }

/* 排版渲染结果（预览 + 导出 Word 共用同一份 HTML） */
.art { color: #24201a; background: #fff; border-radius: 10px; padding: 20px 22px; max-height: 420px; overflow: auto; font-size: 14.5px; line-height: 1.85; }
.art h1 { font-size: 22px; margin: 0 0 16px; line-height: 1.35; }
.art h2 { font-size: 17px; margin: 22px 0 9px; line-height: 1.4; }
.art h3 { font-size: 15px; margin: 16px 0 7px; }
.art p { margin: 0 0 11px; }
.art ul { margin: 0 0 12px; padding-left: 20px; }
.art li { margin: 0 0 6px; }
.art code { background: #f2efe9; padding: 1px 5px; border-radius: 4px; font-size: 13px; }
.art-fig { margin: 15px 0; text-align: center; }
.art-fig img { max-width: 100%; height: auto; border-radius: 8px; display: block; margin: 0 auto; }
.art-fig figcaption { font-size: 12px; color: #8a8072; margin-top: 6px; }
.art--magazine .art__hd { border-bottom: 2px solid #24201a; padding-bottom: 12px; margin-bottom: 6px; }
.art--minimal { max-width: 620px; padding: 24px 28px; line-height: 2; }
.art--wechat { padding: 18px 16px; }

/* 窄屏：工作区两栏收成上下，发布卡单列 */
@media (max-width: 1080px) {
  .md-split { grid-template-columns: 1fr; }
  .md-work { grid-template-columns: 1fr; }
  .md-work__side { max-height: 220px; overflow: auto; }
}
@media (max-width: 720px) {
  .md-item { flex-direction: column; gap: 9px; }
  .md-item__ops { max-width: none; justify-content: flex-start; }
  .md-item__score { text-align: left; display: flex; align-items: baseline; gap: 6px; }
  .md-kvs { grid-template-columns: 1fr; }
  .md-imgs { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); }
  .md-pubs { grid-template-columns: 1fr; }
  .art { padding: 15px 14px; }
}

/* ============================================================
   中国视角（3D）门店气泡：两侧停靠 + 折线指回地图
   ----------------------------------------------------------
   改动原因（2026-10-14）：原来气泡直接压在门店所在的省份上方，
   地图本身就被挡住一大块，看起来像「地图缺了一块」。
   现在改成参考诗境山河项目的做法：
     卡片停靠在容器左右两侧的列里 → 折线 → 地图上那个点（带序号圆点）。
   ⚠ 这块必须放在**所有媒体查询之后**：文件里前面已有若干 @media，
     插到中间会把后续规则吞进断点里（项目铁律）。
   ⚠ 位置由 store-map3d.js 每帧写 left/top（纵向防重叠排布），
     所以这里**不能**再给 .stm3-bub 写 transform —— 一旦写了会覆盖掉
     JS 写的位移，卡片会全部堆到容器左上角。
   ============================================================ */
.stm3-bubbles { pointer-events: none; }
.stm3-leads {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
}
.stm3-lead {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1;
  stroke-opacity: .42;
  /* 折线是每帧重写的，禁掉过渡，否则线会「追着点跑」出拖影 */
  transition: none;
}
.stm3-lead-dot {
  fill: var(--accent);
  stroke: var(--map3d-bg);
  stroke-width: 1.5;
}
.stm3-lead-num {
  fill: var(--accent);
  font: 600 10px/1 var(--font-sans, system-ui, sans-serif);
  text-anchor: middle;
  paint-order: stroke;
  stroke: var(--map3d-bg);
  stroke-width: 3;
  stroke-linejoin: round;
}
.stm3-bub {
  width: 178px;
  max-width: 178px;
  /* 位置完全交给 JS 每帧写 left/top，这里只管外观 */
  transform: none;
  transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
}
.stm3-bub em {
  flex: none;
  display: grid;
  place-items: center;
  width: 17px;
  height: 17px;
  margin-right: 1px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--map3d-bg);
  font-size: 10.5px;
  font-style: normal;
  font-weight: 700;
}
.stm3-bub b {
  /* 序号占了第一行空间，门店名独占一行更好读 */
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 窄屏 / 窄容器：两侧列会把地图挤没，退回单侧（左）且列宽收窄 */
@media (max-width: 780px) {
  .stm3-bub { width: 138px; max-width: 138px; padding: 4px 7px; }
  .stm3-bub span { display: none; }
}

/* ============================================================
   城市视角（高德瓦片）门店气泡：尾巴箭头 + 逐级放大
   ----------------------------------------------------------
   改动原因（2026-10-14）：原来气泡是一颗圆角药丸，
   底边虽然压在坐标点上，但没有箭头，看不出「针尖落在哪条街」。
   现在加一个朝下的实心小三角（::after 画，边框色与气泡一致），
   三角尖端正好落在 translate(-50%,-100%) 后的底部中点 = 坐标点。
   ⚠ 用::after 而不是嵌套 <i>：标记的 DOM 结构是 <i>圆点 + <b>名称</b>，
      再塞一个元素进去会被 paintCityMarks 每帧重排的 querySelector 逻辑干扰。
   ⚠ 放在所有媒体查询之后（项目铁律）。
   ============================================================ */
.stm-mk { --mk-tail: color-mix(in srgb, var(--panel-bg-solid) 92%, transparent); position: absolute; }
.stm-mk::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 100%;
  transform: translateX(-50%);
  border: 5px solid transparent;
  border-top-color: var(--mk-tail);
  /* 三角比气泡边框略深一点，尖端才不会和药丸糊在一起 */
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .22));
}
/* 高亮态与停用态的尾巴跟着换色，否则气泡变了色、箭头还是上一个状态 */
.stm-mk.is-active { --mk-tail: color-mix(in srgb, var(--accent) 18%, var(--panel-bg-solid)); }
.stm-mk.is-off { --mk-tail: var(--panel-bg-solid); }
@media (max-width: 900px) {
  .stm-mk::after { border-width: 4px; }
}

/* ============================================================
   Skill 配置详情卡重排（2026-10-15，用户反馈「红框部分有点丑」）
   ------------------------------------------------------------
   旧样式（文件中部 .md-kvs / .md-kv）是「标签 + 值同行」的 auto-fill
   网格，三个问题：① 长值被 word-break:break-all 硬切，中文被拦腰断开；
   ② 每项一条底边线 + 高度不等 → 视觉参差；③ 12 项平铺无分组、读不出结构。
   这里改成**分组卡片式**：组标题（左侧色条）→ 组内「标签在上、值在下」。
   ⚠ 覆盖必须逐条写全旧属性：只写差异会残留旧值
     （最典型的是 grid-template-columns 不重写，就仍是 260px 三列）。
   ⚠ 放在所有 @media 之后（项目铁律：插到前面会被后续断点吞掉）。
   ============================================================ */
.md-kvs { grid-template-columns: 1fr; gap: 20px; margin-top: 14px; }

.md-grp { display: grid; gap: 10px; min-width: 0; }
.md-grp__t {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--muted);
}
.md-grp__t::before {
  content: '';
  flex: none;
  width: 3px;
  height: 12px;
  border-radius: 2px;
  background: var(--accent);
  opacity: .7;
}
.md-grp__b {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 12px 22px;
  min-width: 0;
}

.md-kv {
  display: grid;
  align-items: stretch;
  gap: 3px;
  font-size: 13px;
  border-bottom: 0;
  padding-bottom: 0;
  min-width: 0;
}
.md-kv__k { color: var(--muted); font-size: 12px; min-width: 0; flex: none; }
.md-kv__v {
  color: var(--text);
  font-size: 13.5px;
  line-height: 1.62;
  word-break: normal;
  overflow-wrap: anywhere;
}

/* 底部说明：从内联样式收成类，加左侧提示条，免得和正文糊在一起 */
.md-skill-note {
  margin: 16px 0 0;
  padding: 10px 12px 10px 13px;
  border-left: 2px solid var(--line);
  border-radius: 0 8px 8px 0;
  background: var(--panel-soft);
  font-size: 12px;
  line-height: 1.75;
  color: var(--muted);
}

/* 窄屏：组内退成单列，避免 190px 也排不下时挤成两字一行 */
@media (max-width: 620px) {
  .md-grp__b { grid-template-columns: 1fr; gap: 11px; }
  .md-skill-note { font-size: 11.5px; }
}

/* Skill 配置详情卡：本身仍是 .panel，这里只补排布节奏。
   ⚠ `.panel` 全局只有边框没有内边距（全靠各视图自己加），不补 padding 的
      后果就是内容紧贴边框 —— 组标题的色条几乎压在上/左边框上。
      用户 2026-10-15 反馈「配置信息部分左侧与包裹区域的上下边框都要有间距」。 */
.md-skill-card { margin-top: 14px; padding: 16px 18px 18px; }

/* ==========================================================================
   AI 智能系统（M3）—— 知识库 / 形象档案 / 穿搭推荐 / 数字衣橱 / Agent / 私域 / 反馈
   --------------------------------------------------------------------------
   统一口径：全部走 admin-hud.css 的主题令牌（--panel-bg / --text / --muted …），
   不写死颜色 —— 深浅两套主题共用同一份规则。
   🔴 所有 flex 子项都要 min-width:0：本页大量长文本（方案标题、备注、JSON 片段），
      没有 min-width:0 会因为内容的固有宽度把整行顶宽、进而撕裂布局。
   🔴 所有 <img> 都要带尺寸约束：固有尺寸的图在 max-width:100% 下会被按比例撑开，
      一张 1148×1531 的图足以把整页顶成一屏黑色（20261012a 已踩过一次）。
   ========================================================================== */

/* ---- 版块分隔：子页内的二级功能区 ---- */
.ai-sec { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--line-soft); }

/* ---- 统计条：四条刷新前先给个数，避免空列表看了像报错 ---- */
.ai-stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
  gap: 10px; margin: 14px 0 2px;
}
.ai-stat {
  display: flex; flex-direction: column; gap: 4px;
  padding: 10px 12px; border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  background: var(--panel-bg); min-width: 0;
}
.ai-stat__k { font-size: 11.5px; color: var(--muted-dim); letter-spacing: .04em; }
.ai-stat__v {
  font-family: var(--serif); font-size: 19px; line-height: 1.2; color: var(--text-strong);
  overflow-wrap: anywhere;
}
.ai-stat__v em { font-size: 11.5px; font-style: normal; color: var(--muted); margin-left: 4px; }

/* ---- 通用列表行：一块内容 + 右侧操作区 ---- */
.ai-list { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
.ai-list--tight { gap: 6px; }
.ai-row {
  display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap;
  padding: 12px 14px; border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  background: var(--panel-bg); transition: border-color .18s ease;
}
.ai-row:hover { border-color: var(--panel-border); }
.ai-row__main { flex: 1 1 320px; min-width: 0; }
.ai-row__t {
  font-size: 14px; font-weight: 600; color: var(--text-strong);
  line-height: 1.5; overflow-wrap: anywhere;
}
.ai-row__m {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 6px; min-width: 0;
}
.ai-row__acts { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* ---- 状态点：语义色沿用令牌，缺席态（无修饰）保持中性灰 ---- */
.ai-pill {
  display: inline-flex; align-items: center; padding: 2px 8px;
  border-radius: 999px; font-size: 11.5px; line-height: 1.6;
  background: var(--hover); color: var(--muted); border: 1px solid var(--line-soft);
  white-space: nowrap;
}
.ai-pill--ok { background: var(--ok-soft); color: var(--ok); border-color: var(--ok-soft); }
.ai-pill--warn { background: var(--warn-soft); color: var(--warn); border-color: var(--warn-soft); }
.ai-pill--bad { background: var(--danger-soft); color: var(--danger); border-color: var(--danger-soft); }

/* ---- 检索命中（M3-01）---- */
.ai-hits {
  margin-top: 14px; padding: 12px 14px;
  border: 1px solid var(--panel-border); border-radius: var(--radius-sm);
  background: var(--accent-soft);
}
.ai-hits__hd {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 13px; color: var(--text-strong); margin-bottom: 10px;
}
.ai-hit {
  padding: 10px 12px; margin-bottom: 8px;
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  background: var(--panel-bg);
}
.ai-hit:last-child { margin-bottom: 0; }
.ai-hit__hd { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 13px; }
.ai-hit__n {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 6px; flex: none;
  background: var(--accent-soft); color: var(--accent); font-size: 11.5px;
}
.ai-hit__sc {
  font-family: var(--mono); font-size: 11.5px; color: var(--accent);
  padding: 1px 6px; border-radius: 6px; background: var(--accent-soft); flex: none;
}
.ai-hit__tx {
  margin: 8px 0 0; font-size: 12.5px; line-height: 1.75; color: var(--text);
  overflow-wrap: anywhere;
}

/* ---- 切分预览 ---- */
.ai-chunks { display: flex; flex-direction: column; gap: 10px; }
.ai-chunk {
  padding: 10px 12px; border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  background: var(--panel-bg);
}
.ai-chunk__hd { font-size: 12.5px; color: var(--text-strong); margin-bottom: 6px; }
.ai-chunk__tx {
  margin: 0 0 6px; font-size: 12.5px; line-height: 1.8; color: var(--text);
  white-space: pre-wrap; overflow-wrap: anywhere;
}

/* ---- 富内容弹窗：切分块 / 商品库可能很长，body 必须能滚 ---- */
.ui-sheet .modal__body { max-height: 70vh; overflow: auto; }

/* ---- 卡片 / 键值 / 正文段（M3-03 档案聚合）---- */
.ai-card { margin-top: 14px; }
.ai-kvs {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 12px 18px; padding: 4px 2px 2px;
}
.ai-kvs--two { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.ai-kv { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ai-kv__k { font-size: 11.5px; color: var(--muted-dim); letter-spacing: .04em; }
.ai-kv__v { font-size: 13px; color: var(--text-strong); overflow-wrap: anywhere; line-height: 1.6; }
.ai-text { margin: 0 0 8px; font-size: 13px; line-height: 1.85; color: var(--text); overflow-wrap: anywhere; }
.ai-line {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 7px 0; border-bottom: 1px solid var(--line-soft);
  font-size: 13px; color: var(--text); min-width: 0;
}
.ai-line:last-child { border-bottom: 0; }
.ai-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.ai-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px; border-radius: 999px;
  border: 1px solid var(--line-soft); background: var(--hover);
  font-size: 12.5px; color: var(--text); max-width: 100%;
}
.ai-chip em { font-style: normal; font-size: 11.5px; color: var(--muted-dim); }

/* ---- 文案块（私域）---- */
.ai-copy {
  margin: 8px 0 0; padding: 10px 12px;
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  background: var(--hover); font-size: 12.5px; line-height: 1.8; color: var(--text);
  overflow-wrap: anywhere;
}
.ai-copy--full { white-space: pre-wrap; max-height: 46vh; overflow: auto; }
.ai-code {
  display: block; padding: 8px 10px; margin-top: 8px;
  border: 1px dashed var(--panel-border); border-radius: var(--radius-sm);
  background: var(--hover); font-family: var(--mono); font-size: 11.5px;
  color: var(--text); overflow-wrap: anywhere; word-break: break-all;
}

/* ---- 场景权重条（M3-05）：<i style="--w:0.8"> 画进度 ---- */
.ai-w { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--muted); }
.ai-w em { font-style: normal; color: var(--text); }
.ai-w i {
  position: relative; display: block; width: 54px; height: 5px; flex: none;
  border-radius: 999px; background: var(--line-soft); overflow: hidden;
}
.ai-w i::after {
  content: ''; position: absolute; inset: 0;
  width: calc(var(--w, 0) * 100%); background: var(--accent); border-radius: 999px;
}
.ai-weights { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px 14px; }
.ai-weight { display: flex; flex-direction: column; gap: 5px; font-size: 12px; color: var(--muted); }
.ai-check {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 13px; color: var(--text); cursor: pointer; user-select: none;
}

/* ---- 禁忌规则（M3-06）：按 Scope 分组 ---- */
.ai-scope { margin-top: 16px; }
.ai-scope__t {
  margin: 0 0 10px; padding-left: 9px; position: relative;
  font-family: var(--serif); font-size: 14px; font-weight: 600; color: var(--text-strong);
}
.ai-scope__t::before {
  content: ''; position: absolute; left: 0; top: 2px; bottom: 2px;
  width: 3px; border-radius: 2px; background: var(--accent); opacity: .75;
}
.ai-rules { display: flex; flex-direction: column; gap: 8px; }
.ai-rule {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 9px 12px; border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  background: var(--panel-bg); font-size: 13px; color: var(--text-strong);
}
.ai-rule.is-off { opacity: .55; }
.ai-rule__note { flex: 1 1 200px; min-width: 0; overflow-wrap: anywhere; }

/* ---- 搭配方案卡（M3-04 / M3-07）---- */
.ai-outfits { display: flex; flex-direction: column; gap: 12px; margin-top: 12px; }
.ai-outfit {
  display: flex; gap: 14px; flex-wrap: wrap;
  padding: 14px; border: 1px solid var(--line-soft); border-radius: var(--radius);
  background: var(--panel-bg); transition: border-color .18s ease;
}
.ai-outfit:hover { border-color: var(--panel-border); }
.ai-outfit__fig {
  flex: none; width: 120px; display: flex; flex-direction: column; align-items: center; gap: 6px;
}
/* 🔴 配图是高宽比不定的远程图，必须锁死 120×150 再 cover，否则会把卡片撑变形 */
.ai-outfit__fig img {
  width: 120px; height: 150px; max-width: 100%; object-fit: cover;
  border-radius: var(--radius-sm); border: 1px solid var(--line-soft); background: var(--hover);
}
.ai-outfit__main { flex: 1 1 380px; min-width: 0; }
.ai-outfit__hd { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 14px; }
.ai-outfit__price { font-family: var(--serif); font-size: 15px; color: var(--accent); flex: none; }
.ai-outfit__items { display: flex; flex-direction: column; gap: 4px; margin: 10px 0 0; }
.ai-item {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 6px 9px; border-radius: var(--radius-sm); background: var(--hover);
  font-size: 12.5px; color: var(--text);
}
.ai-item__role {
  flex: none; padding: 1px 7px; border-radius: 6px;
  background: var(--accent-soft); color: var(--accent); font-size: 11.5px;
}
.ai-outfit__reason {
  margin: 10px 0 0; font-size: 12.5px; line-height: 1.8; color: var(--text);
  overflow-wrap: anywhere; white-space: pre-wrap;
}
.ai-warn {
  margin-top: 8px; padding: 8px 10px; border-radius: var(--radius-sm);
  background: var(--warn-soft); border: 1px solid var(--warn-soft);
  font-size: 12px; line-height: 1.7; color: var(--warn); overflow-wrap: anywhere;
}
.ai-outfit__acts { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 12px; }

/* ---- 数字衣橱（M3-08）---- */
.ai-wd__fig {
  flex: none; width: 48px; height: 60px; overflow: hidden;
  border-radius: var(--radius-sm); border: 1px solid var(--line-soft); background: var(--hover);
}
.ai-wd__fig img { width: 48px; height: 60px; max-width: 100%; object-fit: cover; display: block; }
.ai-wd__ph {
  display: flex; align-items: center; justify-content: center;
  width: 48px; height: 60px; background: var(--accent-soft); color: var(--accent);
  font-family: var(--serif); font-size: 20px;
}
.ai-swatch {
  height: 76px; margin-top: 12px; border-radius: var(--radius-sm);
  border: 1px solid var(--line-soft); background-clip: padding-box;
}

/* ---- 商品选择器（衣橱 / 替换单品共用）---- */
.ai-pick { display: flex; flex-direction: column; gap: 10px; }
.ai-pick__list { display: flex; flex-direction: column; gap: 6px; max-height: 52vh; overflow: auto; }
.ai-pick__row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 9px 11px; border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  background: var(--panel-bg); color: var(--text); font-size: 13px; cursor: pointer;
  text-align: left; width: 100%; transition: border-color .18s ease, background .18s ease;
}
.ai-pick__row:hover, .ai-pick__row:focus-visible { border-color: var(--accent); background: var(--hover); }
.ai-pick__n { font-weight: 600; color: var(--text-strong); min-width: 0; overflow-wrap: anywhere; }

/* ---- AI 顾问（M3-09）---- */
.ai-agent { display: grid; grid-template-columns: 264px 1fr; gap: 14px; align-items: stretch; }
.ai-agent__side {
  display: flex; flex-direction: column; gap: 8px; min-width: 0;
  padding: 12px; border: 1px solid var(--line-soft); border-radius: var(--radius);
  background: var(--panel-bg);
}
.ai-agent__bind { padding-bottom: 8px; border-bottom: 1px solid var(--line-soft); }
.ai-agent__main { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.ai-sess {
  display: flex; flex-direction: column; gap: 3px; text-align: left; width: 100%;
  padding: 9px 10px; border: 1px solid transparent; border-radius: var(--radius-sm);
  background: transparent; color: var(--text); cursor: pointer;
  transition: background .18s ease, border-color .18s ease;
}
.ai-sess:hover { background: var(--hover); }
.ai-sess.is-on { border-color: var(--panel-border); background: var(--accent-soft); }
.ai-sess__t {
  font-size: 13px; color: var(--text-strong); line-height: 1.5;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ai-chat {
  flex: 1 1 auto; display: flex; flex-direction: column; gap: 10px;
  min-height: 300px; max-height: 54vh; overflow-y: auto; overscroll-behavior: contain;
  padding: 14px; border: 1px solid var(--line-soft); border-radius: var(--radius);
  background: var(--panel-bg);
}
.ai-chat__input { display: flex; flex-direction: column; gap: 8px; }
.ai-chat__input textarea { width: 100%; resize: vertical; min-height: 62px; line-height: 1.7; }
.ai-chat__acts { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ai-msg { display: flex; max-width: 100%; }
.ai-msg--me { justify-content: flex-end; }
.ai-msg--ai { justify-content: flex-start; }
.ai-msg__b {
  max-width: min(78%, 620px); padding: 10px 13px;
  border: 1px solid var(--line-soft); border-radius: var(--radius);
  font-size: 13px; line-height: 1.8; overflow-wrap: anywhere;
  /* AI 回复带换行与列表，保留原格式；同时防超长单词撑破气泡 */
  white-space: pre-wrap; word-break: break-word;
}
.ai-msg--me .ai-msg__b { background: var(--accent-soft); border-color: var(--panel-border); color: var(--text-strong); }
.ai-msg--ai .ai-msg__b { background: var(--hover); color: var(--text); }
.ai-msg--live .ai-msg__b::after {
  content: ''; display: inline-block; width: 6px; height: 13px; margin-left: 3px;
  background: var(--accent); vertical-align: -2px; animation: aiBlink 1s steps(2, start) infinite;
}
@keyframes aiBlink { 50% { opacity: 0; } }
.ai-msg__stop { margin-left: 6px; font-size: 11.5px; color: var(--warn); }
.ai-tool {
  max-width: min(88%, 680px); padding: 9px 12px; margin: 2px 0;
  border: 1px dashed var(--panel-border); border-left-width: 3px; border-radius: var(--radius-sm);
  background: var(--hover); font-size: 12px; color: var(--text);
}
.ai-tool--读 { border-left-color: var(--info); }
.ai-tool--写 { border-left-color: var(--warn); }
.ai-tool__hd { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 5px; color: var(--text-strong); }
.ai-tool__hd + div { overflow-wrap: anywhere; word-break: break-all; }

/* ---- 反馈迭代（M3-15）---- */
.ai-fb-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 14px; margin-top: 14px;
}
.ai-rate { display: flex; align-items: center; gap: 10px; padding: 5px 0; font-size: 12.5px; min-width: 0; }
.ai-rate__k { flex: 0 0 78px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ai-rate__bar {
  position: relative; flex: 1 1 auto; min-width: 60px; height: 6px;
  border-radius: 999px; background: var(--line-soft); overflow: hidden;
}
.ai-rate__bar i {
  position: absolute; inset: 0; width: calc(var(--p, 0) * 1%);
  background: var(--ok); border-radius: 999px;
}

/* ---- 响应式：容器查询之外的兜底 ---- */
@media (max-width: 1080px) {
  .ai-agent { grid-template-columns: 1fr; }
  .ai-agent__side { max-height: 220px; overflow: auto; }
  .ai-chat { max-height: 60vh; }
}
@media (max-width: 720px) {
  .ai-stats { grid-template-columns: repeat(auto-fit, minmax(112px, 1fr)); }
  .ai-row { padding: 11px; }
  .ai-row__acts { width: 100%; justify-content: flex-start; }
  .ai-outfit__fig { width: 100%; flex-direction: row; align-items: flex-start; gap: 10px; }
  .ai-msg__b { max-width: 92%; }
  .ai-agent__side { max-height: 190px; }
}
@media (prefers-reduced-motion: reduce) {
  .ai-msg--live .ai-msg__b::after { animation: none; }
  .ai-row, .ai-pick__row, .ai-sess { transition: none; }
}

/* ==========================================================================
   地址联想下拉（门店表单，2026-10-15 用户需求 2）
   --------------------------------------------------------------------------
   输入地址 → 下拉给出候选位置 → 选中即落图。原先只能「先想经纬度、再去
   地图上拖」，这条路径对顾问太绕。
   ⚠ 必须是 position:absolute 挂在输入框下方，**不能用 .field 的流式布局**：
      否则下拉一展开就把地图整个推下去，用户点候选时地图已经不在视野里了。
   ⚠ z-index 要高于地图容器（.stm 内部有瓦片层），否则候选被瓦片盖住。
   ⚠ 放在所有 @media 之后（项目铁律）。
   ========================================================================== */
.ac { position: relative; }
.ac__list {
  position: absolute;
  left: 0; right: 0; top: calc(100% + 5px);
  z-index: 60;
  max-height: 264px;
  overflow-y: auto;
  padding: 4px;
  border: 1px solid var(--panel-border-strong);
  border-radius: var(--radius-sm);
  background: var(--panel-bg-solid);
  box-shadow: var(--shadow);
}
.ac__item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 7px 9px;
  border-radius: 8px;
  cursor: pointer;
}
.ac__item + .ac__item { margin-top: 1px; }
.ac__item:hover, .ac__item.is-on { background: var(--accent-soft); }
.ac__t { font-size: 13px; font-weight: 600; color: var(--text-strong); line-height: 1.45; }
.ac__s { font-size: 11.5px; color: var(--muted); line-height: 1.5; }
/* 搜索中 / 无结果 / 缺 Key —— 都不是「可选项」，所以不给 hover 也不给 pointer */
.ac__msg {
  padding: 9px 10px;
  font-size: 12.5px;
  line-height: 1.7;
  color: var(--muted);
}
.ac__msg .lnk { margin-left: 4px; }

/* ==========================================================================
   顶栏窄屏收敛（2026-10-16 全盘审计）
   ─────────────────────────────────────────────────────────────────────────
   390px 实测现象：brand 副标题 + 页面标题 + 两个全文字按钮把门店切换器
   挤成一个没有文字的椭圆 —— 手机上等于切不了门店，而门店是**全局上下文**，
   同时决定问卷记录与客户档案两处列表的范围。
   处理：≤640px 隐去 brand 副标题与页面标题，两个次要按钮只留图标
   （title / aria-label 仍在，鼠标悬停与读屏可达），把宽度还给门店切换器。
   ========================================================================== */
@media (max-width: 640px) {
  .topbar .brand-text { display: none; }
  .topbar .topbar__title { display: none; }
  .topbar__actions .btn__txt { display: none; }
  .topbar__actions { gap: 6px; }
  .topbar__actions .btn { padding: 6px 8px; }
  .topbar .store-switch { flex: 0 1 auto; min-width: 88px; max-width: 42vw; }
  .topbar .store-switch__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}

/* ==========================================================================
   2026-10-17 用户反馈批次（11 条）
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**；后续要覆盖这里的规则，
      继续往下追加即可（同特异度按源码顺序，后者生效）。
   ========================================================================== */

/* ---------- ① 登录页：粒子背景层 + 排版收敛 + 控件精细化 ---------- */
/* 背景动效层固定在视口，登录卡片抬到它上面。canvas 自身不接收事件。 */
#login-view { position: relative; z-index: 1; }
#auth-fx {
  position: fixed; inset: 0; width: 100%; height: 100%;
  z-index: 0; display: block; pointer-events: none;
}
.loginbox {
  position: relative; z-index: 1;
  padding: 24px 24px 20px;
  border-radius: 18px;
}
.loginbox .field { margin-bottom: 14px; }
.loginbox .tabs { margin-bottom: 16px; }
/* 输入框在登录页加大一号：这是整个流程唯一的输入动作，值得更宽的点击面 */
.loginbox .input--lg { padding: 12px 14px; border-radius: 12px; }
.login-note { margin: 2px 0 0; text-align: center; }
.login-foot { text-align: center; margin-top: 16px; }
/* 按钮精细化：细描边 + 微投影 + hover 微抬升；只动视觉不动尺寸 */
.loginbox .btn {
  border-radius: 12px;
  letter-spacing: .02em;
  box-shadow: 0 1px 2px rgba(58, 47, 33, .05);
}
.loginbox .btn--primary {
  background-image: linear-gradient(180deg, color-mix(in srgb, var(--ink) 91%, #fff) 0%, var(--ink) 100%);
}
.loginbox .btn:hover { transform: translateY(-1px); box-shadow: 0 5px 16px rgba(58, 47, 33, .12); }
.loginbox .btn:active { transform: translateY(0); }
.loginbox .tabs button { border-radius: 999px; }
/* 键盘可达性：所有按钮补 focus 环（只在键盘聚焦时出现，不影响鼠标操作） */
.btn:focus-visible {
  outline: 2px solid color-mix(in srgb, var(--accent) 55%, transparent);
  outline-offset: 2px;
}

/* ---------- ② 「列表 / 卡片」切换按钮的图标 ---------- */
/* 图标与文字同一基线，间距固定 6px；图标不参与压缩 */
.seg__btn { display: inline-flex; align-items: center; gap: 6px; }
.seg__btn .seg__ico { flex: 0 0 auto; }

/* ---------- ③ 表格：操作列不许换行 + 单元格截断 ---------- */
/* 门店列表原来把 4 个按钮塞在 150px 里 → 每个按钮各占一行，行高被撑成 4 倍。
   现在：列宽钉死 + 操作列 nowrap，四个按钮必然排在同一行。 */
.acts-cell { white-space: nowrap; }
.acts-cell .btn { margin-right: 6px; vertical-align: middle; }
.acts-cell .btn:last-child { margin-right: 0; }
/* 单行截断，悬停由 title 属性给全文 */
.cell-clip { max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tbl--stores { min-width: 1080px; }
/* 横向滚动时首列（门店名）固定，滚到右边也知道自己在看哪家店 */
.tbl--stores thead th:first-child,
.tbl--stores tbody td:first-child {
  position: sticky; left: 0; z-index: 1;
  background: var(--panel-bg-solid);
}

/* ---------- ④ 顾问表单：头像区居中 / 密码行 / 门店全选 ---------- */
/* 头像预览与它下面两个按钮必须左右居中对齐。
   旧版按钮包在一个块级 div 里，按钮靠左 → 用户看到的是「按钮偏左」。 */
.cf-ava-field { flex: 0 0 168px; width: 168px; text-align: center; }
.cf-ava-field .c-ava--big { margin: 0 auto; cursor: pointer; }
.cf-ava-field .c-ava--big:focus-visible {
  outline: 2px solid color-mix(in srgb, var(--accent) 55%, transparent);
  outline-offset: 3px;
}
.cf-ava-acts { display: flex; justify-content: center; align-items: center; gap: 6px; margin-top: 8px; }
.cf-ava-field .field__hint { margin-top: 6px; }
.cf-pwd-row { display: flex; gap: 8px; align-items: center; }
.cf-pwd-row .input { flex: 1; min-width: 0; }
.cf-store-bar { margin: 0 0 8px; padding-bottom: 6px; border-bottom: 1px dashed var(--line); }

/* ---------- ⑤ 门店「查看员工」：横向条目 + 头像 ---------- */
.staff-row { flex-direction: row; align-items: center; gap: 10px; }
.staff-row__ava { flex: 0 0 auto; }
.staff-row__ava .c-ava {
  width: 38px; height: 38px; border-radius: 50%;
  border: 1px solid var(--panel-border);
}
.staff-row__ini {
  width: 38px; height: 38px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  color: var(--accent); font-weight: 600; font-size: 15px;
}
.staff-row__main { min-width: 0; }
.staff-row__name { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.staff-row__meta { margin-top: 2px; }

/* ---------- ⑥ 侧栏「修改密码」入口 ----------
   2026-10-18：按钮已搬进左下角个人信息抽屉（#me-pwd），侧栏不再有这颗按钮，
   对应规则删除（留着就是永远匹配不到节点的死代码）。 */

/* ---------- 表格内容不被折断（2026-10-17 截图核对后补） ----------
   实测：编号「S-OWNER」被折成两行、角色标签「超级管理员」被折成两行，
   行高参差。标签与编号本来就该一行显示。 */
.tbl .tag { white-space: nowrap; }
.tbl--consultant th:nth-child(1), .tbl--consultant td:nth-child(1),
.tbl--consultant th:nth-child(2), .tbl--consultant td:nth-child(2) { white-space: nowrap; }
.tbl--stores th:nth-child(1), .tbl--stores td:nth-child(1),
.tbl--stores th:nth-child(3), .tbl--stores td:nth-child(3) { white-space: nowrap; }

/* ============================================================
   ⑦ 新手引导 + 帮助中心（M5，2026-10-18）
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**；后续要覆盖这里的规则，
      必须写全父级前缀。
   ============================================================ */

/* ---------- 页面内帮助入口 ----------
   🔴 必须是 fixed 悬浮、**不占文档流**。
      早先往七个 view 容器顶部插一条按钮条，把内容区整体推下去 34px，
      地图类回归（按容器几何算点击坐标）直接挂掉。
      也不要给 view 容器加 position:relative —— 那会让容器变成内部
      absolute 元素的新包含块，同样是破坏既有布局。 */
.help-fab {
  position: fixed; right: 20px; bottom: 20px; z-index: 900;
  width: 40px; height: 40px; display: grid; place-items: center;
  border-radius: 50%; cursor: pointer;
  border: 1px solid var(--line);
  background: var(--surface); color: var(--text-dim);
  box-shadow: 0 8px 22px rgba(0, 0, 0, .28);
  transition: color .16s, border-color .16s, transform .16s, box-shadow .16s;
}
.help-fab:hover {
  color: var(--accent); border-color: color-mix(in srgb, var(--accent) 55%, var(--line));
  transform: translateY(-2px); box-shadow: 0 12px 26px rgba(0, 0, 0, .34);
}
/* 帮助中心 / 引导打开时把悬浮按钮收起来，避免叠在最上层显得杂乱 */
body.mh-open .help-fab, body.mt-on .help-fab { opacity: 0; pointer-events: none; }

/* ---------- 帮助中心 ---------- */
.mhelp { position: fixed; inset: 0; z-index: 1200; display: flex; }
.mhelp[style*="display: none"] { display: none; }
.mhelp__scrim { position: absolute; inset: 0; background: rgba(10, 9, 8, .58); backdrop-filter: blur(2px); }
.mhelp__box {
  position: relative; margin: auto;
  width: min(1080px, calc(100vw - 48px)); height: min(760px, calc(100vh - 64px));
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 14px; box-shadow: 0 26px 70px rgba(0, 0, 0, .45);
  overflow: hidden;
}
.mhelp__head {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 18px; border-bottom: 1px solid var(--line);
  background: var(--surface-2);
}
.mhelp__title { display: flex; align-items: center; gap: 8px; font-family: var(--serif); font-size: 17px; color: var(--text-strong); }
.mhelp__search { position: relative; display: flex; align-items: center; gap: 7px; min-width: 0; width: clamp(220px, 34vw, 380px); color: var(--text-dim); }
.mhelp__search .input { width: 100%; }
.mhelp__clr {
  position: absolute; right: 6px; display: inline-flex; padding: 3px;
  border: 0; background: transparent; color: var(--text-dim); cursor: pointer; border-radius: 6px;
}
.mhelp__clr:hover { color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.mhelp__main { flex: 1; display: flex; min-height: 0; }
/* 左侧目录：固定宽度，自己滚，不牵动正文 */
.mhelp__nav {
  width: 246px; flex: 0 0 246px; overflow-y: auto;
  padding: 12px 10px 40px; border-right: 1px solid var(--line); background: var(--surface-2);
}
.mhelp__navhead { padding: 6px 10px 8px; font-size: 11px; color: var(--text-dim); letter-spacing: .04em; }
.mhelp__grp { margin-bottom: 10px; }
.mhelp__navitem {
  display: block; width: 100%; text-align: left;
  padding: 7px 10px; margin-bottom: 2px;
  border: 0; border-radius: 8px; background: transparent;
  color: var(--text-dim); font: inherit; font-size: 13px; cursor: pointer;
  transition: background .14s, color .14s;
}
.mhelp__navitem:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); color: var(--text); }
.mhelp__navitem--g { font-weight: 600; color: var(--text); }
.mhelp__navitem--c { padding-left: 22px; font-size: 12.5px; }
.mhelp__navitem--flat { padding: 8px 10px; }
.mhelp__navitem--flat b { display: block; font-size: 13px; color: var(--text); font-weight: 600; }
.mhelp__navitem--flat .tiny { display: block; margin-top: 1px; }
.mhelp__navitem.is-on {
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  color: var(--accent); font-weight: 600;
}
.mhelp__navitem.is-todo { opacity: .58; }
.mhelp__todo { float: right; font-size: 10px; padding: 1px 5px; border-radius: 999px; border: 1px solid var(--line); color: var(--text-dim); }
.mhelp__hits { display: block; margin-top: 3px; font-size: 11px; color: var(--text-dim); }
.mhelp__empty { padding: 24px 14px; font-size: 13px; color: var(--text-dim); line-height: 1.8; }
.mhelp__doc { flex: 1; min-width: 0; overflow-y: auto; padding: 22px 26px 60px; }
.mhelp__dochead { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
.mhelp__dochead h3 {
  margin: 0; font-family: var(--serif); font-size: 20px; color: var(--text-strong);
  border-radius: 6px; padding: 1px 4px; margin-left: -4px;
}
/* 从别处跳转进来时闪一下，让人知道「就是这条」 */
.mhelp__dochead h3.is-flash { animation: mhflash 1.4s ease; }
@keyframes mhflash {
  0%, 100% { background: transparent; }
  18%, 62% { background: color-mix(in srgb, var(--accent) 30%, transparent); }
}
.mhelp__brief {
  padding: 11px 14px; margin-bottom: 16px; border-radius: 10px;
  background: color-mix(in srgb, var(--accent) 9%, transparent);
  border-left: 3px solid var(--accent);
  color: var(--text); font-size: 13.5px; line-height: 1.8;
}
.mhelp__sec { margin-bottom: 18px; }
.mhelp__sech {
  font-size: 11px; letter-spacing: .06em; color: var(--text-dim);
  margin-bottom: 7px; padding-bottom: 5px; border-bottom: 1px dashed var(--line);
}
.mhelp__line { font-size: 13.5px; line-height: 1.85; color: var(--text); }
.mhelp__steps { margin: 0; padding-left: 20px; }
.mhelp__steps li { margin-bottom: 8px; font-size: 13.5px; line-height: 1.75; color: var(--text); }
.mhelp__steps b { display: block; color: var(--text-strong); margin-bottom: 1px; }
.mhelp__faq {
  border: 1px solid var(--line); border-radius: 9px; margin-bottom: 7px;
  background: var(--surface-2); overflow: hidden;
}
.mhelp__faq summary {
  padding: 9px 13px; cursor: pointer; font-size: 13.5px; color: var(--text);
  list-style: none; display: flex; align-items: center; gap: 8px;
}
.mhelp__faq summary::before { content: '?'; flex: 0 0 auto; width: 17px; height: 17px; border-radius: 50%; display: grid; place-items: center; font-size: 11px; background: color-mix(in srgb, var(--accent) 20%, transparent); color: var(--accent); }
.mhelp__faq summary::-webkit-details-marker { display: none; }
.mhelp__faq[open] summary { border-bottom: 1px solid var(--line); }
.mhelp__faqa { padding: 10px 13px 12px 38px; font-size: 13px; line-height: 1.85; color: var(--text-dim); }
.mhelp__welcome { padding: 60px 10px; text-align: center; color: var(--text-dim); }
.mhelp__welcome h3 { font-family: var(--serif); font-size: 21px; color: var(--text-strong); margin: 0 0 12px; }
.mhelp__welcome p { max-width: 460px; margin: 0 auto 12px; font-size: 13.5px; line-height: 1.9; }
.mhelp__todo-box {
  padding: 18px 16px; border: 1px dashed var(--line); border-radius: 10px;
  color: var(--text-dim); font-size: 13px; line-height: 1.8;
}
.mhelp__todo-box code { padding: 1px 6px; border-radius: 5px; background: var(--surface-2); font-size: 12px; }
/* 检索命中：用主色调，不用刺眼的荧光黄 */
.mhelp__doc mark, .mhelp__nav mark { background: color-mix(in srgb, var(--accent) 34%, transparent); color: inherit; border-radius: 3px; padding: 0 2px; }
/* 打开帮助时锁住背后的滚动，否则滚轮会滚到后面的列表上 */
body.mh-open { overflow: hidden; }

/* ---------- 新手引导 ---------- */
/* 🔴 引导是**非阻断**的：容器整体 pointer-events:none，只有卡片可交互。
   早先让 .mtour 铺满全屏且可接收事件，结果它把整个后台的鼠标操作全挡住了 ——
   地图类回归（拖动平移 / 点选落点）集体挂掉，因为点击全落在这层透明墙上。
   用户也不该被一个"介绍"锁死手。镂空高亮框本来就是 pointer-events:none。 */
.mtour { position: fixed; inset: 0; z-index: 1250; pointer-events: none; }
.mtour[style*="display: none"] { display: none; }
.mtour__card { pointer-events: auto; }
/* 镂空高亮：一圈描边 + 向外铺满的暗场，中间留亮。
   ⚠️ 过渡放在 left/top/width/height 上，跟随目标平滑移动 */
.mtour__hole {
  position: fixed; border-radius: 10px; pointer-events: none;
  border: 2px solid var(--accent);
  box-shadow: 0 0 0 9999px rgba(8, 7, 6, .62), 0 0 22px 4px color-mix(in srgb, var(--accent) 42%, transparent);
  transition: left .22s ease, top .22s ease, width .22s ease, height .22s ease;
}
.mtour__card {
  position: fixed; width: min(380px, calc(100vw - 28px));
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 13px; box-shadow: 0 18px 48px rgba(0, 0, 0, .42);
  overflow: hidden; opacity: 0; transform: translateY(6px);
  transition: opacity .18s ease, transform .18s ease;
}
.mtour__card.is-in { opacity: 1; transform: translateY(0); }
/* 没有可高亮的目标时（如最后一步）就居中，别赖在屏幕角落 */
.mtour__card.is-center { top: 50%; left: 50%; transform: translate(-50%, -50%); }
.mtour__card.is-center.is-in { transform: translate(-50%, -50%); }
.mtour__bar { height: 3px; background: var(--surface-2); }
.mtour__barin { height: 100%; width: 0; background: var(--accent); transition: width .22s ease; }
.mtour__top { display: flex; align-items: center; gap: 8px; padding: 9px 12px 4px; }
.mtour__k { font-size: 11px; color: var(--accent); font-weight: 600; font-variant-numeric: tabular-nums; }
.mtour__crumb { font-size: 10.5px; padding: 1px 7px; border-radius: 999px; border: 1px solid var(--line); color: var(--text-dim); }
.mtour__x { margin-left: auto; border: 0; background: transparent; color: var(--text-dim); cursor: pointer; padding: 3px; border-radius: 6px; display: inline-flex; }
.mtour__x:hover { color: var(--text); background: var(--surface-2); }
.mtour__title { margin: 2px 12px 6px; font-family: var(--serif); font-size: 17px; color: var(--text-strong); }
.mtour__body { padding: 0 12px; font-size: 13px; line-height: 1.85; color: var(--text); }
.mtour__body b { color: var(--accent); }
.mtour__entry { padding: 7px 12px 0; font-size: 11.5px; color: var(--text-dim); line-height: 1.7; }
.mtour__acts { display: flex; align-items: center; gap: 8px; padding: 12px; margin-top: 6px; }
/* ==========================================================================
   2026-10-18 左下角个人信息抽屉（入口 + 从左向右拉出的面板）
   --------------------------------------------------------------------------
   侧栏底部原来堆了「当前账号 + 修改密码 + 新手引导」三块，挤成一团；
   现在只留一枚入口（头像 + 姓名 + 角色），其余全搬进抽屉。
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**。
   ========================================================================== */
.sidebar__me {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 10px; margin: 0; border: 1px solid transparent; border-radius: 11px;
  background: transparent; color: inherit; font: inherit; text-align: left; cursor: pointer;
  transition: background .16s ease, border-color .16s ease;
}
.sidebar__me:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); border-color: var(--line); }
.sidebar__me:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* 左下角邮箱单行不换行（用户 2026-10-19 明确要求）：超长部分用 … 收尾。
   同样必须带 min-width:0，否则 flex 子项会被长邮箱顶宽、省略号失效。 */
.sidebar__me #who {
  display: block; font-weight: 600; color: var(--text-strong); font-size: 12.5px;
  line-height: 1.3;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.sidebar__me .sidebar__role { display: block; font-size: 11px; color: var(--muted-dim); margin-top: 1px; }
.sidebar__me .sidebar__who-main { flex: 1 1 auto; min-width: 0; }
.sidebar__me-caret { flex: none; color: var(--text-dim); opacity: .7; }
/* 折叠成图标轨时：入口收成一枚头像按钮，文字与箭头都让位 */
.layout.left-collapsed .sidebar__me { justify-content: center; padding: 6px 0; }
.layout.left-collapsed .sidebar__me .sidebar__who-main,
.layout.left-collapsed .sidebar__me-caret { display: none; }

/* ---- 抽屉本体 ----
   🔴 容器整体 pointer-events:none 是引导浮层那条铁律的同款：
      这里遮罩要能点，所以只有**遮罩和面板**收事件，容器自己不收 ——
      否则关闭状态下这块透明层会盖住整个后台（20261018a 引导踩过同样的坑）。 */
.medrawer { position: fixed; inset: 0; z-index: 1150; pointer-events: none; }
.medrawer[style*="display: none"] { display: none; }
.medrawer__scrim {
  position: absolute; inset: 0; pointer-events: auto;
  background: rgba(8, 7, 6, .5); opacity: 0; transition: opacity .24s ease;
}
.medrawer.is-open .medrawer__scrim { opacity: 1; }
.medrawer__panel {
  position: absolute; top: 0; left: 0; bottom: 0; width: min(340px, 88vw);
  pointer-events: auto; display: flex; flex-direction: column;
  background: var(--surface); border-right: 1px solid var(--line);
  box-shadow: 0 0 44px rgba(0, 0, 0, .38);
  transform: translateX(-100%); transition: transform .26s cubic-bezier(.22, .8, .2, 1);
}
.medrawer.is-open .medrawer__panel { transform: translateX(0); }
@media (prefers-reduced-motion: reduce) {
  .medrawer__panel, .medrawer__scrim { transition: none; }
}
.medrawer__hd {
  display: flex; align-items: center; gap: 11px; padding: 16px 16px 14px;
  border-bottom: 1px solid var(--line);
}
.medrawer__av {
  flex: none; width: 42px; height: 42px; border-radius: 50%;
  display: grid; place-items: center; overflow: hidden;
  background: var(--surface-2); border: 1px solid var(--line);
  color: var(--text-strong); font-size: 17px; font-weight: 600;
}
/* 头像可能是上传的图：必须锁死尺寸，否则固有尺寸会把头部撑开 */
.medrawer__av img { width: 100%; height: 100%; object-fit: cover; display: block; }
.medrawer__id { min-width: 0; }
.medrawer__id strong {
  display: block; font-size: 14.5px; color: var(--text-strong);
  line-height: 1.35; word-break: break-all;
}
.medrawer__role {
  display: inline-block; margin-top: 4px; padding: 1px 8px; border-radius: 999px;
  border: 1px solid var(--line); font-size: 11px; color: var(--text-dim);
}
.medrawer__x {
  flex: none; border: 0; background: transparent; color: var(--text-dim);
  cursor: pointer; padding: 5px; border-radius: 8px; display: inline-flex;
}
.medrawer__x:hover { color: var(--text); background: var(--surface-2); }
.medrawer__body { flex: 1 1 auto; overflow-y: auto; padding: 6px 16px 24px; }
.medrawer__sec { padding: 14px 0 4px; }
.medrawer__sech {
  font-size: 11px; letter-spacing: .06em; color: var(--text-dim);
  margin-bottom: 9px; padding-bottom: 6px; border-bottom: 1px dashed var(--line);
}
.medrawer__kvs { display: grid; gap: 11px 14px; }
.medrawer__kv { display: grid; gap: 2px; min-width: 0; }
.medrawer__kv__k { font-size: 11.5px; color: var(--muted-dim); letter-spacing: .04em; }
.medrawer__kv__v {
  font-size: 13px; color: var(--text-strong); line-height: 1.6; overflow-wrap: anywhere;
}
.medrawer__acts { display: grid; gap: 8px; }
.medrawer__note {
  margin: 16px 0 0; padding: 10px 12px; border-radius: 9px;
  background: var(--surface-2); border-left: 3px solid var(--line);
  font-size: 11.5px; line-height: 1.75; color: var(--text-dim);
}
.medrawer__note:empty { display: none; }
/* 抽屉开着时锁住背后滚动，免得滚轮滚到列表上 */
body.me-open { overflow: hidden; }

/* ==========================================================================
   2026-10-18 形象档案 / M3 卡片内边距
   --------------------------------------------------------------------------
   .panel 全局只有边框、没有内边距（谁用谁自己补），所以 .ai-card 里的标题与
   键值网格原本是**直接贴着边框**的：上下左右全挤在一起、看不出区块边界。
   这里对齐 Skill 配置页「默认配置」板块的口径（.md-skill-card 的
   padding: 16px 18px 18px）—— 同类卡片用同一套内边距，视觉上才像一家人。
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**。
   ========================================================================== */
.ai-card { padding: 16px 18px 18px; }
/* 卡片自己有了内边距后，键值网格原先那点补偿性 padding 就成了多余的外扩 */
.ai-card > .ai-kvs { padding: 4px 0 2px; }
/* 卡片内的正文段（报告摘要 / 落地建议）原本自带 8px 下边距，够用；
   只有列表类内容（历史方案 / 反馈记录）首行需要离开标题一点距离。 */
.ai-card > .ai-list { margin-top: 2px; }
/* 窄屏下把左右内边距收窄，避免 390px 上内容被两侧各吃掉 18px */
@media (max-width: 640px) {
  .ai-card { padding: 14px 12px 15px; }
}

/* ==========================================================================
   2026-10-19  左下角顾问头像（真实上传图）
   --------------------------------------------------------------------------
   以前左下角只画首字圆块，顾问列表里上传的头像在这里完全看不到，
   抽屉里却又显示了真实图 —— 同一个人在两处长得不一样。
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**。
   ========================================================================== */
.sidebar__avatar img {
  width: 100%; height: 100%;
  object-fit: cover;
  border-radius: 10px;   /* 与容器同一圆角，否则直角会戳出容器 */
  display: block;
}

/* ==========================================================================
   2026-10-19  设置中心（模型设置 + 品牌设置）
   --------------------------------------------------------------------------
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**。
   ========================================================================== */

/* ---- 模型列表 ---- */
.ms-group { margin-top: 16px; }
.ms-group__h {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  font-size: 13px; font-weight: 700; color: var(--text-strong);
  padding-bottom: 8px; margin-bottom: 8px;
  border-bottom: 1px solid var(--line);
}
.ms-mrow {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px; margin-bottom: 8px;
  border: 1px solid var(--line); border-radius: 10px;
  background: color-mix(in srgb, var(--panel-bg-solid) 58%, transparent);
}
/* 云端模型是只读条目，视觉上要一眼区别于可编辑的本地模型 */
.ms-mrow--ro { background: transparent; border-style: dashed; }
.ms-mrow.is-off { opacity: .58; }
.ms-mrow__main { flex: 1 1 auto; min-width: 0; }
.ms-mrow__t {
  font-size: 13px; font-weight: 600; color: var(--text-strong);
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}
.ms-mrow__meta {
  margin-top: 3px; font-size: 11px; color: var(--muted-dim);
  font-family: var(--mono);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ms-mrow__acts { flex: none; display: flex; gap: 6px; flex-wrap: wrap; }
.ms-empty {
  padding: 14px 16px; border: 1px dashed var(--line); border-radius: 10px;
  font-size: 12px; color: var(--muted-dim); line-height: 1.8;
}
.ms-empty code {
  font-family: var(--mono); font-size: 11.5px;
  background: color-mix(in srgb, var(--panel-bg-solid) 58%, transparent); padding: 1px 5px; border-radius: 4px;
}
/* 类型标签：三类模型 + 云端 / 可识图 / 已停用，颜色按语义区分 */
.ms-tag {
  display: inline-block; flex: none;
  font-size: 10.5px; line-height: 1.6; padding: 0 6px;
  border-radius: 4px; border: 1px solid transparent;
  font-weight: 600; letter-spacing: .02em;
}
.ms-tag--text  { background: var(--accent-soft);  color: var(--accent);  border-color: color-mix(in srgb, var(--accent) 34%, transparent); }
.ms-tag--image { background: var(--info-soft);    color: var(--info);    border-color: color-mix(in srgb, var(--info) 34%, transparent); }
.ms-tag--video { background: var(--warn-soft);    color: var(--warn);    border-color: color-mix(in srgb, var(--warn) 34%, transparent); }
.ms-tag--embedding { background: color-mix(in srgb, var(--info) 16%, var(--ok-soft)); color: var(--ok); border-color: color-mix(in srgb, var(--ok) 34%, transparent); }
.ms-tag--audio { background: var(--muted-soft, var(--accent-soft)); color: var(--muted); border-color: var(--line); }
.ms-tag--cloud { background: var(--ok-soft);      color: var(--ok);      border-color: color-mix(in srgb, var(--ok) 34%, transparent); }
.ms-tag--vision{ background: transparent;         color: var(--muted-dim); border-color: var(--line); }
.ms-tag--off   { background: transparent;         color: var(--muted-dim); border-color: var(--line); }

/* ---- 模型弹窗内的表单 ---- */
.ms-form { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.ms-field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.ms-field > span { font-size: 12px; color: var(--muted); }
.ms-field--wide { grid-column: 1 / -1; }
#msf-msg { color: var(--danger); }

/* ---- 品牌设置 ---- */
/* 🆕 v1.16.6 R1：预览区从右侧独立栏挪到 Logo 字段下方，整块改为单栏纵向排列。
   旧版 grid 两栏（表单 | 预览），预览离 Logo 很远，用户看不出改了什么。 */
.ms-brand { display: block; }
.ms-brand__form { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.ms-logo { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* 🆕 v1.16.4 R1：Logo 预览框（88px），替代旧 46px 的死占位块。
   无图 = 虚线占位（点击选文件）；有图 = 图片预览（点击看大图）。
   🆕 v1.16.6 R1：position:relative 作为右上角 X 的定位锚点。 */
.ms-logo__pv {
  position: relative;
  flex: none; width: 88px; height: 88px; border-radius: 12px; padding: 0;
  display: grid; place-items: center; overflow: hidden;
  border: 1px dashed var(--line); background: color-mix(in srgb, var(--panel-bg-solid) 58%, transparent);
  color: var(--muted-dim); cursor: pointer; font: inherit;
  transition: border-color .16s ease, color .16s ease;
}
.ms-logo__pv:hover { border-color: var(--accent); color: var(--accent); }
.ms-logo__pv.is-filled { border-style: solid; border-color: var(--line-soft); cursor: zoom-in; }
.ms-logo__pv.is-filled:hover { border-color: var(--accent); }
/* 🆕 v1.16.6 R1：预览图右上角清除按钮 —— 黑底白叉，48px 命中区（视觉 22px）。
   旧版是表单下方一个「清除」胶囊按钮，跟图片分离，用户看不出它清的是哪张图。 */
.ms-logo__x {
  position: absolute; top: 2px; right: 2px; z-index: 2;
  width: 22px; height: 22px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(0, 0, 0, .82); color: #fff;
  font-size: 15px; line-height: 1; font-weight: 400;
  cursor: pointer; user-select: none;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .35);
  transition: background .14s ease, transform .14s ease;
}
.ms-logo__x:hover { background: #000; transform: scale(1.08); }
.ms-logo__ph { display: flex; flex-direction: column; align-items: center; gap: 4px; font-size: 12px; }
.ms-logo__ph i { font-style: normal; font-size: 22px; font-weight: 300; line-height: 1; }
.ms-logo__ph em { font-style: normal; }
.ms-logo__pv img { width: 100%; height: 100%; object-fit: contain; display: block; }
.ms-logo__box img { width: 100%; height: 100%; object-fit: contain; display: block; }
.ms-brand__preview { min-width: 0; }
.ms-brand__stage {
  border: 1px dashed var(--line); border-radius: 12px;
  padding: 14px 16px; background: color-mix(in srgb, var(--panel-bg-solid) 58%, transparent);
}
.ms-brand__stage .ms-pv { display: flex; align-items: center; gap: 10px; }
.ms-brand__stage .ms-pv__mark {
  flex: none; width: 34px; height: 34px; border-radius: 9px; overflow: hidden;
  display: grid; place-items: center;
  background: linear-gradient(140deg, var(--accent), color-mix(in srgb, var(--accent) 55%, #000));
  color: var(--accent-ink); font-family: var(--serif); font-weight: 700; font-size: 15px;
}
.ms-brand__stage .ms-pv__mark img { width: 100%; height: 100%; object-fit: contain; display: block; }
.ms-brand__stage .ms-pv__txt { min-width: 0; display: flex; flex-direction: column; }
.ms-brand__stage .ms-pv__name {
  font-size: 14px; font-weight: 700; color: var(--text-strong);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ms-brand__stage .ms-pv__work {
  font-size: 11.5px; color: var(--muted-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ---- 通用字段 / 动作行（设置中心与素材中心共用） ---- */
.st-field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.st-field > span { font-size: 12px; color: var(--muted); }
.st-field > span em { font-style: normal; }
.st-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.st-actions .tiny { min-height: 18px; }
.st-err { color: var(--danger); }
.st-warn { color: var(--warn); }

@media (max-width: 860px) {
  .ms-brand { grid-template-columns: 1fr; }
  .ms-form { grid-template-columns: 1fr; }
  .ms-mrow { flex-direction: column; align-items: stretch; }
  .ms-mrow__acts { justify-content: flex-end; }
}

/* ==========================================================================
   2026-10-19  AI 素材中心
   --------------------------------------------------------------------------
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**。
   ========================================================================== */
.st-note { color: var(--muted-dim); }

/* ---- 照片墙（瀑布流：CSS columns，图片高度由内容决定） ---- */
.st-masonry { columns: 4; column-gap: 12px; }
/* 🔴 v1.16.41 用户第 1 / 2 项：作品墙改「JS 分列 + flex 列容器」的瀑布流。
   为什么弃用 CSS columns：列高平衡算法在「单张卡片比均分高度还高」时会**少用一列**
   —— 实测 1108px 宽的墙、6 条竖屏视频只铺了 3 列 268px，右侧整块空着（用户第 2 项）。
   现在列数由 JS 按容器宽度算（1~4），卡片轮流进列，有几列就每列都有内容。 */
.st-flow { display: flex; gap: 12px; align-items: flex-start; }
.st-flow__col { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 12px; }
.st-flow .st-card,
.st-flow .st-vcard { margin: 0; width: 100%; }
/* 视频封面按素材自身比例显示（不能写死 9:16，横屏素材会被裁成竖条） */
.st-flow .st-vcard .st-card__media > img {
  aspect-ratio: auto; height: auto; object-fit: contain; background: #0b0a09;
}
.st-card {
  break-inside: avoid;           /* 卡片被拆到两列是瀑布流最常见的翻车点 */
  margin: 0 0 12px;
  position: relative;
  border: 1px solid var(--line); border-radius: 12px; overflow: hidden;
  background: color-mix(in srgb, var(--panel-bg-solid) 58%, transparent);
  cursor: zoom-in;
  transition: border-color .16s ease, transform .16s ease;
}
.st-card:hover { border-color: var(--accent); transform: translateY(-2px); }
.st-card > img { display: block; width: 100%; height: auto; }
/* 🆕 2026-10-22 需求 3：图片包进 .st-card__media（蒙版与按钮组的定位基准）。
   选择器必须写成 .st-card__media > img —— 旧的 `.st-card > img` 在加了包裹层之后
   一条都匹配不到，照片会整片丢样式。 */
.st-card__media { position: relative; }
.st-card__media > img { display: block; width: 100%; height: auto; }
.st-card figcaption {
  display: flex; flex-direction: column; gap: 2px;
  padding: 8px 10px 10px;
}
.st-card figcaption b {
  font-size: 12px; color: var(--text-strong);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.st-card figcaption span { font-size: 10.5px; color: var(--muted-dim); }
/* 「做同款 / 删除」平时藏着，hover 才出现 —— 墙上全挂按钮会糊成一片。
   🆕 2026-10-22 需求 3（用户报障）：旧实现把按钮组贴在卡片**底部**，
   与作品名称（figcaption）重叠、两颗按钮紧挨着、层级还压在图下面。
   现在：**居中**浮在图片上的灰色蒙版里，与标题彻底分行；gap 管间距；
   z-index 高于蒙版与「自建」徽章。 */
.st-card__acts {
  position: absolute; left: 0; right: 0; top: 50%;
  display: flex; justify-content: center; align-items: center; gap: 8px;
  opacity: 0; transform: translateY(-50%) scale(.96);
  transition: opacity .16s ease, transform .16s ease;
  pointer-events: none; z-index: 3;
}
/* 🔴 视频卡 **必须**单独写一条 hover 规则：
   它内部复用了 .st-card__acts（按钮样式共用），但它的容器是 .st-vcard，
   只写 `.st-card:hover .st-card__acts` 匹配不到它 ——
   于是视频墙上那颗「做同款」永远停在 pointer-events:none，
   真实鼠标**根本点不到**（JS .click() 能绕过这层，所以离线单测会假通过）。 */
.st-card:hover .st-card__acts,
.st-vcard:hover .st-card__acts,
.st-card:focus-within .st-card__acts,
.st-vcard:focus-within .st-card__acts { opacity: 1; transform: translateY(-50%) scale(1); pointer-events: auto; }

/* ---- 视频墙（等比分列，封面 ≠ 瀑布流） ---- */
.st-vwall { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.st-vcard {
  position: relative;
  border: 1px solid var(--line); border-radius: 12px; overflow: hidden;
  background: color-mix(in srgb, var(--panel-bg-solid) 58%, transparent); cursor: pointer;
  transition: border-color .16s ease, transform .16s ease;
}
.st-vcard:hover { border-color: var(--accent); transform: translateY(-2px); }
.st-vcard .st-card__media > img { display: block; width: 100%; aspect-ratio: 9 / 16; object-fit: cover; }
.st-vcard__play {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 44px; height: 44px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(0, 0, 0, .42); color: #fff;
  backdrop-filter: blur(2px);
  pointer-events: none;
}
.st-vcard figcaption {
  display: flex; flex-direction: column; gap: 2px; padding: 8px 10px 10px;
}
.st-vcard figcaption b {
  font-size: 12px; color: var(--text-strong);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.st-vcard figcaption span { font-size: 10.5px; color: var(--muted-dim); }
/* ---- 生成台 ---- */
.st-form { display: flex; flex-direction: column; gap: 14px; }
.st-ta { resize: vertical; min-height: 92px; line-height: 1.7; }
.st-params { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; }

/* ---- 我的作品 ---- */
/* 🆕 2026-10-22 需求 9：不再写死 aspect-ratio:1/1 正方形窗口。
   比例由 JS 按生成时记录的 params.ratio 内联给出（加载前的占位），
   图片 / 视频就绪后再按**真实像素**校正一次（naturalWidth/Height、
   videoWidth/Height）；记录里没存比例（auto）也不退化成方块，
   而是让图片按自然高度排布。
   🆕 2026-10-22 需求 7：本区块的**排列方式**（瀑布流）与 stage 内图片尺寸
   已整体迁到文件末尾的「需求 7」段 —— 此处只留卡片外框与占位样式，
   避免同一件事有两处定义（改一处忘另一处 = 样式打架）。 */
.st-work {
  margin: 0; border: 1px solid var(--line); border-radius: 12px; overflow: hidden;
  background: color-mix(in srgb, var(--panel-bg-solid) 58%, transparent);
  display: flex; flex-direction: column;
}
.st-work__stage {
  position: relative; aspect-ratio: auto; min-height: 140px;
  background: color-mix(in srgb, var(--bg) 62%, #000);
  cursor: zoom-in; overflow: hidden;
}
.st-work__ph {
  width: 100%; height: 100%; display: grid; place-items: center;
  font-size: 12px; color: var(--muted-dim);
}
.st-work__badge {
  position: absolute; left: 6px; top: 6px;
  font-size: 10px; padding: 1px 6px; border-radius: 4px;
  background: rgba(0, 0, 0, .5); color: #fff;
}
.st-work figcaption {
  display: flex; flex-direction: column; gap: 2px; padding: 8px 10px 4px;
  min-width: 0;
}
.st-work figcaption b {
  font-size: 12px; color: var(--text-strong);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.st-work figcaption span {
  font-size: 10.5px; color: var(--muted-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.st-work__acts { display: flex; gap: 6px; padding: 6px 10px 10px; }

@media (max-width: 1180px) {
  .st-masonry { columns: 3; }
  .st-params { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 860px) {
  .st-masonry { columns: 2; }
  .st-vwall { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .st-params { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* 触屏没有 hover：按钮必须常驻，否则「做同款」根本点不到。
     🆕 需求 3：按钮组改成居中浮层后，触屏 fallback 用 position:static
     让它回到图片下方的文档流里（不再绝对定位，也就不可能与标题重叠）。 */
  .st-card__acts { opacity: 1; transform: none; pointer-events: auto; position: static; margin: 8px; }
}
@media (max-width: 560px) {
  .st-masonry { columns: 1; }
  .st-vwall { grid-template-columns: 1fr; }
  .st-params { grid-template-columns: 1fr; }
}

/* ==========================================================================
   2026-10-19  素材灯箱（看图 / 播视频）
   --------------------------------------------------------------------------
   🔴 容器 pointer-events:none、只有卡片 auto —— 与新手引导浮层同款铁律：
      全屏容器若不穿透，会把下方页面的所有交互一起吃掉。
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**。
   ========================================================================== */
.st-lb { position: fixed; inset: 0; z-index: 1300; }
.st-lb__scrim {
  position: absolute; inset: 0;
  background: rgba(6, 6, 8, .82);
  backdrop-filter: blur(3px);
}
.st-lb__box {
  position: relative; z-index: 1;
  height: 100%;
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr) 56px;
  grid-template-rows: minmax(0, 1fr) auto;
  align-items: center;
  padding: 22px 12px 18px;
  pointer-events: none;
}
.st-lb__stage {
  grid-column: 2; grid-row: 1;
  justify-self: center; align-self: center;
  max-height: 100%; max-width: 100%;
  display: grid; place-items: center;
  pointer-events: auto;
}
.st-lb__stage > img,
.st-lb__stage > video {
  max-width: 100%; max-height: 74vh;
  border-radius: 10px; display: block;
  object-fit: contain;
  box-shadow: 0 18px 48px rgba(0, 0, 0, .5);
}
.st-lb__nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 40px; height: 40px; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .22);
  background: rgba(255, 255, 255, .1);
  color: #fff; font-size: 22px; line-height: 1;
  cursor: pointer; pointer-events: auto;
}
.st-lb__nav:hover { background: rgba(255, 255, 255, .2); }
.st-lb__nav--prev { left: 10px; }
.st-lb__nav--next { right: 10px; }
.st-lb__x {
  position: absolute; right: 14px; top: 14px;
  width: 34px; height: 34px; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .22);
  background: rgba(255, 255, 255, .1); color: #fff;
  cursor: pointer; pointer-events: auto; line-height: 1;
}
.st-lb__x:hover { background: rgba(255, 255, 255, .2); }
.st-lb__foot {
  grid-column: 1 / -1; grid-row: 2;
  display: flex; align-items: center; gap: 12px;
  max-width: 760px; width: 100%; margin: 12px auto 0;
  padding: 0 6px;
  pointer-events: auto;
}
.st-lb__cap {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column; gap: 2px; color: #fff;
}
.st-lb__cap b {
  font-size: 13px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.st-lb__cap span {
  font-size: 11px; color: rgba(255, 255, 255, .62);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body.st-lb-open { overflow: hidden; }
@media (max-width: 640px) {
  .st-lb__box { grid-template-columns: 44px minmax(0, 1fr) 44px; padding: 16px 8px 14px; }
  .st-lb__stage > img, .st-lb__stage > video { max-height: 62vh; }
  .st-lb__nav { width: 32px; height: 32px; font-size: 18px; }
  .st-lb__foot { flex-direction: column; align-items: stretch; }
  .st-lb__cap b, .st-lb__cap span { white-space: normal; }
}

/* ============================== 20261019b：品牌 Logo 修复 ============================== */
/* 🔴 .brand-mark 是 32×32 的 display:grid 容器，applyBrand() 把 <img> 塞进去后
   img 没有尺寸约束 —— width:100% 在 grid 容器里退化成固有宽度（可能上千 px），
   直接把顶栏撑爆或缩成 1×1（与左侧栏头像 1×1 是同一类坑，见铁律）。
   规则必须放在所有 @media 之后（追加规则铁律）。 */
.brand-mark--img {
  background: none;
  box-shadow: 0 0 0 1px var(--panel-border-strong, var(--line));
  overflow: hidden;
}
.brand-mark--img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 9px;
  display: block;
}

/* ====================== 20261019b：供应商 + 模型通道 ====================== */
/* 通道总览卡（三用途并排） */
.ms-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px; margin: 14px 0 4px; }
.ms-card { border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; background: var(--panel-bg-solid); min-width: 0; }
.ms-card__h { font-weight: 600; font-size: 13px; margin-bottom: 8px; display: flex; align-items: baseline; gap: 8px; }
.ms-card__list { display: flex; flex-direction: column; gap: 6px; }
.ms-card__row { display: flex; align-items: center; gap: 8px; min-width: 0; }
.ms-card__nm { font-size: 12.5px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1 1 auto; }
.ms-card__meta { font-size: 11px; color: var(--muted); flex: none; }
.ms-card__empty { font-size: 12px; color: var(--muted); line-height: 1.7; }
/* 表格包装与状态徽章 */
.ms-twrap { overflow-x: auto; }
.ms-tbl { font-size: 13px; }
.ms-tbl th { font-size: 12px; white-space: nowrap; }
.ms-tbl tr.is-off td { opacity: .55; }
.ms-tstate { display: inline-block; font-size: 11px; padding: 2px 8px; border-radius: 999px; background: var(--muted-soft, var(--accent-soft)); color: var(--muted); white-space: nowrap; }
.ms-tstate--ok { background: var(--ok-soft); color: var(--ok); }
.ms-tstate--warn { background: var(--warn-soft); color: var(--warn); }
.ms-tstate--bad { background: var(--danger-soft, var(--warn-soft)); color: var(--danger, var(--warn)); }
.ms-tstate--na { background: var(--info-soft); color: var(--info); }
.ms-tnt { max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ms-url { max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ms-acts { display: inline-flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
/* 主通道 / 已添加标签 */
.ms-tag--primary { background: var(--accent); color: var(--accent-ink); border-color: transparent; }
.ms-tag--ok { background: var(--ok-soft); color: var(--ok); }
/* 供应商预设网格 */
.ms-pcards { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 12px; }
.ms-pcard { border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; background: var(--panel-bg-solid); display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.ms-pcard__h { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.ms-pcard__note { font-size: 12px; color: var(--muted); line-height: 1.65; min-height: 32px; }
.ms-pcard__url { color: var(--muted); word-break: break-all; }
.ms-pcard__models { display: flex; flex-wrap: wrap; gap: 5px; }
/* 表单 */
.ms-req { color: var(--danger); font-style: normal; }
.ms-form .ms-field em { display: block; font-style: normal; margin-top: 3px; }
/* 响应式 */
@media (max-width: 860px) {
  .ms-cards { grid-template-columns: 1fr; }
  .ms-pcards { grid-template-columns: 1fr; }
}

/* ====================== 20261019c：素材中心 v1.4.0 ====================== */
/* ⚠️ 依项目铁律：本段追加在**所有 @media 之后**；后续要覆盖这里的规则，
   也必须继续往后追加，禁止插回文件中部。 */

/* ---- 墙 tab（图片墙 / 视频墙，带图标） ---- */
.st-walltabs { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.st-walltabs .seg__btn { display: inline-flex; align-items: center; gap: 6px; }
.st-walltabs .seg__btn svg { flex: none; }

/* ---- 自建预设徽章 ---- */
.st-card__badge {
  position: absolute; left: 6px; top: 6px; z-index: 1;
  font-size: 10px; padding: 1px 7px; border-radius: 4px;
  background: var(--accent); color: var(--accent-ink);
}

/* ---- 比例宫格（带矩形示意图） ----
   🔴 放在 st-params **外面**整行铺开：塞回 5 列参数网格里一格只有 ~180px，
   宫格会挤成三行碎块。按钮横排、矩形按真实比例画。 */
.st-ratio-wrap { margin-top: 2px; }
.st-ratios { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.st-ratio {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 12px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--panel-bg-solid); cursor: pointer;
  font-size: 12px; color: var(--muted);
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.st-ratio:hover { border-color: var(--accent); color: var(--text-strong); }
.st-ratio.is-on { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.st-rect { display: block; border: 1.5px solid currentColor; border-radius: 3px; flex: none; }

/* ---- 生成台参数行：比例挪走后只剩 4 项 ---- */
.st-params { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1180px) {
  .st-params { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .st-params { grid-template-columns: 1fr; }
}

/* ---- 视频时长拖动条 ---- */
.st-slider { display: flex; align-items: center; gap: 10px; }
.st-slider input[type="range"] { flex: 1 1 auto; min-width: 0; accent-color: var(--accent); }
.st-slider__end { flex: none; min-width: 28px; text-align: center; font-size: 11px; color: var(--muted); }
.st-slider__val { margin-top: 6px; font-size: 12px; color: var(--muted); }
.st-slider__val b { color: var(--accent); font-size: 14px; }

/* ---- 灯箱改双栏：舞台 + 详情侧栏 ----
   🔴 旧版是三列 grid（导航/舞台/导航），v1.4.0 改 flex 双栏后必须把
   .st-lb__stage 上的 grid-column/grid-row 显式归 auto，否则它作为
   .st-lb__main 的网格子项会隐式造列，布局直接崩。 */
.st-lb__box { display: flex; }
.st-lb__main {
  position: relative; flex: 1 1 auto; min-width: 0; height: 100%;
  display: grid; place-items: center;
}
.st-lb__stage {
  grid-column: auto; grid-row: auto;
  max-height: 100%; max-width: 100%;
  display: grid; place-items: center;
  pointer-events: auto;
}
.st-lb__side {
  flex: 0 0 380px; max-width: 42vw;
  height: calc(100% - 6px);
  margin: 3px 0 3px 12px;
  overflow-y: auto;
  background: var(--panel-bg-solid);
  border: 1px solid var(--line); border-radius: 14px;
  padding: 16px 18px 20px;
  pointer-events: auto;
}
.st-lb__sidehead { display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px; }
.st-lb__sidehead > b { font-size: 15px; color: var(--text-strong); overflow-wrap: anywhere; }
.st-lb__acts { display: flex; flex-wrap: wrap; gap: 8px; }
.st-dl { display: flex; flex-direction: column; border-top: 1px solid var(--line); }
.st-dl__row {
  display: flex; justify-content: space-between; gap: 12px;
  padding: 7px 2px; border-bottom: 1px solid var(--line); font-size: 12.5px;
}
.st-dl__row > span { color: var(--muted); flex: none; }
.st-dl__row > b { font-weight: 500; color: var(--text-strong); text-align: right; min-width: 0; overflow-wrap: anywhere; }
.st-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.st-tags i {
  font-style: normal; font-size: 11px; padding: 2px 8px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent);
}
.st-lb__block { margin-top: 14px; }
.st-lb__block > span { display: block; font-size: 12px; color: var(--muted); margin-bottom: 6px; }
.st-lb__block > p {
  margin: 0; font-size: 12.5px; line-height: 1.75;
  background: var(--bg); border: 1px solid var(--line); border-radius: 10px;
  padding: 10px 12px; white-space: pre-wrap; overflow-wrap: anywhere;
  max-height: 190px; overflow-y: auto;
}
.st-var { display: flex; gap: 10px; font-size: 12.5px; padding: 5px 0; }
.st-var b { flex: none; color: var(--text-strong); }
.st-var span { color: var(--muted); overflow-wrap: anywhere; }
@media (max-width: 960px) {
  .st-lb__box { flex-direction: column; overflow-y: auto; }
  .st-lb__main { flex: none; height: auto; }
  .st-lb__stage > img, .st-lb__stage > video { max-height: 48vh; }
  .st-lb__side { flex: none; width: 100%; max-width: 100%; height: auto; max-height: none; margin: 12px 0 0; }
}

/* ---- 手动添加预设弹窗 ---- */
.st-pd { position: fixed; inset: 0; z-index: 1280; }
.st-pd__scrim { position: absolute; inset: 0; background: rgba(6, 6, 8, .62); backdrop-filter: blur(2px); }
.st-pd__box {
  position: relative; z-index: 1;
  width: min(680px, calc(100vw - 32px));
  max-height: calc(100vh - 48px);
  margin: 24px auto 0;
  display: flex; flex-direction: column;
  background: var(--panel-bg-solid);
  border: 1px solid var(--line); border-radius: 16px;
  box-shadow: 0 24px 64px rgba(0, 0, 0, .4);
  pointer-events: auto;
}
.st-pd__head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px; border-bottom: 1px solid var(--line);
  background: transparent;
}
.st-pd__body {
  padding: 16px 18px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 12px;
}
.st-pd__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.st-pd__prev { margin-top: 8px; }
.st-pd__prev img {
  max-width: 180px; max-height: 180px; display: block;
  border-radius: 10px; border: 1px solid var(--line);
}
.st-pd__foot {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 18px; border-top: 1px solid var(--line);
}
@media (max-width: 640px) {
  .st-pd__grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   20261019d（v1.5.0）模型设置三分区 tab + 云端倍率显示 + 列表限高
   ========================================================================== */
.ms-tabs {
  display: flex; align-items: center; gap: 6px;
  margin: 2px 0 14px; flex-wrap: wrap;
}
.ms-tab {
  appearance: none; border: 1px solid var(--line);
  background: var(--panel-bg-solid, #fff);
  color: var(--text); border-radius: 999px;
  padding: 7px 16px; font-size: 13px; cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.ms-tab:hover { border-color: var(--accent, #a4813c); }
.ms-tab--on {
  background: var(--accent, #a4813c); border-color: var(--accent, #a4813c);
  color: #fff; font-weight: 600;
}
/* 用途卡内的通道列表：超过最大高度出滚动条（🔴 顶部列表太长把页面顶爆） */
.ms-card__list {
  max-height: 380px; overflow-y: auto;
  padding-right: 2px;
}
.ms-card__list::-webkit-scrollbar { width: 6px; }
.ms-card__list::-webkit-scrollbar-thumb {
  background: var(--line); border-radius: 3px;
}

/* ==========================================================================
   20261020a（v1.6.0）素材中心：灯箱缩放 + 中英提示词分别复制 + 自定义图片上传
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**。
   ========================================================================== */
/* ---- 灯箱舞台：缩放容器 ---- */
.st-lb__main { overflow: hidden; }
.st-lb__stage > img,
.st-lb__stage > video {
  transition: transform .16s ease;
  will-change: transform;
  touch-action: pinch-zoom;
}
.st-lb__stage > img.is-zoomed { cursor: zoom-out; }
.st-zoom {
  position: absolute; left: 50%; bottom: 12px; transform: translateX(-50%);
  display: flex; align-items: center; gap: 2px;
  padding: 4px 6px; border-radius: 999px;
  background: rgba(22, 20, 18, .66);
  border: 1px solid rgba(255, 255, 255, .18);
  backdrop-filter: blur(6px);
  pointer-events: auto; z-index: 2;
}
.st-zoom__btn {
  min-width: 30px; height: 28px; padding: 0 8px;
  border: 0; border-radius: 999px; background: transparent;
  color: #fff; font-size: 15px; line-height: 1; cursor: pointer;
}
.st-zoom__btn:hover { background: rgba(255, 255, 255, .18); }
.st-zoom__btn--reset { font-size: 11.5px; color: rgba(255, 255, 255, .82); }
.st-zoom__v {
  min-width: 46px; text-align: center;
  color: rgba(255, 255, 255, .88); font-size: 11.5px;
  font-variant-numeric: tabular-nums;
}
.st-zoom__hint {
  position: absolute; right: 14px; bottom: 16px;
  font-size: 11px; color: rgba(255, 255, 255, .48);
  pointer-events: none; transition: opacity .2s ease;
}

/* ---- 提示词区块：标题行 + 就地复制反馈 ---- */
.st-pb__h {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 6px;
}
.st-pb__h > span { font-size: 12px; color: var(--muted); }
.st-pb__copy { padding: 2px 10px; font-size: 11.5px; }
.st-pb__copy.is-done {
  border-color: #3d7a5b; color: #3d7a5b;
  background: rgba(61, 122, 91, .1);
}

/* ---- 添加预设：自定义图片上传控件（替代系统文件按钮） ---- */
.st-pickrow { display: flex; gap: 12px; align-items: flex-start; flex-wrap: wrap; }
.st-pick {
  position: relative; flex: none;
  width: 168px; height: 168px; padding: 0;
  display: grid; place-items: center;
  border: 1.5px dashed var(--line); border-radius: 12px;
  background: var(--bg); color: var(--muted);
  cursor: pointer; overflow: hidden;
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.st-pick:hover { border-color: var(--accent); color: var(--accent); }
.st-pick__ph {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  font-size: 12px; line-height: 1.2;
}
.st-pick__ph b { font-weight: 500; }
.st-pick__ph i { font-style: normal; font-size: 10.5px; opacity: .72; }
.st-pick > img { width: 100%; height: 100%; object-fit: cover; display: block; }
.st-pick__side { display: flex; flex-direction: column; gap: 8px; }
@media (max-width: 640px) {
  .st-pick { width: 132px; height: 132px; }
}

/* ---- 20261020a：出生日期（整块可点）+ 自绘日历 ---- */
.cf-date-wrap { position: relative; }
.cf-date-wrap .cf-date { padding-right: 34px; cursor: pointer; }
.cf-date__ico {
  position: absolute; right: 11px; top: 50%; transform: translateY(-50%);
  color: var(--muted); pointer-events: none;
}
.cf-date.is-open { border-color: var(--accent); }
.cfdp {
  position: fixed; z-index: 1400; width: 268px;
  padding: 10px 10px 8px;
  background: var(--panel-bg-solid, #fff);
  border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, .24);
}
.cfdp__head { display: flex; align-items: center; gap: 4px; margin-bottom: 8px; }
.cfdp__head b { flex: 1; text-align: center; font-size: 13px; color: var(--text-strong); }
.cfdp__nav {
  width: 26px; height: 26px; border: 0; border-radius: 8px;
  background: transparent; color: var(--muted);
  cursor: pointer; font-size: 14px; line-height: 1;
}
.cfdp__nav:hover { background: var(--accent-soft); color: var(--accent); }
.cfdp__week, .cfdp__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.cfdp__week span { text-align: center; font-size: 10.5px; color: var(--muted); padding: 3px 0; }
.cfdp__cell {
  height: 30px; border: 0; border-radius: 8px;
  background: transparent; color: var(--text);
  font-size: 12.5px; cursor: pointer;
}
.cfdp__cell.is-empty { cursor: default; }
.cfdp__cell:hover:not(.is-empty):not(.is-on) { background: var(--accent-soft); }
.cfdp__cell.is-today { color: var(--accent); font-weight: 600; }
.cfdp__cell.is-on { background: var(--accent); color: var(--accent-ink, #fff); font-weight: 600; }
.cfdp__foot {
  display: flex; align-items: center; gap: 8px;
  margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line);
}

/* ---- 20261020a：验证码 60 秒倒计时态 ---- */
.btn.is-counting,
.btn:disabled.is-counting {
  opacity: .72; cursor: not-allowed;
  font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   20261020b（v1.6.1）模型设置：顶部行内三分区 tab（带数量）+ 积分倍率高亮
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**，不插到中间。
   ========================================================================== */
/* 三个 tab 按钮直接落在工具栏那一行；不再有「分区」标签与竖分隔线 */
.ms-tabs--inline {
  display: flex; align-items: center; gap: 6px;
  margin: 0; flex-wrap: wrap; min-width: 0;
}
/* tab 按钮里的数量徽章 */
.ms-tab__n {
  display: inline-block; margin-left: 6px;
  min-width: 18px; padding: 0 6px;
  border-radius: 999px; text-align: center;
  font-size: 11px; font-weight: 700; line-height: 1.6;
  background: var(--accent-soft); color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  font-variant-numeric: tabular-nums;
}
.ms-tab--on .ms-tab__n {
  background: rgba(255, 255, 255, .26);
  color: #fff;
  border-color: rgba(255, 255, 255, .42);
}
/* 积分倍数徽章：贴在模型名称右侧；免费特别高亮 */
.ms-card__hd {
  display: flex; align-items: center; gap: 0;
  min-width: 0; flex: 1 1 auto;
}
/* 名称过长时只省略名称，倍数徽章始终完整可见 */
.ms-card__hd .ms-card__nm { flex: 0 1 auto; }
/* 供应商 / 优先级文案：回到**模型名称右侧、按钮左侧**，并右对齐。
   🔴 2026-10-21 用户纠正：上一版误把它换到第二行（flex:1 0 100%），必须撤回。 */
.ms-card__row { flex-wrap: nowrap; align-items: center; }
.ms-card__row .ms-card__hd { flex: 0 1 auto; }
.ms-card__row .ms-card__meta {
  flex: 1 1 auto;
  min-width: 0;
  text-align: right;
  font-size: 11px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 卡片放宽一点：名称 + 倍数徽章 + 按钮 一行放得下 */
.ms-cards { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.ms-credit {
  display: inline-block; margin-left: 6px; flex: none;
  padding: 0 7px; border-radius: 999px;
  font-size: 10.5px; font-weight: 700; line-height: 1.7;
  background: var(--info-soft); color: var(--info);
  border: 1px solid color-mix(in srgb, var(--info) 34%, transparent);
  font-variant-numeric: tabular-nums;
}
.ms-credit--free {
  background: var(--ok-soft);
  color: var(--ok);
  border-color: color-mix(in srgb, var(--ok) 46%, transparent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--ok) 14%, transparent);
}


/* ==========================================================================
   20261020c（v1.7.0）改密流程重做 + 顾问信息抽屉深色模式 + 头像圆角正方形
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**，不插到中间。
   ========================================================================== */

/* ---- ① 补齐后台缺失的主题令牌 ----
   🔴 根因：`--surface` / `--surface-2` / `--text-dim` / `--panel-soft`
      这些令牌**只在客户页 style.css 的浅色 :root 里定义过**（--surface:#FFFFFF），
      admin-hud.css 自己没定义 —— 于是深色主题下：
        · .medrawer__panel 背景 var(--surface) = 纯白（抽屉是白底）；
        · .medrawer__note / .mtour__bar 等 var(--surface-2) 全部落空（透明）；
        · 一切 var(--text-dim) 的次要文字继承成主文字色（层级全塌）。
      这里在**两套主题里各自补齐**，不改动 style.css（三页共用，禁改）。 */
[data-theme="dark"] {
  --surface: #1E1A17;
  --surface-2: rgba(232, 226, 216, .07);
  --surface-3: rgba(232, 226, 216, .12);
  --text-dim: #A09383;
  --panel-soft: rgba(232, 226, 216, .05);
  --muted-soft: rgba(232, 226, 216, .05);
}
[data-theme="light"] {
  --surface: #FFFDF9;
  --surface-2: rgba(46, 40, 32, .05);
  --surface-3: rgba(46, 40, 32, .09);
  --text-dim: #6F6455;
  --panel-soft: rgba(46, 40, 32, .035);
  --muted-soft: rgba(46, 40, 32, .035);
}

/* ---- ② 顾问信息抽屉：深色模式适配 ----
   抽屉是**侧边滑出**的浮层，不是页面容器：必须自带实底（不能透出背后的
   玻璃面板），否则深色下会看见侧栏网格穿过来。 */
.medrawer__panel {
  background: var(--surface);
  border-right: 1px solid var(--line);
  color: var(--text);
}
.medrawer__scrim { background: rgba(8, 7, 6, .62); }
.medrawer__hd { border-bottom: 1px solid var(--line); }
.medrawer__av {
  /* 头像统一为**圆角正方形**（与侧栏底部队友头像一致），
     不用 50% 圆形 —— 用户明确要求「圆角正方形头像」。 */
  border-radius: 12px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--text-strong);
}
.medrawer__av img { border-radius: 12px; }
.medrawer__role { color: var(--text-dim); border-color: var(--line); }
.medrawer__kv__k { color: var(--muted-dim); }
.medrawer__kv__v { color: var(--text-strong); }
.medrawer__note { background: var(--surface-2); border-left-color: var(--line); color: var(--text-dim); }
.medrawer__x { color: var(--text-dim); }
.medrawer__x:hover { color: var(--text); background: var(--surface-2); }

/* ---- ③ 头像统一圆角正方形 ----
   · 侧栏底部（.sidebar__avatar）本来就是 10px 圆角正方形，这里再钉一次，
     防止将来被别处覆盖回圆形；
   · 员工行 / 顾问卡片里的圆形徽章也一并转成圆角正方形，保持全站一致。 */
.sidebar__avatar,
.sidebar__avatar img { border-radius: 10px; }
.staff-row__ava .c-ava,
.staff-row__ini { border-radius: 10px; }
.c-card__ini b { border-radius: 22px; }

/* ---- ④ 改密弹窗 ----
   三个输入框（当前密码 / 新密码 / 确认新密码）一次呈现，
   旧密码填错原地提示，不必重走三步向导。 */
.pwd-form { margin-top: 14px; }
.pwd-form .field__hint { margin-top: 6px; }

/* ==========================================================================
   20261020c（v1.7.0）设置中心 · 数据备份
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**，不插到中间。
   ========================================================================== */
.bk-grid {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 18px; align-items: start;
}
.bk-col { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.bk-card {
  border: 1px solid var(--panel-border); border-radius: 14px;
  background: var(--panel-bg); padding: 16px 18px 18px;
}
.bk-card--note { background: var(--panel-soft); }
.bk-card__hd { font-size: 14px; color: var(--text-strong); margin-bottom: 8px; }
.bk-card__d {
  font-size: 12.5px; line-height: 1.85; color: var(--muted);
  margin: 0 0 10px;
}
.bk-card__d:last-child { margin-bottom: 0; }
.bk-card__d code {
  font-family: var(--mono); font-size: 11.5px;
  padding: 1px 5px; border-radius: 5px;
  background: var(--surface-2); color: var(--text-strong);
}
.bk-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.bk-form { display: flex; flex-direction: column; gap: 12px; }
.bk-form .st-field > span { color: var(--muted); }
@media (max-width: 980px) {
  .bk-grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   20261021（v1.7.1）用户报障修复 —— 双模式 / 头像 / 卡片对齐 / 自定义下拉
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**，不插到中间。
   ========================================================================== */

/* ---- ① 帮助中心 + 新手引导：显式双模式兜底 ----
   🔴 用户 2026-10-21 明确：「以后任何新增的界面都需要支持双模式，不得遗漏」。
   .mhelp__* / .mtour__* 虽然都用了 var(--surface)，但 --surface 的浅色值来自
   style.css 的 :root（客户页三页共用文件），一旦加载顺序或变量回退出问题，
   浮层就会退回白底 —— 所以这里在**两套主题下写死兜底色**，不依赖跨文件继承。 */
[data-theme="dark"] .mhelp__box,
[data-theme="dark"] .mtour__card {
  background: #1E1A17;
  border-color: rgba(198, 162, 106, .20);
  color: #E8E2D8;
}
[data-theme="light"] .mhelp__box,
[data-theme="light"] .mtour__card {
  background: #FFFDF9;
  border-color: rgba(150, 120, 72, .22);
  color: #2E2820;
}
[data-theme="dark"] .mhelp__head,
[data-theme="dark"] .mtour__bar { background: rgba(232, 226, 216, .07); }
[data-theme="light"] .mhelp__head,
[data-theme="light"] .mtour__bar { background: rgba(46, 40, 32, .05); }
[data-theme="dark"] .mhelp__nav { background: rgba(232, 226, 216, .07); border-right-color: rgba(198, 162, 106, .18); }
[data-theme="light"] .mhelp__nav { background: rgba(46, 40, 32, .05); border-right-color: rgba(150, 120, 72, .22); }
[data-theme="dark"] .mhelp__doc { background: #1E1A17; }
[data-theme="light"] .mhelp__doc { background: #FFFDF9; }
/* 引导卡：文字层级在两套主题下分别给足对比度 */
[data-theme="dark"] .mtour__body,
[data-theme="dark"] .mtour__title { color: #E8E2D8; }
[data-theme="light"] .mtour__body,
[data-theme="light"] .mtour__title { color: #2E2820; }
[data-theme="dark"] .mtour__entry,
[data-theme="dark"] .mhelp__navhead,
[data-theme="dark"] .mhelp__todo-box { color: #A09383; }
[data-theme="light"] .mtour__entry,
[data-theme="light"] .mhelp__navhead,
[data-theme="light"] .mhelp__todo-box { color: #6F6455; }
/* 引导镂空外的暗场：浅色主题下也保持压暗，突出高亮目标 */
[data-theme="light"] .mtour__hole {
  box-shadow: 0 0 0 9999px rgba(30, 26, 23, .46), 0 0 22px 4px color-mix(in srgb, var(--accent) 42%, transparent);
}

/* ---- ② 左下角头像：明确「圆角正方形」 ----
   🔴 用户 2026-10-21 报「左下角头像还是没有改为圆角正方形」。
   32px 容器上 10px 圆角视觉上仍偏圆 → 收到 6px，正方形感明确；
   同时给容器加 overflow:hidden，保证真实上传图也被裁成圆角正方形。 */
.sidebar__avatar {
  border-radius: 6px !important;
  overflow: hidden;
}
.sidebar__avatar img {
  border-radius: 6px !important;
}
.layout.left-collapsed .sidebar__foot .sidebar__avatar {
  border-radius: 6px !important;
}

/* ---- ③ 供应商预设卡片：按钮统一贴卡片底部对齐 ----
   🔴 用户 2026-10-21 报「添加并填 Key 按钮高低不平」。
   .ms-pcard 是 flex column，把最后一个子元素推到底（margin-top:auto），
   同一行的卡片按钮就落在同一条基线上。 */
.ms-pcard { align-items: stretch; }
.ms-pcard > :last-child { margin-top: auto; }
.ms-pcard > .btn { align-self: flex-start; }

/* ---- ④ 自定义下拉框（替代原生 select）----
   🔴 用户 2026-10-21 报：原生 select 宽度不足、文字显示不全，
      且原生下拉列表会「盖住下拉框入口」。
   做法：自绘触发按钮 + 绝对定位浮层菜单；
   · 触发按钮宽度足够，文字完整不截断；
   · 浮层默认**向下**展开且 z-index 抬高，不遮挡触发按钮本体；
   · 浮层用 --surface/--line 令牌，自动跟随深浅主题。 */
.bk-sel {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  min-width: 208px;
  max-width: 100%;
}
.bk-sel__btn {
  display: flex; align-items: center; gap: 8px;
  width: 100%;
  padding: 8px 11px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--surface);
  color: var(--text);
  font: inherit; font-size: 12.5px;
  cursor: pointer;
  text-align: left;
  transition: border-color .15s ease, background .15s ease;
}
.bk-sel__btn:hover { border-color: var(--panel-border-strong); }
.bk-sel__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.bk-sel__txt { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bk-sel__caret { flex: none; color: var(--text-dim); font-size: 10px; transition: transform .15s ease; }
.bk-sel.is-open .bk-sel__caret { transform: rotate(180deg); }
.bk-sel__menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 1200;
  min-width: 100%;
  padding: 4px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  box-shadow: var(--shadow);
  display: none;
}
.bk-sel.is-open .bk-sel__menu { display: block; }
.bk-sel__opt {
  display: block; width: 100%;
  padding: 8px 10px;
  border: 0; border-radius: 7px;
  background: transparent;
  color: var(--text);
  font: inherit; font-size: 12.5px;
  text-align: left; white-space: nowrap;
  cursor: pointer;
}
.bk-sel__opt:hover { background: var(--hover); }
.bk-sel__opt.is-on { color: var(--accent); font-weight: 600; }

/* ---- ⑥ 登录页：主按钮与提示框的双模式收敛（v1.7.2）----
   🔴 报障一：深色模式下「登录」按钮文字是黑的，看不清。
      根因：`.loginbox .btn--primary` 把底色写成了 style.css 的 var(--ink)
      （那套令牌在深浅两套主题下都是深墨 #23201C），
      而文字色用的是后台的 var(--accent-ink)（深色主题 = #14110F 深墨）——
      深底 + 深字，必然糊。
      修法：登录页主按钮跟随后台的 --accent 强调色，
      深色主题 = 香槟金底 + 深墨字（对比充分），
      浅色主题 = 深金底 + 近白字（对比充分），
      两套主题各写一份显式兜底，不靠继承。
   🔴 报障二：验证码「已发送」提示框与登录按钮叠在一起。
      根因：#auth-msg 在 .loginbox 内但没有任何独立间距，
      里面的 .errbox 还带 margin-bottom:12px，
      视觉上就贴着下一个按钮。
      修法：#auth-msg 明确 margin-top，框内 .errbox 去掉下边距；
      「成功」提示改用 --ok / --ok-soft 令牌（浅色主题自动变浅绿、深色主题变深绿），
      彻底删掉 admin.js 里那段硬编码的内联浅绿色。 */
.loginbox .btn--primary {
  background-image: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 78%, #fff));
  border-color: transparent;
  color: var(--accent-ink);
}
.loginbox .btn--primary:hover {
  background-image: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 78%, #fff));
  color: var(--accent-ink);
}
[data-theme="light"] .loginbox .btn--primary {
  background-image: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 84%, #000));
  color: #FFFDF9;
}
[data-theme="light"] .loginbox .btn--primary:hover {
  background-image: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 84%, #000));
  color: #FFFDF9;
}
/* 提示框与按钮之间的呼吸位：提示框自身不再抢下边距 */
#auth-msg { margin-top: 14px; }
#auth-msg .errbox { margin-bottom: 0; }
/* 成功提示：走语义令牌，深浅两套主题各自成立 */
.errbox--ok {
  border-color: color-mix(in srgb, var(--ok) 45%, transparent);
  background: var(--ok-soft);
  color: var(--ok);
}

/* ==========================================================================
   v1.7.3（20261021c）到店登记改造 + 详情抽屉色卡 / 照片放大
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**，不插到中间。
   ========================================================================== */

/* ---- ① 现场拍照面板：深色模式不要白色底 ----
   🔴 报障：深色主题下三个空白拍照面板是**奶白色大块**，非常刺眼。
      根因：`.shot` 的底色写的是 var(--bg-soft)，而 --bg-soft 是**客户页浅色令牌**
      （style.css :root = #EFEAE1），后台主题从未覆盖它 —— 于是深色下照抄浅色底。
      修法：后台用自己的令牌重写（--panel-bg-solid / --line），
            两套主题各自成立，不改 style.css（三页共用，禁改）。 */
.shot {
  background: color-mix(in srgb, var(--panel-bg-solid) 62%, transparent);
  border-color: var(--line);
}
.shot__plus { color: var(--muted-dim); }
.shot__cap { color: var(--muted); }
.shot__cap span { color: var(--muted-dim) !important; }
[data-theme="light"] .shot { background: rgba(255, 253, 249, .72); }

/* ---- ② 色板（.sw）后台适配 ----
   style.css 的 .sw__n / .sw:hover 用的是客户页令牌（--ink-2 / #D3C7B4），
   在后台深色下文字偏暗、hover 描边发白，这里按后台令牌重写。 */
.sw { background: var(--surface); border-color: var(--line); }
.sw:hover { border-color: var(--panel-border-strong); }
.sw.is-on { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.sw__n { color: var(--muted); }
.sw.is-on .sw__n { color: var(--text-strong); }
.sw__tick { color: var(--accent); }

/* ---- ③ 身体数据参考范围 ---- */
.f__ref {
  margin-top: 5px;
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--muted-dim);
  font-family: var(--mono);
}

/* ---- ④ 自绘下拉（.wsel）：后台版门店 / 形象顾问选择 ----
   原生 <select> 承载不了「头像 + 名称 + 编号」，故自绘。 */
.wsel { position: relative; }
.wsel__btn {
  display: flex; align-items: center; gap: 8px;
  width: 100%; min-height: 36px;
  padding: 7px 11px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit; font-size: 12.5px;
  cursor: pointer; text-align: left;
  transition: border-color .15s ease, background .15s ease;
}
.wsel__btn:hover { border-color: var(--panel-border-strong); }
.wsel__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.wsel__cur { display: flex; align-items: center; gap: 8px; min-width: 0; flex-wrap: wrap; }
.wsel__ph { color: var(--muted-dim); }
.wsel__t { color: var(--text-strong); font-weight: 600; }
.wsel__s { color: var(--muted-dim); font-size: 11.5px; font-family: var(--mono); }
.wsel__ava {
  width: 22px; height: 22px; border-radius: 6px;
  object-fit: cover; flex: none;
  border: 1px solid var(--line);
}
.wsel__ava--ini {
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent);
  font-size: 11px; font-weight: 700;
}
/* 门店默认 logo（2026-10-23 需求 15）：
   stores 表没有 logo 列（只有 name / address / geo / remark / code），
   所以「默认 logo」= 取门店名首字生成的圆角字块，配色由 id 哈希决定，
   同一家门店每次进来都是同一个颜色（不会一会儿红一会儿蓝）。 */
.wsel__logo {
  display: grid; place-items: center; flex: none;
  width: 22px; height: 22px; border-radius: 6px;
  background: var(--accent-soft); color: var(--accent);
  font-size: 11px; font-weight: 700;
  border: 1px solid var(--line);
}
/* 门店详细地址：紧跟名称右侧，超长省略（弹层只有 320px 宽，不能把列表撑爆） */
.wsel__addr {
  flex: 1 1 auto; min-width: 0;
  color: var(--muted-dim); font-size: 11.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.wsel__list {
  position: absolute; top: calc(100% + 4px); left: 0;
  z-index: 1200;
  min-width: 100%; max-width: 320px; max-height: 260px; overflow-y: auto;
  padding: 4px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel-bg-solid);
  box-shadow: var(--shadow);
}
.wsel__item {
  display: flex; align-items: center; gap: 8px;
  width: 100%;
  padding: 7px 9px;
  border: 0; border-radius: 7px;
  background: transparent;
  color: var(--text);
  font: inherit; font-size: 12.5px;
  text-align: left; white-space: nowrap;
  cursor: pointer;
}
.wsel__item:hover { background: var(--hover); }
.wsel__item.is-on { color: var(--accent); font-weight: 600; }

/* ---- ⑤ 详情抽屉「色彩档案」真实色卡 ----
   原来只有一行文字 + 一条固定莫兰迪色条，顾问看不出客户到底选了哪些颜色。
   现在每个颜色一枚色卡（色值来自 A.colorHex）。 */
.swatch__vs { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.swatch__c {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 9px 4px 5px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface-2);
}
.swatch__dot {
  width: 16px; height: 16px; border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, .14);
  flex: none;
}
.swatch__cn { font-size: 12px; color: var(--text-strong); }

/* ---- ⑥ 现场照片点击放大（灯箱） ---- */
.shots-view img.is-zoomable { cursor: zoom-in; transition: transform .15s ease, box-shadow .15s ease; }
.shots-view img.is-zoomable:hover { transform: scale(1.03); box-shadow: 0 6px 20px rgba(0, 0, 0, .35); }
.plb { position: fixed; inset: 0; z-index: 1400; display: none; }
.plb.is-on { display: block; }
.plb__scrim { position: absolute; inset: 0; background: rgba(6, 6, 8, .86); backdrop-filter: blur(3px); }
.plb__box {
  position: relative; z-index: 1;
  height: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; padding: 24px;
}
.plb__stage img {
  max-width: 92vw; max-height: 78vh;
  border-radius: 12px; display: block; object-fit: contain;
  box-shadow: 0 18px 48px rgba(0, 0, 0, .55);
}
.plb__cap { color: #EDE7DC; font-size: 12.5px; }
.plb__x {
  position: absolute; right: 16px; top: 16px;
  width: 36px; height: 36px; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .22);
  background: rgba(255, 255, 255, .1); color: #fff;
  cursor: pointer; line-height: 1; font-size: 15px;
}
.plb__x:hover { background: rgba(255, 255, 255, .2); }
body.plb-open { overflow: hidden; }

/* ---- ⑦ 拍照上传建议 ---- */
.shots__tip {
  grid-column: 1 / -1;
  margin-top: 2px;
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--muted-dim);
}

/* ============================================================
   v1.8.0（2026-10-22）
   ============================================================ */

/* 需求 8：详情顶部客户信息卡右上角那条横线去掉
   （.dacts 原本有 border-top，视觉上像把按钮和名片切开的一道疤）
   🔴 2026-10-23 需求 12：按钮区从「名片右侧第三列」改成**独占一行的下方横条**
      （.dhero__acts，flex:1 1 100% 自动换行）。左右结构改上下结构后，
      「姓名 / 性别 / 年龄 / 职业 / 提交时间」这一行不再被一排按钮挤到换行；
      按钮移到了下方，只用留白分隔，**不加边线** —— v1.8.0 需求 9 用户明确
      要求去掉这条横线，不能在换个位置后又悄悄加回来。 */
.dhero .dacts { border-top: 0; margin-top: 12px; padding-top: 10px; }

/* 需求 2：自述体型 / 骨骼感常驻区块 —— 与围度数值区分开，避免看混 */
.selfbox { margin-top: 12px; padding-top: 12px; border-top: 1px dashed var(--line-soft); }
.selfbox .fgrid { grid-template-columns: 1fr 1fr; }
.selfbox .f__v { font-weight: 600; }

/* 需求 9：报告记录表 */
.tbl--rl th, .tbl--rl td { padding: 10px 10px; vertical-align: middle; }
.tbl--rl .rl-seq { font-family: var(--mono); color: var(--text-strong); }
.tbl--rl .rl-no {
  font-family: var(--mono); font-size: 12px; color: var(--muted);
  max-width: 190px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tbl--rl .rl-time { font-size: 12.5px; color: var(--muted); white-space: nowrap; }
.tbl--rl .rl-model {
  font-size: 12.5px; color: var(--muted);
  max-width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rl-tag {
  display: inline-block; padding: 2px 9px; border-radius: 999px;
  font-size: 11.5px; line-height: 1.6; border: 1px solid var(--panel-border);
  color: var(--muted); white-space: nowrap;
}
.rl-tag--initial { color: var(--text-strong); border-color: color-mix(in srgb, var(--accent) 45%, transparent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.rl-tag--followup { color: var(--text-strong); border-color: color-mix(in srgb, var(--ok) 45%, transparent); background: color-mix(in srgb, var(--ok) 14%, transparent); }
.rl-lock { font-size: 11px; opacity: .8; }
.tbl--rl .rl-acts { white-space: nowrap; }
.tbl--rl .rl-acts .btn { padding: 3px 8px; font-size: 12px; margin: 2px 2px 2px 0; }
.rl-focus {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 0 0 12px; padding: 9px 12px; border-radius: 10px;
  border: 1px solid var(--panel-border); background: var(--hover);
  font-size: 13px; color: var(--muted);
}
.rl-focus b { color: var(--text-strong); }

/* 报告日志弹窗 */
.uid-html { margin-bottom: 10px; }
.rl-logs { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.rl-logs li {
  display: grid; grid-template-columns: 132px 1fr; gap: 4px 10px;
  padding: 9px 12px; border-radius: 10px;
  border: 1px solid var(--panel-border); background: var(--hover);
  font-size: 12.5px;
}
.rl-logs__t { grid-row: 1 / span 3; font-family: var(--mono); color: var(--muted-dim); font-size: 11.5px; }
.rl-logs__a { color: var(--text-strong); }
.rl-logs__d { color: var(--muted); white-space: pre-wrap; }
.rl-logs__b { color: var(--muted-dim); font-size: 11.5px; }

/* ══════════════════════════════════════════════════════════════════
   2026-10-22 需求 5：报告记录列表「最近复诊」列
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**，不插到中间。
   ══════════════════════════════════════════════════════════════════ */
.tbl--rl .rl-lastfu {
  font-size: 12.5px; color: var(--muted); white-space: nowrap;
}
.tbl--rl .rl-lastfu .rl-fcnt {
  display: inline-block; margin-left: 5px; padding: 0 6px;
  border-radius: 999px; font-size: 11px; line-height: 1.7;
  color: var(--text-strong);
  border: 1px solid color-mix(in srgb, var(--ok) 45%, transparent);
  background: color-mix(in srgb, var(--ok) 14%, transparent);
}

/* ══════════════════════════════════════════════════════════════════
   2026-10-22 需求 9：问卷覆盖档案 · 逐项差异对比弹窗
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**，不插到中间。
   ══════════════════════════════════════════════════════════════════ */
.covdiff__grp {
  margin: 12px 0 4px;
  border: 1px solid var(--panel-border);
  border-radius: 12px;
  background: var(--hover);
  overflow: hidden;
}
.covdiff__gt {
  padding: 8px 12px;
  font-size: 12.5px; font-weight: 600;
  color: var(--text-strong);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border-bottom: 1px solid var(--panel-border);
}
.covdiff__rows { padding: 4px 2px; }
.covdiff__row {
  display: grid;
  grid-template-columns: 20px 78px 1fr 16px 1fr;
  gap: 8px; align-items: baseline;
  padding: 7px 10px;
  border-radius: 9px;
  font-size: 13px;
}
.covdiff__row:hover { background: color-mix(in srgb, var(--accent) 7%, transparent); }
.covdiff__row--ref { grid-template-columns: 78px 1fr 16px 1fr; cursor: default; }
.covdiff__k { color: var(--text-strong); font-weight: 600; }
.covdiff__old {
  color: var(--muted); text-decoration: line-through;
  text-decoration-color: color-mix(in srgb, var(--muted) 55%, transparent);
  overflow-wrap: anywhere;
}
.covdiff__arrow { color: var(--muted-dim); text-align: center; }
.covdiff__new { color: var(--text-strong); overflow-wrap: anywhere; }
.covdiff__none { padding: 12px; font-size: 12.5px; color: var(--muted); }
.covdiff__tools {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px;
  border-top: 1px solid var(--panel-border);
}
.covdiff__attach {
  display: flex; align-items: flex-start; gap: 7px;
  margin-top: 10px; font-size: 13px; color: var(--text-strong);
}
.covdiff__row.is-clear .covdiff__new { color: var(--warn); }
.covdiff__warn {
  display: inline-block; margin-left: 6px; padding: 0 6px;
  border-radius: 999px; font-style: normal; font-size: 11px; line-height: 1.7;
  color: var(--warn);
  border: 1px solid color-mix(in srgb, var(--warn) 45%, transparent);
  background: color-mix(in srgb, var(--warn) 14%, transparent);
}

/* ══════════════════════════════════════════════════════════════════
   2026-10-22 需求 10：审计日志视图
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**，不插到中间。
   ══════════════════════════════════════════════════════════════════ */
.tbl--au { font-size: 12.5px; }
.tbl--au td { vertical-align: top; }
.tbl--au .au-t {
  font-family: var(--mono); color: var(--muted-dim);
  font-size: 11.5px; white-space: nowrap;
}
.tbl--au .au-role {
  display: inline-block; margin-left: 5px; padding: 0 6px;
  border-radius: 999px; font-size: 10.5px; line-height: 1.7;
  color: var(--muted);
  border: 1px solid var(--panel-border);
  background: var(--hover);
}
.tbl--au .au-act {
  display: inline-block; padding: 1px 8px;
  border-radius: 999px; font-size: 11.5px; line-height: 1.8;
  color: var(--text-strong);
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  white-space: nowrap;
}
.tbl--au .au-fail {
  display: inline-block; margin-left: 5px; padding: 0 6px;
  border-radius: 999px; font-size: 10.5px; line-height: 1.7;
  color: var(--warn);
  border: 1px solid color-mix(in srgb, var(--warn) 45%, transparent);
  background: color-mix(in srgb, var(--warn) 14%, transparent);
}
.tbl--au .au-d {
  color: var(--muted); font-family: var(--mono); font-size: 11.5px;
  overflow-wrap: anywhere;
}
.au-pager {
  display: flex; align-items: center; justify-content: flex-end; gap: 10px;
  margin-top: 12px;
}

/* ══════════════════════════════════════════════════════════════════
   2026-10-22 需求 11：客户档案列表 · 档案进度百分比
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**，不插到中间。
   ══════════════════════════════════════════════════════════════════ */
.pprog {
  margin: 8px 0 4px;
  padding: 8px 10px 7px;
  border: 1px solid var(--panel-border);
  border-radius: 11px;
  background: var(--hover);
}
.pprog__head {
  display: flex; align-items: baseline; justify-content: space-between;
  margin-bottom: 6px;
}
.pprog__k { font-size: 11.5px; color: var(--muted); }
.pprog__pct {
  font-family: var(--mono); font-size: 14px; font-weight: 600;
  color: var(--text-strong);
}
.pprog__bar {
  height: 6px; border-radius: 999px; overflow: hidden;
  background: color-mix(in srgb, var(--text-strong) 10%, transparent);
}
.pprog__bar > i {
  display: block; height: 100%; border-radius: 999px;
  background: var(--accent);
  transition: width .28s ease;
}
.pprog--ok .pprog__bar > i { background: var(--ok); }
.pprog--mid .pprog__bar > i { background: var(--warn); }
.pprog--low .pprog__bar > i { background: color-mix(in srgb, var(--warn) 70%, var(--danger)); }
.pprog__segs {
  display: flex; flex-wrap: wrap; gap: 4px; margin-top: 7px;
}
.pprog__seg {
  font-size: 10.5px; line-height: 1.7;
  padding: 0 6px; border-radius: 999px;
  color: var(--muted-dim);
  border: 1px solid var(--panel-border);
  background: transparent;
}
.pprog__seg.is-part {
  color: var(--warn);
  border-color: color-mix(in srgb, var(--warn) 40%, transparent);
  background: color-mix(in srgb, var(--warn) 10%, transparent);
}
.pprog__seg.is-full {
  color: var(--ok);
  border-color: color-mix(in srgb, var(--ok) 40%, transparent);
  background: color-mix(in srgb, var(--ok) 10%, transparent);
}

/* ==========================================================================
   20261022a  需求 3 / 6 / 8 / 9：素材中心交互修正
   --------------------------------------------------------------------------
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**，不插到中间。
   ========================================================================== */

/* ---- 需求 3：hover 时的灰色透明蒙版（盖在图片上，按钮浮在它上面） ---- */
.st-card__mask {
  position: absolute; inset: 0; z-index: 1;
  background: rgba(58, 54, 48, .46);
  opacity: 0; transition: opacity .16s ease;
  pointer-events: none;
}
.st-card:hover .st-card__mask,
.st-vcard:hover .st-card__mask,
.st-card:focus-within .st-card__mask,
.st-vcard:focus-within .st-card__mask { opacity: 1; }
/* 「自建」徽章与视频播放钮要压在蒙版之上（否则 hover 时被灰层糊住） */
.st-card__badge { z-index: 2; }
.st-vcard__play { z-index: 2; }

/* ---- 需求 8：生成日志板块 ---- */
.st-genlog { margin-top: 26px; }
.tbl--genlog { font-size: 12.5px; }
.tbl--genlog td { vertical-align: middle; }
.tbl--genlog .au-t { color: var(--muted-dim); white-space: nowrap; }

/* ---- 需求 8：从生成日志跳过来时，对应作品卡高亮一闪 ---- */
.st-work.is-locate {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  animation: stLocate 1.8s ease;
}
@keyframes stLocate {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent); }
  70%  { box-shadow: 0 0 0 10px color-mix(in srgb, var(--accent) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 0%, transparent); }
}

/* ==========================================================================
   20261022b  需求 7：我的作品改瀑布流
   --------------------------------------------------------------------------
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**，不插到中间。
   --------------------------------------------------------------------------
   🔴 旧实现是 grid：同一行的卡片被拉成**等高**，图是竖图/横图时卡片底部
   会留下一条空白（用户报障：第二个作品红框处的多余空白）。
   现在改用 CSS columns 瀑布流（与「照片墙」.st-masonry 同一套做法）：
     · 列容器 columns:4，卡片 break-inside:avoid 不被拆到两列；
     · 卡片高度由**图片真实比例**决定（JS 用 naturalWidth/Height 校正
       stage 的 aspect-ratio），图有多高卡片就有多高 → 底部不再留白。
   🔴 注意：`display:grid` 与 `columns` 同时存在时 grid 胜出、column-count
      会被忽略，所以这里必须显式写 `display:block`。
   ========================================================================== */
.st-works__grid {
  display: block;
  columns: 4; column-gap: 12px;
}
.st-work {
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
  page-break-inside: avoid;
  margin: 0 0 12px;
}
/* 🔴 图片/视频必须**填满** stage（width+height 100% + object-fit:cover）。
   旧写法是 `height:auto`：图片按自然比例渲染，与 stage 的 aspect-ratio
   不一致时下方就空出一条 —— 这正是用户截图里那条多余空白。
   比例一致时 cover 等于原图，不会裁切。 */
.st-work__stage > img,
.st-work__stage > video {
  width: 100% !important;
  height: 100% !important;
  object-fit: cover;
  display: block;
}

/* 🔴 v1.16.14：这三块原本是给 CSS `columns` 瀑布流写的列数断点。
   需求 9 已把 `.st-works__grid` 改成 CSS Grid（行优先），
   `columns` 对 grid 容器**无效**，所以这里必须同步改成
   `grid-template-columns`，否则窄屏下 4 列不变、卡片被挤扁。
   列数与旧口径一一对应（1180→3 / 860→2 / 560→1）。 */
@media (max-width: 1180px) {
  .st-works__grid { columns: 3; }
}
@media (max-width: 860px) {
  .st-works__grid { columns: 2; }
}
@media (max-width: 560px) {
  .st-works__grid { columns: 1; }
}

/* ══════════════════════════════════════════════════════════════
   2026-10-23 需求 2：覆盖档案 · 全量字段对比（相同项 / 禁用行 / 组注）
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**，不插到中间。
   ══════════════════════════════════════════════════════════════ */
/* 组标题右侧的灰色小注（写库目标 / 暂无登记记录） */
.covdiff__gn {
  margin-left: 8px; font-weight: 400; font-size: 11.5px; color: var(--muted-dim);
}
/* 「以下 N 项问卷与档案一致」分隔行 */
.covdiff__sub {
  padding: 8px 10px 4px; font-size: 11.5px; color: var(--muted-dim);
}
/* 相同项：无复选框、无箭头，值 + 「相同」徽标，弱化处理 */
.covdiff__row--same {
  grid-template-columns: 78px 1fr auto;
  cursor: default; opacity: .72;
}
.covdiff__row--same:hover { background: transparent; }
.covdiff__v { color: var(--muted); overflow-wrap: anywhere; }
.covdiff__same {
  flex: none; padding: 0 8px; border-radius: 999px;
  font-size: 11px; line-height: 1.7; color: var(--muted-dim);
  border: 1px solid var(--panel-border);
  background: var(--hover);
  justify-self: end;
}
/* 禁用行（档案无登记记录时明细节整组禁用） */
.covdiff__row.is-off { opacity: .5; cursor: not-allowed; }
.covdiff__row.is-off:hover { background: transparent; }

/* 🆕 2026-10-23 需求 11：商品卡片视图 —— 宫格自适应铺排。
   ⚠️ .dcard-list 默认是「竖排 flex」（客户档案横条列表用），商品卡片视图
   复用同一容器导致「一个卡片独占一行」。这里加 grid 变体：auto-fill 按
   容器宽度自动决定列数，与顾问列表卡片同一套自适应思路。
   🔴 本块必须留在所有 @media 之后（项目铁律）。 */
.dcard-list--grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 12px;
  align-items: stretch;
}
.dcard-list--grid > .sku-card { height: 100%; }
/* 卡片 hero 图：宫格模式下 200px 太高（一屏只能看 2～3 张），压到 150px */
.dcard-list--grid .sku-card__hero { height: 150px; }
@media (max-width: 640px) {
  .dcard-list--grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
  .dcard-list--grid .sku-card__hero { height: 120px; }
}

/* 🆕 2026-10-23 需求 8：四场景统一客户头像（问卷记录 / 问卷详情 / 档案列表 / 档案详情）。
   单层结构：.pav 容器直接包 img 或 .pav__ini，不套第二层圆角块 ——
   旧档案详情是「外层 .dhero__av 渐变方框 + 内层再一层带边框圆角图」，
   用户看到的就是两层头像。色相由 JS personHueOf() 写进 --h（同一客户四场景一致）。 */
.pav {
  display: block; flex: none; overflow: hidden; position: relative;
  border-radius: 12px; background: var(--hover);
  /* 🔴 v1.16.46：aspect-ratio 派生高度的前提是**不能被 flex 拉伸**。
     .dcard--person / .dhero 等容器是 align-items: stretch，
     拉伸会把 4:5 的头像抻成别的比例 —— 这里显式钉住 flex-start。 */
  align-self: flex-start;
}
/* 🆕 v1.16.46 需求 1：客户头像显示区域统一改为 **4:5**（竖版半身照比例）。
   🔴 为什么改比例：客户上传的照片千奇百怪（横图 / 竖图 / 方图都有），
      原来 1:1 + cover 会把脸切掉一大半，横图客户尤其惨。
   ⚠️ 高度用 aspect-ratio 派生而不是写死像素 —— 容器宽度被 flex 压缩时
      比例仍然保持 4:5，不会被拉成别的形状。
   📐 尺寸口径：list 46×57.5、detail 54×67.5（宽度不变，高度按 4:5 派生）。 */
.pav--list { width: 46px; aspect-ratio: 4 / 5; height: auto; }
/* 详情 54px 宽 / 14px 圆角 —— 沿用 v1.9.3 需求 13 的口径（圆角正方形而非圆形） */
.pav--detail { width: 54px; aspect-ratio: 4 / 5; height: auto; border-radius: 14px; }
/* 🔴 v1.16.46 需求 1：图片**完整显示**，空余部分留白。
   原来 object-fit: cover 会裁切；改成 contain 后
   横图 / 方图都能看全，多出来的部分由白底补齐（与商品图同一套语言）。
   ⚠️ 白底必须写死 #fff（不是 var(--panel-bg)）——
      深色模式下若用面板底色会形成明显的深色边框，看着像「图被贴了黑边」。 */
.pav img { width: 100%; height: 100%; object-fit: contain; background: #fff; display: block; }
.pav__ini {
  width: 100%; height: 100%; display: grid; place-items: center;
  font-family: var(--serif); font-weight: 600; color: hsl(var(--h) 30% 90%);
  background: linear-gradient(155deg, hsl(var(--h) 26% 46%), hsl(var(--h) 22% 30%));
  box-shadow: inset 0 0 0 1px hsl(var(--h) 34% 66% / .30);
}
.pav--list .pav__ini { font-size: 18px; }
.pav--detail .pav__ini { font-size: 22px; }
/* 🔴 .dhero__av 纯净化：只做定位容器，不再自带渐变底 / 圆角 / 阴影
   （那些全交给内层 .pav 一层），杜绝「两层头像」。 */
.dhero__av {
  width: auto; height: auto;
  border-radius: 0;
  background: none;
  box-shadow: none;
  display: block;
  flex: 0 0 auto;
}

/* 🆕 2026-10-23 需求 12：商品表单图片占位（1 主图 + 5 副图）。
   点占位即上传、传完就地预览、角标可删（删后可重传）。
   参考问卷页「现场拍照」占位观感：虚线框 + 居中加号 + 角标。 */
.sku-mup {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}
.sku-mup__slot {
  position: relative; display: block; width: 100%; padding: 0;
  aspect-ratio: 1 / 1; overflow: hidden;
  border: 1px dashed var(--line, #cbb); border-radius: 10px;
  background: var(--hover); color: var(--muted-dim);
  cursor: pointer;
  transition: border-color .16s ease, color .16s ease;
}
.sku-mup__slot:hover { border-color: var(--accent); color: var(--accent); }
.sku-mup__slot.is-filled { border-style: solid; border-color: var(--line-soft); }
.sku-mup__tag {
  position: absolute; top: 6px; left: 6px; z-index: 2;
  font-size: 10px; line-height: 1.7; padding: 0 6px; border-radius: 4px;
  /* v1.16.4 R13：--muted-dim 在图片上几乎不可读（深浅双模都暗）。
     改用实底面板色 + 主文字色，保证任何背景图上都看得清。 */
  background: var(--panel-bg-solid); border: 1px solid var(--line); color: var(--text);
}
.sku-mup__ph { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; height: 100%; font-size: 12px; }
.sku-mup__ph i { font-style: normal; font-size: 22px; font-weight: 300; }
/* 🆕 v1.16.6 R7：商品图槽 1:1，非正方形图**完整显示**而不是裁切 ——
   旧版 object-fit: cover 会把竖图上下切掉、横图左右切掉，用户看不到全貌。
   改为 contain + 白底（照片类商品图铺白底最不干扰判断；深浅双模都保持白底，
   因为这是「看商品」而不是「看界面」，底色必须中性统一）。 */
.sku-mup__slot img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: contain; display: block; background: #fff;
}
.sku-mup__del {
  position: absolute; top: 6px; right: 6px; z-index: 2;
  width: 20px; height: 20px; border-radius: 50%;
  background: rgba(0, 0, 0, .55); color: #fff;
  display: grid; place-items: center; font-size: 13px; line-height: 1;
}
.sku-mup__del:hover { background: rgba(180, 60, 50, .85); }
@media (max-width: 640px) {
  .sku-mup { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* 🆕 2026-10-23 需求 13：品牌与供应商字典页（双列） */
.brandcols { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 14px; align-items: start; }
.brandcol { background: var(--panel-bg); border: 1px solid var(--panel-border); border-radius: var(--radius); padding: 12px 14px; }
.brandcol__h { display: flex; align-items: center; gap: 8px; padding-bottom: 10px; border-bottom: 1px solid var(--line-soft); margin-bottom: 6px; }
.bdict__row { display: flex; align-items: center; gap: 10px; padding: 9px 2px; border-bottom: 1px dashed var(--line-soft); }
.bdict__row:last-child { border-bottom: none; }
.bdict__main { flex: 1 1 auto; min-width: 0; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.bdict__used { font-size: 10.5px; color: var(--warn); background: var(--warn-soft); border: 1px solid color-mix(in srgb, var(--warn) 34%, transparent); border-radius: 20px; padding: 0 7px; }
.bdict__acts { flex: none; display: flex; gap: 6px; }
/* 表单下拉里的「＋ 新增…」占位项 */
.kf-dict-new { color: var(--accent); font-weight: 600; }

/* 🆕 2026-10-23 需求 10：经营驾驶舱（总览栏目）。
   所有颜色走 CSS 变量（深浅双模自动适配），不写死色值。 */

/* ① 欢迎模块：左文右数 */
.cpt-welcome { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; padding: 4px 2px 2px; }
.cpt-welcome__main { flex: 1 1 260px; min-width: 0; }
.cpt-welcome__hi { font-family: var(--serif); font-size: 21px; line-height: 1.35; color: var(--text-strong); }
.cpt-welcome__hi b { font-weight: 600; }
.cpt-welcome__meta { font-size: 12.5px; color: var(--muted-dim); margin-top: 5px; }
.cpt-welcome__n {
  flex: none; display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 10px 22px; border-radius: var(--radius);
  background: var(--hover); border: 1px solid var(--line-soft);
}
.cpt-welcome__num {
  font-family: var(--serif); font-size: 30px; line-height: 1.1;
  color: var(--accent); font-variant-numeric: tabular-nums;
}
.cpt-welcome__lab { font-size: 11px; color: var(--muted-dim); letter-spacing: .08em; }

/* ② 待办列表：卡片流（与问卷卡片同语言：头像 + 主信息 + 右箭头） */
.cpt-todo__list { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 10px; }
.cpt-todo {
  display: flex; align-items: center; gap: 11px; width: 100%; text-align: left;
  padding: 11px 12px; border-radius: var(--radius);
  border: 1px solid var(--panel-border); background: var(--panel-bg); color: var(--text);
  cursor: pointer; font: inherit;
  transition: border-color .16s ease, transform .16s ease;
}
.cpt-todo:hover { border-color: var(--accent); transform: translateY(-1px); }
.cpt-todo__main { flex: 1 1 auto; min-width: 0; }
.cpt-todo__top { display: flex; align-items: center; gap: 8px; min-width: 0; }
.cpt-todo__top b { font-size: 13.5px; color: var(--text-strong); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cpt-todo__flag {
  flex: none; font-size: 10.5px; line-height: 1.6; padding: 0 7px; border-radius: 20px;
  color: var(--warn); background: var(--warn-soft);
  border: 1px solid color-mix(in srgb, var(--warn) 34%, transparent);
}
.cpt-todo__flag.is-run {
  color: var(--info); background: var(--info-soft);
  border-color: color-mix(in srgb, var(--info) 34%, transparent);
}
.cpt-todo__sub { display: flex; align-items: center; gap: 8px; margin-top: 4px; min-width: 0; }
.cpt-todo__go { flex: none; font-size: 12px; color: var(--accent); }
.cpt-todo__empty { padding: 18px 2px; color: var(--muted-dim); font-size: 13px; }

/* ③ 快捷入口 */
.cpt-quick { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
.cpt-q {
  display: flex; flex-direction: column; align-items: flex-start; gap: 7px;
  padding: 13px 14px; border-radius: var(--radius);
  border: 1px solid var(--panel-border); background: var(--panel-bg); color: var(--text);
  cursor: pointer; font: inherit; text-align: left;
  transition: border-color .16s ease, transform .16s ease;
}
.cpt-q:hover { border-color: var(--accent); transform: translateY(-1px); }
.cpt-q__ico {
  display: grid; place-items: center; width: 34px; height: 34px;
  border-radius: var(--radius-sm); background: var(--hover); color: var(--accent);
}
.cpt-q__t { font-size: 13px; font-weight: 600; color: var(--text-strong); }
.cpt-q__d { font-size: 11px; color: var(--muted-dim); }

/* ④ 数据统计：KPI 大数字（复用 .statgrid / .stat 面板，只换内部排版） */
.cpt-kpi { display: flex; flex-direction: column; gap: 4px; }
.cpt-kpi__k {
  font-size: 10.5px; color: var(--muted-dim);
  font-family: var(--mono); letter-spacing: .12em; text-transform: uppercase;
}
.cpt-kpi__v {
  font-family: var(--serif); font-size: 27px; line-height: 1.25;
  color: var(--text-strong); font-variant-numeric: tabular-nums;
}
.cpt-kpi__d { font-size: 11.5px; color: var(--muted-dim); }

/* 待办点击跳转后，目标问卷卡片闪一下高亮（吸引视线确认「跳对了」） */
.dcard.is-flash { animation: cptFlash 1.6s ease; }
@keyframes cptFlash {
  0%, 100% { box-shadow: none; }
  15%, 65% { box-shadow: 0 0 0 2px var(--accent), 0 0 18px var(--accent-glow); }
}
@media (prefers-reduced-motion: reduce) {
  .dcard.is-flash { animation: none; box-shadow: 0 0 0 2px var(--accent); }
  .cpt-todo:hover, .cpt-q:hover { transform: none; }
}

@media (max-width: 640px) {
  .cpt-todo__list { grid-template-columns: 1fr; }
  .cpt-quick { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cpt-welcome__n { padding: 8px 16px; }
  .cpt-welcome__num { font-size: 26px; }
}

/* 🆕 2026-10-24 需求：驾驶舱四块各自独立成卡（欢迎 / 待办 / 快捷 / 统计）。
   板块之间靠 .cpt-stack 的 gap 拉开间距，不再用 <hr> 横线分隔 ——
   卡片自带的边框 + 阴影已经是视觉边界，再叠一条线会被读成「同一张表的分区」，
   拆成独立卡之后反而更像四个平级模块。 */
.cpt-stack { display: flex; flex-direction: column; gap: 20px; }
.cpt-card { padding: 22px 24px; }
/* 欢迎区原先靠外层 .card 的 padding 撑开，现在自己就在卡里，去掉内衬避免双份留白 */
.cpt-card .cpt-welcome { padding: 0; }
/* .statgrid 默认带 18px 下边距（给页面底部留白），在卡片内会多出一截空白 */
.cpt-card .statgrid { margin-bottom: 0; }

@media (max-width: 640px) {
  .cpt-stack { gap: 14px; }
  .cpt-card { padding: 16px 14px; }
}

/* 🆕 2026-10-24：商品图「待上传」态 —— 选完文件立刻本地预览，保存商品时才真正上传。
   虚线框 + 角标用来区分「已存进 storage」和「还在本地」，
   否则用户会以为已经传完，关弹窗才发现图没了。 */
.sku-mup__wait {
  position: absolute; left: 6px; bottom: 6px; z-index: 2;
  font-size: 10px; line-height: 1.7; padding: 0 6px; border-radius: 4px;
  background: color-mix(in srgb, var(--accent) 16%, var(--panel-bg));
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  color: var(--accent);
}
.sku-mup__slot.is-pending { border-style: dashed; border-color: var(--accent); }

/* 🆕 20261024d：商品表单「临时添加补充」的 chip 组。
   ⚠️ 为什么不用 style.css 的 .chip--custom / .chip__x：
      style.css 先加载、admin-hud.css 后加载，两者同为单类选择器 → 后者胜出，
      .chip--custom 的虚线边框与浅底会被 admin-hud.css 的 .chip 整条覆盖，
      表现为「补充项和固定项长得一模一样」，用户根本分不出哪个是刚临时加的。
      这里用 sku-chip--custom / sku-chip__x 独立命名，避免与问卷页共用规则互相污染。 */
.chipset .sku-chip--custom {
  border-style: dashed;
  border-color: color-mix(in srgb, var(--accent) 46%, transparent);
  background: color-mix(in srgb, var(--accent) 9%, transparent);
  color: var(--text);
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.chipset .sku-chip--custom.is-on {
  background: var(--accent);
  border-color: var(--accent);
  border-style: solid;
  color: var(--accent-ink);
  font-weight: 600;
}
.chipset .sku-chip__x {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 15px; height: 15px;
  margin-left: 1px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--text) 14%, transparent);
  color: var(--muted);
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  flex: none;
}
.chipset .sku-chip__x:hover { background: var(--danger); color: #fff; }
.chipset .sku-chip--custom.is-on .sku-chip__x {
  background: color-mix(in srgb, var(--accent-ink) 30%, transparent);
  color: var(--accent-ink);
}

/* 「补充输入 + 添加」行：与问卷页 .custom-add 同一形态，但用独立类名 */
.sku-chip-add {
  display: flex;
  gap: 8px;
  margin-top: 9px;
  align-items: center;
}
.sku-chip-add .input { flex: 1; max-width: none; }
.sku-chip-add .btn { flex: none; }

/* 商品表单 chip 组：组标题与补充行之间留一点呼吸感 */
#sku-form .field .chipset + .sku-chip-add { margin-top: 8px; }

/* ============================================================
   🆕 v1.11.0 到店登记 / 客户建档「客户类型」区块（.wict*）
   ------------------------------------------------------------
   为什么独立命名：问卷页已有 .chiprow/.chip，而 admin-hud.css 在
   style.css **之后**加载，复用类名会被问卷 chip 规则整条覆盖，
   选项会长得和问卷选项一模一样（v1.10.0 商品 chip 组同款教训）。
   全部走主题令牌（--panel-border / --surface / --accent / --muted…），
   深浅双模通用，禁硬编码色。本块放在所有 @media 之后，避免被断点吞掉。
   ============================================================ */
.wict {
  grid-column: 1 / -1;
  margin: 2px 0 4px;
  padding: 12px 14px 13px;
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-sm);
  background: var(--hover);
}
.wict__k {
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  font-family: var(--mono);
  letter-spacing: .06em;
  margin-bottom: 8px;
}
.wict__k .req { margin-left: 4px; }
.wict__opts { display: flex; flex-wrap: wrap; gap: 8px; }
.wict__opt {
  border: 1px solid var(--panel-border);
  background: transparent;
  border-radius: 999px;
  padding: 6px 18px;
  font: inherit;
  font-size: 13.5px;
  color: var(--muted);
  cursor: pointer;
  transition: .15s ease;
  user-select: none;
  line-height: 1.5;
}
.wict__opt:hover { border-color: var(--accent); color: var(--accent); }
.wict__opt.is-on {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
}
.wict__hint {
  margin-top: 9px;
  font-size: 12px;
  line-height: 1.7;
  color: var(--muted);
}
.wict__sel { margin-top: 10px; }
.wict__q { max-width: 340px; }
.wict__list {
  margin-top: 8px;
  max-height: 220px;
  overflow-y: auto;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel-bg-solid);
}
.wict__ld {
  padding: 10px 12px;
  font-size: 12px;
  color: var(--muted);
}
.wict__item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 11px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 12.5px;
  text-align: left;
  cursor: pointer;
}
.wict__item + .wict__item { border-top: 1px solid var(--line-soft); }
.wict__item:hover { background: var(--hover); }
.wict__item.is-on { color: var(--accent); }
.wict__item:disabled { opacity: .55; cursor: default; }
.wict__code {
  flex: none;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--muted);
  border: 1px solid var(--line-soft);
  border-radius: 5px;
  padding: 1px 6px;
}
.wict__nm { font-weight: 600; }
.wict__ph { color: var(--muted); font-family: var(--mono); font-size: 11.5px; }

/* ===== v1.12.0 表单校验红框（必填未填 / 格式错误） =====
   需求原话：「点击保存时，如必填项未输入或错误时，除了提示，对应的输入框
   边框也要变成红色，便于快速定位。」
   ⚠️ 必须追加在**所有 @media 之后**：本文件历史上多次因为新规则写在
      @media 前面被整段覆盖（v1.10.0 chip / v1.11.0 .wict 都踩过）。
     这里把动效的 @media 放在最前面，是为了保证「新规则全部在 @media 之后」。
   ⚠️ 全部走主题令牌（--danger / --danger-soft），深浅双模自动适配，零硬编码色。 */
@media (prefers-reduced-motion: no-preference) {
  .is-invalid { animation: mInvalidNudge .22s ease; }
}
@keyframes mInvalidNudge {
  0%, 100% { transform: translateX(0); }
  35% { transform: translateX(-2px); }
  70% { transform: translateX(2px); }
}
.input.is-invalid,
.textarea.is-invalid,
select.is-invalid,
input.is-invalid,
.wsel.is-invalid,
.f.is-invalid .input,
.f.is-invalid .textarea,
.field.is-invalid .input,
.field.is-invalid .textarea,
.field.is-invalid select,
.ms-field.is-invalid .input,
.ms-field.is-invalid select,
.csel.is-invalid .csel__btn,
.wict.is-invalid .wict__opt {
  border-color: var(--danger) !important;
  box-shadow: 0 0 0 3px var(--danger-soft);
}
/* 只标了外框、控件本身没拿焦点的字段块（如身高 + 体重一起标） */
.f.is-invalid > .f__k,
.field.is-invalid > .field__label,
.ms-field.is-invalid > span,
.wict.is-invalid .wict__k {
  color: var(--danger);
}
/* 红字说明：贴在字段块底部，比 toast 更不容易漏看，也不抢焦点 */
.flbad {
  margin-top: 5px;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--danger);
}

/* ============================================================
   v1.13.0 需求 2：弹窗操作按钮常驻底部
   ------------------------------------------------------------
   用户原话：「平台所有弹出框，但凡有操作按钮，必须保存和取消，
   这两个按钮都固定到弹出框底部随时可见，不随页面滚动。」
   做法：.modal__box 已是 flex column、.modal__body 是唯一的滚动容器，
   把按钮行做成 sticky 贴住滚动区底边即可 —— 不用改 30 多个弹窗的 DOM。
   bottom:-28px 是用来吃掉 .modal__body 的 padding-bottom（style.css 里是 28px），
   否则按钮会浮在内容区上方、露出一条空白。
   🔴 本块同样必须留在**所有 @media 之后**（见 v1.10.0 chip / v1.11.0 .wict 的教训）。
   ============================================================ */
.modal__body > .mfoot {
  position: sticky;
  bottom: -28px;
  z-index: 6;
  margin: 16px -20px -28px;
  padding: 12px 20px;
  background: var(--bg);
  border-top: 1px solid var(--line);
  box-shadow: 0 -10px 18px -16px rgba(35, 32, 28, .5);
}
/* 窄屏：padding 变成 16 / 22（见 style.css 的 ≤640 断点），补偿值跟着走 */
@media (max-width: 640px) {
  .modal__body > .mfoot { bottom: -22px; margin: 14px -16px -22px; padding: 12px 16px; }
}

/* ================= v1.14.0（20261026a）新增样式 =================
   🔴 铁律：新规则一律追加在所有 @media 之后（避免被响应式规则反向覆盖）。 */

/* ---- 需求 14：生成台参考图横向一行排开，「选择图片」在占位图下方 ---- */
#st-ref-pickers { display: flex; gap: 18px; flex-wrap: wrap; align-items: flex-start; }
.st-refcol { display: flex; flex-direction: column; gap: 8px; position: relative; }
/* 🆕 v1.16.41 用户第 5 项：生成台参考图 —— 有图时点图片放大，删除按钮改成
   图片右上角的 ✕（不再单独占一行按钮）。按钮放在列容器上（<button> 不能嵌套）。 */
.st-pick__x {
  position: absolute; top: 6px; right: 6px; z-index: 3;
  width: 22px; height: 22px; border-radius: 50%;
  border: none; background: rgba(0, 0, 0, .62); color: #fff;
  font-size: 12px; line-height: 1; cursor: pointer;
  display: none; place-items: center;
}
.st-refcol.is-on .st-pick__x { display: grid; }
.st-pick__x:hover { background: var(--danger); }
.st-pick__side--under { flex-direction: row; flex-wrap: wrap; }

/* ---- 需求 3：覆盖对比弹窗 · 组标题右上角「全选」 ---- */
.covdiff__gt { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.covdiff__gt > span:first-child { font-weight: 600; }
.covdiff__gall {
  margin-left: auto; display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; font-weight: 500; color: var(--muted);
  cursor: pointer; user-select: none; white-space: nowrap;
}
.covdiff__gall:hover { color: var(--accent); }
.covdiff__gall input { accent-color: var(--accent); cursor: pointer; }

/* ---- 需求 1：AI 初诊弹窗 · 诊断报告列表（条目多时内部纵向滚动） ---- */
.diag-rep__list { max-height: 240px; overflow-y: auto; padding-right: 4px; }

/* ---- 需求 2/12：档案抽屉照片库 —— 点击开灯箱 + 悬停删除按钮 ---- */
.shots-view .pshot { position: relative; }
.shots-view .pshot img.is-zoomable { cursor: zoom-in; }
.pshot__del {
  position: absolute; top: 6px; right: 6px;
  width: 24px; height: 24px; border-radius: 50%;
  border: none; cursor: pointer;
  background: rgba(20, 18, 15, .72); color: #fff;
  font-size: 15px; line-height: 1; display: grid; place-items: center;
  opacity: 0; transition: opacity .15s ease, background .15s ease;
}
.pshot__del:hover { background: #B4453B; }
.pshot:hover .pshot__del, .pshot__del:focus-visible { opacity: 1; }

/* ---- 需求 15：档案详情头像可点击换头像 ---- */
.dhero__av { position: relative; overflow: hidden; }
.dhero__av.is-clickable { cursor: pointer; }
.dhero__av.is-clickable::after {
  content: '更换'; position: absolute; left: 0; right: 0; bottom: 0;
  padding: 3px 0; text-align: center; font-size: 11px; line-height: 1.2; color: #fff;
  background: rgba(20, 18, 15, .62);
  opacity: 0; transition: opacity .15s ease; pointer-events: none;
}
.dhero__av.is-clickable:hover::after { opacity: 1; }

/* ---- 需求 7：更换门店 · 平铺单选列表（无弹出层，不会被弹窗裁剪） ---- */
.rlist { display: flex; flex-direction: column; gap: 6px; max-height: 264px; overflow-y: auto; }
.rlist__item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 11px; border: 1px solid var(--panel-border); border-radius: 10px;
  cursor: pointer; background: var(--bg); transition: border-color .14s ease, background .14s ease;
}
.rlist__item:hover { border-color: var(--accent); }
.rlist__item.is-on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 9%, transparent); }
.rlist__t { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; font-size: 13.5px; color: var(--text-strong); }
.rlist__dot {
  flex: none; width: 15px; height: 15px; border-radius: 50%;
  border: 1.6px solid var(--line); background: transparent; transition: border-color .14s ease;
}
.rlist__item.is-on .rlist__dot {
  border-color: var(--accent);
  background: radial-gradient(circle, var(--accent) 0 42%, transparent 46%);
}

/* ---- 需求 16：顶栏按钮默认只显示图标，悬停展开文字 ---- */
.topbar__actions .btn .btn__txt { display: none; }
.topbar__actions .btn:hover .btn__txt,
.topbar__actions .btn:focus-visible .btn__txt { display: inline; }

/* ---- 需求 11：模型通道列表筛选工具条 ---- */
.ms-filter { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin: 0 0 10px; }
.ms-filter__q { max-width: 220px; }
.ms-filter__sel { max-width: 150px; }
.ms-filter__n { margin-left: auto; }

/* ================================================================
   🆕🆕 v1.15.0 需求 2 / 5 / 8 —— UI 版式收口
   ⚠️ 依项目铁律：本块追加在**所有 @media 之后**（v1.10.0 chip / v1.11.0 .wict 的血泪：
      写在 @media 前面的新规则会被响应式断点整段吞掉。）
   ================================================================ */

/* ---- 需求 2：驾驶舱待办「门店名 / 提交时间」各自独立一行 ----
   🔴 旧版 .cpt-todo__sub 是 flex 单行排布，窄边框里门店 chip 和「… 提交」
      会挤成一团再折行 —— 用户截图反馈的正是这个。改成网格一人一行。 */
.cpt-todo__sub { display: grid; grid-auto-flow: row; gap: 2px; margin-top: 4px; min-width: 0; }
.cpt-todo__sub > * { min-width: 0; }
.cpt-todo__tm { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- 需求 5：模型通道筛选条所有控件同行 ----
   🔴 根因：基类 .input{width:100%}，在 .ms-filter（flex-wrap）里每个控件都
      占满整行 → 后面的兄弟必然换行，看起来就是「每个控件独占一行」。
      这里给 .ms-filter 的直接子控件换成「弹性基础 + 最小宽」：够宽时同行，
      不够时才换行（正是用户要的「除非宽度不够才换行」）。 */
.ms-filter > .input { width: auto; flex: 1 1 auto; min-width: 0; }
.ms-filter > .ms-filter__q { flex: 2 1 200px; min-width: 132px; max-width: none; }
.ms-filter > .ms-filter__sel { flex: 1 1 132px; min-width: 112px; max-width: none; }
.ms-filter > .ms-filter__n { flex: none; margin-left: auto; white-space: nowrap; }

/* ---- 需求 8：客户档案列表「刷新」按钮 —— 图标旋转 loading ---- */
#btn-prefresh { display: inline-flex; align-items: center; gap: 6px; }
#btn-prefresh .btn__ico-busy { display: inline-flex; width: 14px; height: 14px; flex: none; }
#btn-prefresh .btn__ico-busy svg { width: 14px; height: 14px; display: block; }
#btn-prefresh.is-busy { pointer-events: none; opacity: .72; }
@keyframes prefSpin { to { transform: rotate(360deg); } }
#btn-prefresh.is-busy .btn__ico-busy { animation: prefSpin .8s linear infinite; }

/* ================================================================
   🆕🆕 v1.15.0 需求 10 / 12 —— 顾问列表列宽（角色文案走 JS，不在这里））
   ⚠️ 同上：本块追加在**所有 @media 之后**。
   ================================================================ */

/* ---- 需求 10：顾问列表「名称」列至少容得下 4 个汉字不换行 ----
   🔴 旧表现：表格 auto 布局下「名称」列被邮箱 / 门店这些长内容挤到最窄，
      中文人名折成两行（甚至单个字换行），一列看见一半的姓氏让人读起来很累。
      这里用 min-width + nowrap 钉住：4 个汉字 ≈ 4×14px + 左右内边距。 */
.tbl--consultant .ctbl__name { white-space: nowrap; min-width: 74px; }
.tbl--consultant .ctbl__name b { font-weight: 600; color: var(--text-strong); }

/* ---- 需求 12：修改登录密码弹窗的红框 / 抖动 —— 不另写一套 ----
   🔴 pwdDialog 的三个输入框用的就是 .input，已被上面 6302 行的通用规则覆盖
      （红框 + mInvalidNudge 抖动 + label 变红）。这里**不再复制一遍**，
      否则以后改通用样式会漏改这里，两边颜色悄悄分叉。 */

/* ================================================================
   🆕🆕 v1.15.0 需求 16 —— 库存管理（台账矩阵 / 单据表单 / 明细行）
   ⚠️ 本块整体追加在**所有 @media 之后**（项目铁律）。
   颜色全部走主题变量（--danger / --warn / --ok / --panel-*），
   深浅双模自动成立，不写任何硬编码色值。
   ================================================================ */

/* ---- 台账：每款商品一张「颜色 × 尺码」矩阵 ---- */
.inv-sku { border: 1px solid var(--panel-border); border-radius: var(--radius); padding: 12px 14px 14px; margin-bottom: 14px; background: var(--panel-bg); }
.inv-sku__h { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.inv-sku__h b { font-size: 14.5px; }
/* 单元格：主数字 = 现存；小字 = 安全库存。低/零库存用暖色描边警示。
   🔴 可点击单元格只在有 a.invDoc 权限时渲染（JS 控制），CSS 不负责藏。 */
.inv-cell { text-align: center; cursor: pointer; transition: background .14s ease, border-color .14s ease; }
.inv-cell--na { color: var(--muted-dim); cursor: default; }
.inv-cell:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.inv-cell--low { background: color-mix(in srgb, var(--warn) 12%, transparent); }
.inv-cell--out { background: color-mix(in srgb, var(--danger) 14%, transparent); }
.inv-cell__q { display: block; font-weight: 700; font-size: 14px; }
.inv-cell--low .inv-cell__q { color: var(--warn); }
.inv-cell--out .inv-cell__q { color: var(--danger); }
.inv-cell__s { display: block; font-size: 10.5px; color: var(--muted-dim); }

/* 「只看库存告警」toggle 的按下态 */
#inv-alarm.is-on { border-color: var(--accent); color: var(--accent); }

/* ---- 流水的正负着色（入=绿 / 出=暖红，与全站 tag 口径一致） ---- */
.inv-up { color: var(--ok); font-weight: 600; }
.inv-down { color: var(--danger); font-weight: 600; }

/* ---- 单据表单（内联卡，非浮层） ---- */
.inv-form { border: 1px solid var(--panel-border-strong, var(--panel-border)); border-radius: var(--radius); padding: 14px 16px 16px; margin-top: 12px; background: var(--panel-bg); }
.inv-form__h { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.inv-form__h strong { font-size: 14.5px; }
.inv-form__help { margin: 8px 2px 10px; }
.inv-form__acts { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 12px; padding-top: 12px; border-top: 1px dashed var(--panel-border); }
.inv-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 10px 14px; }

/* 明细行：商品 → 规格（联动）→ 数量 → 行备注 → 删除 */
.inv-lines { display: grid; gap: 8px; }
.inv-line { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1.1fr) 92px minmax(0, 1fr) 34px; gap: 8px; align-items: center; }
.inv-line .input { width: 100%; }

@media (max-width: 900px) {
  .inv-line { grid-template-columns: 1fr 1fr; }
  .inv-line .inv-line__q { grid-column: 1; }
  .inv-line button { grid-column: 2; justify-self: end; }
}

/* ================================================================
   🆕🆕 v1.16.0（20261028a）UI 细节批次
   ⚠️ 依项目铁律：本块追加在**所有 @media 之后**，后续新规则继续往下追加。
   ================================================================ */

/* ---- 需求 3：驾驶舱待办门店名 —— 去掉矩形框与底纹，颜色淡化 ---- */
/* 旧渲染用 .dchip.dchip--store（徽标框+底纹），用户反馈视觉太重；
   新类 .cpt-todo__store 是纯文字弱化（无边框 / 无底色 / 更淡的颜色），
   只影响驾驶舱待办，不动其他页面的 .dchip--store。 */
.cpt-todo__store {
  font-size: 11px;
  color: var(--muted-dim);
  letter-spacing: .01em;
}
.cpt-todo__store::after { content: '·'; margin: 0 6px 0 4px; color: var(--muted-dim); opacity: .55; }

/* ---- 需求 16：所有列表操作按钮换行时上下行间距不得为 0 ---- */
/* 表格单元格里挤一排小按钮（报告记录 6 个、商品列表、门店列表…），
   窄屏/内容多时会折行 —— 行距 0 粘成一坨。给 td 内按钮统一加纵向间距：
   单按钮时也只多 2px，不影响常规行高。 */
.tbl td .btn { margin-top: 2px; margin-bottom: 2px; }

/* ---- 需求 7：问卷照片「加入档案」动作行 ---- */
.pshot { margin: 0; }
.pshot__act { margin-top: 5px; display: flex; justify-content: center; }

/* ---- 需求 9：可排序表头（报告记录 / 模型通道共用视觉） ---- */
.th-sort { cursor: pointer; user-select: none; white-space: nowrap; }
.th-sort:hover { color: var(--text-strong); }
.th-sort .th-sort__a { display: inline-block; min-width: 12px; color: var(--muted-dim); font-size: 11px; }
.th-sort.is-sorted .th-sort__a { color: var(--accent); font-weight: 600; }

/* ---- 需求 8：模型通道筛选条控件同行（v1.16.0 真修） ---- */
/* 🔴 v1.15.0 的同行规则（.ms-filter > .input）失效的根因：全站「禁原生 select」
   的 enhanceSelect（common.js）把三个筛选 select 包进了 .csel 自绘壳
   （.csel { width:100% }）—— select 不再是 .ms-filter 的直接子级，
   壳又占满整行 → 搜索占一行、每个下拉各占一行。给 .csel 壳同样上弹性。 */
.ms-filter > .csel { flex: 1 1 132px; min-width: 118px; max-width: 190px; width: auto; }

/* ================= v1.16.1 Bug9：商品头图区改成正方形 =================
   电商商品图惯例 1:1。旧规则写死高度（200/150/120px），宽卡片把图压扁、
   窄卡片裁切过度；aspect-ratio 让占位与图片都随卡片宽度自适应。
   （本文件铁律：新规则一律追加在所有 @media 之后，靠源序覆盖旧规则。） */
.sku-card__hero { height: auto; aspect-ratio: 1 / 1; }
.dcard-list--grid .sku-card__hero { height: auto; aspect-ratio: 1 / 1; }

/* ================= v1.16.1 Bug5：全站搜索框清空按钮 =================
   刻意不插 DOM：给搜索框包壳会破坏 .toolbar / .ms-filter 里
   「直接子级」弹性规则（v1.16.0 需求 8 的 .ms-filter > .csel 会复发）。
   改用背景图 ×：placeholder 以「搜索」开头（或 type=search）的 .input，
   有文字时右侧出现 ×；点击由 admin.js 全局委托判定右侧 32px 区域。
   灰圆白叉在深浅双模下都可见。 */
.input.sclear { padding-right: 30px; background-repeat: no-repeat; background-position: right 8px center; background-size: 15px 15px; }
.input.sclear.sclear--on {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='11' fill='rgba(127,127,127,0.55)'/%3E%3Cpath d='M8.2 8.2l7.6 7.6M15.8 8.2l-7.6 7.6' stroke='%23ffffff' stroke-width='2.6' stroke-linecap='round'/%3E%3C/svg%3E");
}

/* ================= v1.16.3 N4/N5：弹窗必填校验 =================
   旧实现是 resolve 之后 A.toast 报「名称不能为空」：toast 在页面底部，
   弹窗还盖在上面，用户根本看不到那一闪，而且提示与出错字段分离、
   弹窗已经关了，刚填的联系人/电话全丢。
   现在统一在**弹窗内**完成：标题红星号 + 输入框红框 + 抖动 + 弹窗内红字。
   颜色一律取 --danger（主题变量，深浅双模各自定义），不写死色值。
   「减少动态效果」偏好在 admin.js 里判断（这里不再加 @media 块 ——
   本文件铁律要求新规则追加在所有 @media 之后，末尾再插 @media 会让
   既有的「最后一个 @media 之后」类断言集体假红）。 */
.req-star {
  display: inline-block; margin-left: 3px;
  color: var(--danger); font-weight: 700;
  font-size: 13px; line-height: 1; vertical-align: super;
}
.input.is-bad, .textarea.is-bad {
  border-color: var(--danger) !important;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--danger) 22%, transparent);
}
@keyframes uidShake {
  0%, 100% { transform: translateX(0); }
  15% { transform: translateX(-5px); }
  30% { transform: translateX(5px); }
  45% { transform: translateX(-4px); }
  60% { transform: translateX(4px); }
  78% { transform: translateX(-2px); }
}
.input.shake, .textarea.shake { animation: uidShake .42s cubic-bezier(.36, .07, .19, .97) both; }

/* ================= v1.16.3 N8：表单首个分区去掉顶部虚线 =================
   .sec-sub 用 border-top:1px dashed 做分区分隔，但**第一个**分区上面
   本来就只有弹窗标题，再拉一条虚线是多余的（看起来像一条割裂的横线）。 */
.sec-sub--first { border-top: 0; padding-top: 0; margin-top: 2px; }

/* ================= v1.16.3 N7：商品列表「刷新」按钮转圈 =================
   与客户档案 #btn-prefresh 同一套视觉（图标 + 文字 + .is-busy 旋转），
   这里按 id 单独给一份规则，避免改动客户档案那套已验证过的样式。 */
#sku-reload { display: inline-flex; align-items: center; gap: 6px; }
#sku-reload .btn__ico-busy { display: inline-flex; width: 14px; height: 14px; flex: none; }
#sku-reload .btn__ico-busy svg { width: 14px; height: 14px; display: block; }
#sku-reload.is-busy { pointer-events: none; opacity: .72; }
#sku-reload.is-busy .btn__ico-busy { animation: prefSpin .8s linear infinite; }

/* ══════════════════════════════════════════════════════════════════
   v1.16.7 需求 5：客户档案列表「档案进度」宽度必须所有客户一致
   ------------------------------------------------------------------
   🔴 用户报障原文：「客户档案列表，档案进度板块的宽度应该所有客户都一样宽。
      当前无到店记录的档案，档案进度区域的宽度会更宽。」

   根因（puppeteer 实测确认，非猜测）：
     卡片是 flex 行 [头像 | 主区(含 .pprog) | .dcard__stats | .dcard__side]。
     .dcard__main 是 `flex:1 1 auto` —— 它的宽度 = 卡片宽 − 其余三块宽 − gap。
     而 .dcard__stats 是 `grid-auto-flow:column` 的隐式列网格，每列宽度取
     max(内容宽, .dstat 的 min-width:62px)。三列里「最近」列的内容是
     `MM-DD HH:MM`（如 10-05 11:00，mono 16 字符 ≈ 79.5px），
     **无到店记录时该列内容是「—」（≈12px）**，于是该列塌到 min-width 62px：

       有到店记录：.dcard__stats = 62 + 95.5 + 62 = 223.5px → .pprog = 792.4px
       无到店记录：.dcard__stats = 62 +  62  + 62 = 190.0px → .pprog = 825.9px
                                                        ↑ 差 33.5px

     也就是说「最近」列一塌，主区就把省下的 33.5px 全吃掉，进度条跟着变宽 ——
     同一列表里两行进度条宽度不等，视觉上像没对齐。

   修复：把三列宽度**写死**（62 / 96 / 62），不再让内容参与列宽计算。
     · 96px 取自「最近」列在有值时的实际宽度 95.5px，向上取整留 0.5px 余量，
       `MM-DD HH:MM` 永远放得下（.dstat__v 已 white-space:nowrap）。
     · 只作用在 .dcard--person，不碰通用 .dcard__stats（其它卡片将来复用不受影响）。
     · 窄屏（≤640px）已有的 `grid-template-columns: repeat(3,1fr)` 优先级更高
       （媒体查询里的显式模板会覆盖这里的隐式列宽），窄屏仍是三列等分撑满，
       本条不改变窄屏表现。
     ⚠️ 依项目铁律：新规则追加在**所有 @media 之后**，靠源序覆盖。 */
.dcard--person .dcard__stats {
  grid-auto-columns: 62px 96px 62px;
}

/* ================= v1.16.8 需求 16：库存台账「刷新」按钮转圈 =================
   与客户档案 #btn-prefresh / 商品列表 #sku-reload 同一套视觉（图标 + 文字 +
   .is-busy 旋转）。旧实现只有纯文字「刷新」，点了没有任何进行中反馈 ——
   顾问会以为没点上，连点好几次。 */
#inv-refresh { display: inline-flex; align-items: center; gap: 6px; }
#inv-refresh .btn__ico-busy { display: inline-flex; width: 14px; height: 14px; flex: none; }
#inv-refresh .btn__ico-busy svg { width: 14px; height: 14px; display: block; }
#inv-refresh.is-busy { pointer-events: none; opacity: .72; }
#inv-refresh.is-busy .btn__ico-busy { animation: prefSpin .8s linear infinite; }

/* 🆕 v1.16.15 需求 2：库存流水筛选栏的「刷新」按钮 —— 与上面 #inv-refresh
   逐条同款（同一套图标 + is-busy 旋转 + 忙时禁点），保证三个刷新入口视觉一致。 */
#inv-txn-refresh { display: inline-flex; align-items: center; gap: 6px; }
#inv-txn-refresh .btn__ico-busy { display: inline-flex; width: 14px; height: 14px; flex: none; }
#inv-txn-refresh .btn__ico-busy svg { width: 14px; height: 14px; display: block; }
#inv-txn-refresh.is-busy { pointer-events: none; opacity: .72; }
#inv-txn-refresh.is-busy .btn__ico-busy { animation: prefSpin .8s linear infinite; }

/* ================= v1.16.8 需求 16：库存流水「时间」列不换行 =================
   `2026-10-28 23:35` 在 112px 里会被折成两行（日期一行、时刻一行），
   扫读时看不出是哪一笔。加宽到 136px 并禁止换行，保证一行完整显示。 */
.inv-nowrap { white-space: nowrap; }

/* ================= v1.16.8 需求 15：新增 / 编辑库存单据改为弹出框 ========
   容器仍是那套内联渲染（行数可增删、商品↔规格联动都要在弹层里读 DOM），
   这里只把 #inv-doc-form 本身抬成居中浮层 + 加遮罩 —— 不动任何取值逻辑。
   ⚠️ 刻意不用 uiDialog：它 resolve 时弹层已摘除，读值全是 null。 */
.inv-scrim {
  position: fixed; inset: 0; z-index: 88;
  background: color-mix(in srgb, var(--ink, #14110d) 52%, transparent);
  backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
}
.inv-doc-modal {
  z-index: 89;
  /* 🆕 v1.16.12 三段式：本体 flex column 且**自身不滚动**（原 overflow:auto 会让
     标题头跟着明细滚走）。滚动交给 .inv-form__body，标题头与底部按钮行常驻。
     ⚠️ min-height:0 必须给滚动子元素，否则 flex 子项 min-height:auto 撑破容器。 */
  display: flex; flex-direction: column; overflow: hidden;
  /* 🔴🔴 v1.16.15 需求 3（用户报障：新建单据弹窗**只在右侧内容区**、且随内容区滚动）
     ---- 真因 ----
     元凶是 `.card` 的 `backdrop-filter`：按 CSS 规范，backdrop-filter 非 none
     的元素会**建立 fixed 包含块**。弹层原先挂在 #inv-view（.card/.content 内部），
     于是 position:fixed 的包含块是**右侧内容区**而不是视口 ——
     表现为「弹窗只在内容区里居中」且「内容区一滚弹窗跟着滚」。
     v1.16.14 把它从 .card 挪到 #inv-view 只解决了「高度被 .card 撑到 2813px」，
     包含块仍是 .content，所以定位基准依然是错的。
     ---- 修法（v1.16.15）----
     JS `ensureDocFormHost()` 把 `#inv-doc-form` 与遮罩一起挪到 **document.body** 下，
     包含块退回初始包含块（视口）→ top/left 50% 才是真正的**全屏居中固定**，
     不再随内容区滚动。此时 `max-height: calc(100% - 32px)` 的 `100%` 解析为
     视口高度，`width: min(960px, 88%)` 的 `88%` 解析为视口宽度，纯 CSS 自洽。
     ⚠️ 新增铁律：**带 backdrop-filter 的容器（本项目所有 .card）是 fixed
        包含块** —— 浮层/弹层绝不能挂在 .card 内部；若要「全屏居中固定」，
        必须一路挂到 document.body。 */
  position: fixed;
  top: 50%; left: 50%; transform: translate(-50%, -50%);
  max-height: calc(100% - 32px);
  width: min(960px, 88%);
  padding: 0;
  background: var(--panel-bg-solid, var(--panel-bg));
  border: 1px solid var(--panel-border-strong, var(--panel-border));
  border-radius: 14px;
  box-shadow: 0 18px 48px rgba(0, 0, 0, .34);
}
.inv-doc-modal .inv-form {
  padding: 0; border: 0; background: none;
  /* 🔴 v1.16.14：弹窗高度已由 .inv-doc-modal 的（JS 写入的）max-height 约束，
     这里只需**填满弹窗**：`flex:1 1 auto` + `min-height:0` 即可。
     不要写 `max-height:100%`（父级 .inv-doc-modal 高度是 auto，百分比不解析）。 */
  display: flex; flex-direction: column; min-height: 0;
  flex: 1 1 auto;
}
/* 🆕 v1.16.12：单据弹窗标题头 —— 独立一行 + 底部分割线 + 内边距，
   与全局 .modal__head（uiDialog 弹窗）视觉口径统一：
   同款 14px 20px 内边距、同款 1px 底边线、同款衬线加粗标题。
   原实现只是 `display:flex; margin-bottom:12px` 且因 .inv-form padding:0
   而紧贴弹窗边缘，看起来「没有标题头」。 */
.inv-doc-modal .inv-form__h {
  flex: none;
  padding: 14px 20px;
  margin: 0;
  border-bottom: 1px solid var(--line);
  background: transparent;
}
.inv-doc-modal .inv-form__h strong {
  font-family: var(--serif); font-size: 16px; color: var(--text-strong);
}
/* 内容区：唯一滚动容器（标题头与底部按钮行不参与滚动） */
.inv-form__body { flex: 1; min-height: 0; overflow-y: auto; padding: 16px 20px 4px; }
/* 底部按钮行常驻：不随内容滚动，与 .mfoot 同一设计意图 */
.inv-doc-modal .inv-form__acts {
  flex: none;
  padding: 12px 20px 16px;
  margin: 0;
  border-top: 1px solid var(--line);
  background: transparent;
}
.inv-doc-modal .inv-form__help { margin: 0 0 10px; }
.inv-form__x {
  width: 26px; height: 26px; padding: 0; border-radius: 8px;
  font-size: 15px; line-height: 1; display: inline-flex;
  align-items: center; justify-content: center;
}
/* 单据行里「搜索 + 商品下拉」并排：搜索框窄一点，下拉吃掉剩余空间 */
.inv-line__sku-cell { display: flex; gap: 6px; min-width: 0; }
.inv-line__skuq { flex: 0 0 128px; min-width: 0; }
.inv-line__sku { flex: 1 1 auto; min-width: 0; }

/* ============ v1.16.8 需求 13：库存台账矩阵「颜色」列限宽 ============
   行首颜色名（如「复古墨绿」）会把第一列撑得很宽，把尺码列挤到需要横向滚动。
   限宽 92px + 省略号，完整色名仍可从 title 看到。 */
.tbl--vmx .vmx__color {
  width: 92px; max-width: 92px; min-width: 72px;
  text-align: left; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}

/* ============ v1.16.8 需求 18：库存台账商品主图 ==================
   38px 圆角方块，无图时显示商品名首字（渐变底与商品卡头像同源）。
   图片一律 object-fit: contain + 白底（项目铁律：商品图不许裁切）。 */
.inv-thumb {
  flex: none; width: 38px; height: 38px; border-radius: 9px; overflow: hidden;
  display: grid; place-items: center;
  background: var(--hover); border: 1px solid var(--line-soft);
  font-family: var(--serif); font-size: 15px; font-weight: 600;
  color: var(--muted);
}
.inv-thumb__img { width: 100%; height: 100%; object-fit: contain; display: block; background: #fff; }

/* ============ v1.16.8 需求 17：商品网格卡片操作按钮图标化 ============
   默认只显示图标，鼠标划过某个按钮时才展开它自己的文字 —— 五个文字按钮
   会把卡片底部挤到换行。文字用 max-width 过渡而不是 display 切换，
   避免相邻按钮在 hover 时被推得来回跳。 */
.sku-card__acts { gap: 6px; }
.sku-iact {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 0; padding: 0 9px; height: 30px;
}
.sku-iact > svg { flex: none; }
.sku-iact__t {
  max-width: 0; overflow: hidden; white-space: nowrap;
  opacity: 0; margin-left: 0;
  transition: max-width .18s ease, opacity .18s ease, margin-left .18s ease;
}
.sku-iact:hover .sku-iact__t,
.sku-iact:focus-visible .sku-iact__t { max-width: 60px; opacity: 1; margin-left: 5px; }

/* ============ v1.16.8 需求 3：副图占位格区分「生成中 / 排队中」 ========
   只有当前真正在生成的那一格是「副图生成中…」+「停止生成」，
   后面排队的那几格弱化显示「排队中…」，不再每个空位都转圈。 */
.mcell.is-generating.is-queued { opacity: .62; }
.mcell.is-generating.is-queued .mcell__stop { display: none; }

/* ============ v1.16.8 需求 7：「同步全部」按钮的忙态 ============ */
#ai-sync-all.is-busy { pointer-events: none; opacity: .7; }
#ai-sync-all.is-busy::after {
  content: ""; display: inline-block; width: 11px; height: 11px; margin-left: 7px;
  vertical-align: -1px; border-radius: 50%;
  border: 2px solid currentColor; border-top-color: transparent;
  animation: prefSpin .8s linear infinite;
}

/* ==========================================================================
   v1.16.8 需求 6：AI 调用台整页重排 —— 四张卡片 + 卡内小组
   旧版四块内容只靠 margin-top:20px 硬隔开、字段一把平铺，视觉上「炸开」。
   新版：.aipage（列向 14px 间距）→ .aiblk（卡片：头 / 体 / 底栏）→ .aigrp（小组）。
   配色全部走 CSS 变量，深浅两套模式自动跟随，不写死颜色。
   ⚠️ 依项目铁律：本段追加在**全部响应式断点之后**，窄屏靠 minmax()/flex-wrap 自适应
   （不在末尾再插断点块：会让既有「最后一个断点之后」类断言集体假红）。
   ========================================================================== */
.aipage { display: flex; flex-direction: column; gap: 14px; }

.aiblk { display: flex; flex-direction: column; }
.aiblk__h {
  display: flex; align-items: flex-start; gap: 10px;
  padding-bottom: 10px; margin-bottom: 12px;
  border-bottom: 1px solid var(--line-soft);
}
.aiblk__no {
  flex: 0 0 auto; width: 20px; height: 20px; border-radius: 6px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; line-height: 1;
  background: var(--accent); color: var(--accent-ink);
}
.aiblk__ht { min-width: 0; }
.aiblk__ht h4 {
  margin: 0; font-size: 14px; font-weight: 600; color: var(--text-strong); line-height: 1.35;
}
.aiblk__ht p { margin: 3px 0 0; font-size: 11.5px; color: var(--muted-dim); line-height: 1.5; }

.aiblk__b { display: flex; flex-direction: column; gap: 12px; }
.aiblk__f {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding-top: 12px; margin-top: 12px;
  border-top: 1px solid var(--line-soft);
}

/* 卡内小组：浅底 + 虚线框，把「颜色」「场景身形」「预算」各自圈起来 */
.aigrp {
  border: 1px dashed var(--line);
  border-radius: 10px;
  padding: 10px 12px 12px;
  background: color-mix(in srgb, var(--hover) 45%, transparent);
}
.aigrp__t {
  display: flex; align-items: center; gap: 6px;
  font-size: 11.5px; font-weight: 600; color: var(--muted);
  margin-bottom: 9px; letter-spacing: .01em;
}
.aigrp__t::before {
  content: ""; width: 2px; height: 11px; border-radius: 2px;
  background: var(--accent); opacity: .75;
}

/* 条件栅格：默认 260px 起（约 3 列）；--2 是 300px 起（宽控件 / chip 组用两列） */
.aiform { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.aiform--2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.aiform__full { grid-column: 1 / -1; }
/* 只有一行勾选框的小组（如「只显示在售」）要和其它输入框底部对齐 */
.aifield--end { display: flex; align-items: flex-end; }
.aifield--end .aick { padding-bottom: 7px; }

/* ============ v1.16.9 需求 1：登录页「测试员一键登录」金光环绕按钮 ============
   视觉目标：在安静的登录页里唯一「发光」的元素，引导测试人员注意，但不与
   「登录」主按钮抢语义。实现方式：金色渐变底 + 呼吸式外辉光 + 内描边高光，
   三层叠加；hover / focus 时辉光增强。全部用 CSS 动画，无外部资源。
   全部响应式断点之后追加，靠源序覆盖；主题令牌取自本文件，深浅两套各自适配。
   🆕 v1.16.11 需求 1：**移除环绕流光带**。原 `.btn-glow::after` 用旋转的
   conic-gradient 做「沿按钮一周游走的高光」，实际观感是一根顺时针旋转的线条
   常驻在按钮外圈（用户两次截图报障），且与「干净的金属质感」目标相悖。
   现改为纯静态金色渐变 + 呼吸辉光，不再有任何旋转元素。 */
.btn-glow {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  margin-top: 16px;
  padding: 11px 18px;
  border: 1px solid transparent;
  border-radius: 12px;
  font-size: 14px; font-weight: 600; letter-spacing: .02em;
  color: var(--accent-ink);
  background:
    linear-gradient(135deg, #F3DFA6 0%, #C8A96A 38%, #A9873F 62%, #EFD79A 100%);
  background-size: 220% 100%;
  box-shadow:
    0 0 0 1px rgba(198, 162, 106, .55),
    0 0 14px rgba(198, 162, 106, .35),
    0 0 26px rgba(198, 162, 106, .18);
  cursor: pointer;
  animation: btnGlowSweep 4.5s linear infinite, btnGlowPulse 2.6s ease-in-out infinite;
}
/* 内描边高光：细一圈亮线，让金色边框「有厚度」 */
.btn-glow::before {
  content: "";
  position: absolute; inset: 1px;
  border-radius: 11px;
  border: 1px solid rgba(255, 248, 224, .55);
  pointer-events: none;
}
.btn-glow__ico { flex: none; }
.btn-glow__t { white-space: nowrap; }
.btn-glow:hover {
  box-shadow:
    0 0 0 1px rgba(198, 162, 106, .8),
    0 0 20px rgba(198, 162, 106, .55),
    0 0 38px rgba(198, 162, 106, .3);
  animation-play-state: paused, running;
}
.btn-glow:active { transform: translateY(1px); }
.btn-glow:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.btn-glow[disabled] { opacity: .62; cursor: not-allowed; animation: none; }

@keyframes btnGlowSweep {
  0%   { background-position: 0% 50%; }
  100% { background-position: 220% 50%; }
}
@keyframes btnGlowPulse {
  0%, 100% {
    box-shadow:
      0 0 0 1px rgba(198, 162, 106, .55),
      0 0 14px rgba(198, 162, 106, .35),
      0 0 26px rgba(198, 162, 106, .18);
  }
  50% {
    box-shadow:
      0 0 0 1px rgba(198, 162, 106, .78),
      0 0 20px rgba(198, 162, 106, .52),
      0 0 36px rgba(198, 162, 106, .28);
  }
}

/* ==========================================================================
   v1.16.10 R2：登录页按钮统一（金光风格 + 宽度对齐）
   --------------------------------------------------------------------------
   R2a：`#btn-test-login` 原先直接挂在 `.wrap`（max-width:560px）下，
        比上方 `.loginbox` 卡片（max-width:420px）宽出一截，视觉上「冒头」。
        修法：外包一层 `.login-extra`，与 `.loginbox` 用**完全相同的**
        max-width + 水平居中 + 同一左内边距基准，宽度严丝合缝。
   R2b：正常「登录」按钮（#btn-login-pwd / #btn-login-otp）改用 `.btn-glow`
        同款金光风格。要点：**必须覆盖 `.loginbox .btn--primary` 的深色渐变底**
        （那条规则在 146782 字符处，靠源序覆盖不到 —— 本段追加在文件末尾，
        所以这里显式重置 background / color / box-shadow 才能生效）。
   ⚠️ 全部追加在所有响应式断点之后（本文件最后一个断点在 258776 字符），
      靠源序覆盖；注释里不写断点字面量（检查脚本按关键字定位最后断点）。
   ========================================================================== */

/* R2a：测试按钮容器与登录卡片同宽 */
.login-extra {
  max-width: 420px;
  margin: 14px auto 0;
  padding: 0;
}

/* R2b：登录卡片内的金光按钮 —— 尺寸与卡片一致，风格与测试按钮同款。
   用 `.loginbox .btn-glow` 提高特异性压过 `.loginbox .btn` / `.loginbox .btn--primary`。 */
.loginbox .btn-glow {
  width: 100%;
  margin-top: 4px;
  padding: 12px 18px;
  border-radius: 12px;
  color: var(--accent-ink);
  background:
    linear-gradient(135deg, #F3DFA6 0%, #C8A96A 38%, #A9873F 62%, #EFD79A 100%);
  background-size: 220% 100%;
  box-shadow:
    0 0 0 1px rgba(198, 162, 106, .55),
    0 0 14px rgba(198, 162, 106, .35),
    0 0 26px rgba(198, 162, 106, .18);
}
/* hover：与独立金光按钮一致的辉光增强（并停掉 sweep，只留呼吸） */
.loginbox .btn-glow:hover {
  background:
    linear-gradient(135deg, #F3DFA6 0%, #C8A96A 38%, #A9873F 62%, #EFD79A 100%);
  background-size: 220% 100%;
  color: var(--accent-ink);
  box-shadow:
    0 0 0 1px rgba(198, 162, 106, .8),
    0 0 20px rgba(198, 162, 106, .55),
    0 0 38px rgba(198, 162, 106, .3);
  animation-play-state: paused, running;
  transform: translateY(-1px);
}
.loginbox .btn-glow:active { transform: translateY(1px); }
/* 禁用态（登录请求中）保持金光但不闪 */
.loginbox .btn-glow[disabled] { opacity: .62; animation: none; }
/* 窄屏：测试按钮容器随卡片一起收边（用 clamp 而非断点，保持本段无新断点） */
.login-extra { max-width: min(420px, 100%); }

/* ==========================================================================
   20261031b（v1.16.10 R4）模型设置「已启用通道」：五用途纵向 tab + 单用途全宽列表
   ⚠️ 依项目铁律：本段追加在**所有响应式断点之后**；注释里不写断点关键字字面量。
   ========================================================================== */
/* 外壳：左侧用途导航（窄栏）+ 右侧当前用途的完整通道列表（吃掉剩余宽度）。
   🔴 用 flex + wrap 实现「宽屏纵向 / 窄屏自动折行成横向」——
      导航 flex-basis 200px 且**不许长胖**（flex-grow:0），
      内容区 flex-grow:1 且有 min-width 门槛；两者放不下时导航自动折到上一行。
      这样**不需要任何响应式断点**（依项目铁律：本段之后不得再出现断点关键字）。 */
.msk {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin: 14px 0 4px;
  align-items: flex-start;
}
/* 左侧纵向导航：固定 200px 宽、不参与伸缩；窄屏放不下时整块折行 */
.msk-nav {
  display: flex; flex-direction: column; gap: 6px;
  flex: 0 0 200px;
  min-width: 0;
}
.msk-tab {
  appearance: none; text-align: left; cursor: pointer;
  border: 1px solid var(--line);
  background: var(--panel-bg-solid, #fff);
  color: var(--text);
  border-radius: 10px;
  padding: 9px 12px;
  display: flex; flex-direction: column; gap: 3px;
  min-width: 0;
  transition: background .15s, color .15s, border-color .15s;
}
.msk-tab:hover { border-color: var(--accent, #a4813c); }
.msk-tab__t {
  display: flex; align-items: center; gap: 6px;
  font-size: 13px; font-weight: 600;
  white-space: nowrap;
}
.msk-tab__n {
  display: inline-block; margin-left: auto;
  min-width: 18px; padding: 0 6px;
  border-radius: 999px; text-align: center;
  font-size: 11px; font-weight: 700; line-height: 1.6;
  background: var(--accent-soft); color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  font-variant-numeric: tabular-nums;
}
/* 主通道名：让导航本身带关键信息，不用点进去才知道默认用谁 */
.msk-tab__s {
  font-size: 11px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  max-width: 100%;
}
.msk-tab--on {
  background: var(--accent, #a4813c);
  border-color: var(--accent, #a4813c);
  color: #fff;
}
.msk-tab--on .msk-tab__s { color: rgba(255, 255, 255, .78); }
.msk-tab--on .msk-tab__n {
  background: rgba(255, 255, 255, .26);
  color: #fff;
  border-color: rgba(255, 255, 255, .42);
}
/* 右侧内容区：吃掉剩余宽度；最小 320px，小于它就整块换行（避免被挤成一条） */
.msk-pane {
  flex: 1 1 320px;
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 12px 14px;
  background: var(--panel-bg-solid);
  min-width: 0;
}
.msk-pane__h { margin-bottom: 8px; }
.msk-pane__pri { margin-left: auto; }
.msk-list { display: flex; flex-direction: column; gap: 6px; }
/* 行：名称 + 倍数徽章 + 供应商·优先级（右对齐）+ 操作按钮，全宽下不再截断 */
.msk-row { min-width: 0; }
.msk-empty { padding: 6px 0; }
/* 导航折行后的兜底：一旦整块折到独立一行，让它横向铺开成胶囊行更省高度。
   用 :has() 检测「内容区被挤到下一行」—— 不引入断点关键字。 */
.msk-nav:only-child,
.msk:not(:has(.msk-pane)) .msk-nav { flex-direction: row; flex-wrap: wrap; }
.msk-tab { min-width: 0; }

/* ==========================================================================
   20261031c（v1.16.10 R7）AI 调用台：颜色 / 避雷色 改色卡多选
   ⚠️ 依项目铁律：本段追加在**所有响应式断点之后**；注释里不写断点关键字字面量。
   ========================================================================== */
/* 色卡容器在 aiform 的两列里要能自适应：单列时列宽较大，色卡可多放几枚 */
.palette--ai {
  grid-template-columns: repeat(auto-fill, minmax(58px, 1fr));
  gap: 6px;
  max-height: 232px;
  overflow-y: auto;
  padding: 2px 2px 2px 0;
}
.palette--ai::-webkit-scrollbar { width: 6px; }
.palette--ai::-webkit-scrollbar-thumb {
  background: var(--line); border-radius: 3px;
}
/* 分组小标题要独占一整行（否则会被 auto-fill 塞进某个格子） */
.palette--ai .palette__cap { grid-column: 1 / -1; }
/* 色卡在紧凑尺寸下略缩，色名允许两行 */
.palette--ai .sw { padding: 6px 3px 5px; border-radius: 9px; }
.palette--ai .sw__dot { width: 28px; height: 28px; margin-bottom: 4px; }
.palette--ai .sw__n { font-size: 11px; }
/* 「补充颜色名 + 添加」行：与建档页 .custom-add 同形，窄一点 */
.palette--ai + .custom-add { margin-top: 8px; }

/* ==========================================================================
   20261031c（v1.16.11 需求 2）模型设置「已启用通道」列表 → 真表格
   --------------------------------------------------------------------------
   用户报障：卡片行里「模型名 + 倍数徽章 + 供应商·优先级 + 按钮」在窄列里
   各行宽度不一、看着不齐。改为 table-layout:fixed + 百分比列宽，严格对齐。
   列：模型通道(48%) / 供应商(20%) / 优先级(12%) / 操作(20%)。
   徽章并入首列（倍数）与末列（默认使用），避免表头列数过多。
   ⚠️ 依项目铁律：本段追加在**所有响应式断点之后**；注释里不写断点关键字字面量。
   ========================================================================== */
.msk-tblwrap { overflow-x: auto; }
.msk-tbl {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  font-size: 13px;
}
.msk-tbl thead th {
  text-align: left;
  font-weight: 600;
  font-size: 11px;
  letter-spacing: .04em;
  color: var(--muted);
  text-transform: none;
  padding: 6px 10px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.msk-tbl tbody td {
  padding: 9px 10px;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
  vertical-align: middle;
  min-width: 0;
}
.msk-tbl tbody tr:last-child td { border-bottom: 0; }
.msk-tbl tbody tr:hover td { background: color-mix(in srgb, var(--accent) 5%, transparent); }
/* 列宽：固定百分比，保证各行列严格对齐 */
.msk-tbl__c1 { width: 48%; }
.msk-tbl__c2 { width: 20%; }
.msk-tbl__c3 { width: 12%; }
.msk-tbl__c4 { width: 20%; }
/* 模型名：允许省略号，不撑破列 */
.msk-tbl__nm {
  font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  display: inline-block; max-width: 100%; vertical-align: bottom;
}
/* 供应商列：超长省略，避免顶破列宽 */
.msk-tbl__c2 {
  color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 优先级列：等宽数字，纵向对齐更整齐 */
.msk-tbl__c3 { font-variant-numeric: tabular-nums; color: var(--muted); }
/* 操作列：右对齐（按钮 / 「默认使用」都靠右，与表头右边界齐） */
.msk-tbl__c4 { text-align: right; }
.msk-tbl__def {
  display: inline-block;
  font-size: 12px;
  color: var(--ok);
  white-space: nowrap;
}
/* 窄屏：表格允许横向滚动而不是把列挤爆（靠 overflow-x，不引入响应式断点） */
.msk-tblwrap { -webkit-overflow-scrolling: touch; }

/* ══════════════════════════════════════════════════════════════
   v1.16.13 批次（用户九项需求）
   ⚠️ 依项目铁律：本段追加在**所有断点块之后**，不插到中间。
   ══════════════════════════════════════════════════════════════ */

/* ---- 需求 7：生成日志列宽（标题列太宽、模型列太窄） ----
   🔴 旧实现是 `auto` 布局 + 内联 `width:150/60/160/96`，
      但「标题」列**没有宽度约束**，auto 布局会把剩余空间全给它 →
      标题列宽到只剩一行字也占半屏，模型列被挤成 160px 里放长模型名。
   改 `table-layout: fixed` + 百分比列宽：五列严格对齐、不随内容抖动。
   时间 15% / 类型 8% / 标题 32% / 模型 27% / 操作 18%。
   ⚠️ 内联 width 会被本段的 `!important` 之外的选择器覆盖 —— fixed 布局下
      内联 width 仍参与计算，故本段同时给出百分比，优先级由 fixed 布局保证。
   注意：内联样式优先级高于 class，所以这里必须用 !important 覆盖内联宽度。

   🔴🔴 v1.16.54 第 2 项（线上报障：移动端「时间」「类型」两列内容互相压住）：
   v1.16.44 给这张表加了「参考图片 / 生成结果」两列，现在是 **7 列**，
   而上面这段列宽还停留在 5 列 —— 三个百分比（第 5 列 18%）之后没有给
   第 6、7 列留任何宽度，fixed 布局下它们的可用宽度就是 0，内容全部溢出；
   同时第 1、2 列按 15% / 8% 只有 138 / 73px，`2026-11-09 14:23` 这种
   时间文本直接撑破单元格、盖到「类型」上 —— 就是用户截图里的重叠。
   修法：改成按当前 7 列给**定宽**（px，与建表时的内联宽度一致），
   只让「标题 / 模型」两列吃剩余宽度，并给前两列加 ellipsis 兜底。 */
.tbl--genlog { table-layout: fixed; }
.tbl--genlog th:nth-child(1), .tbl--genlog td:nth-child(1) { width: 150px !important; }
.tbl--genlog th:nth-child(2), .tbl--genlog td:nth-child(2) { width: 64px !important; }
.tbl--genlog th:nth-child(3), .tbl--genlog td:nth-child(3) { width: 240px !important; }
.tbl--genlog th:nth-child(4), .tbl--genlog td:nth-child(4) { width: 160px !important; }
.tbl--genlog th:nth-child(5), .tbl--genlog td:nth-child(5) { width: 92px !important; }
.tbl--genlog th:nth-child(6), .tbl--genlog td:nth-child(6) { width: 92px !important; }
.tbl--genlog th:nth-child(7), .tbl--genlog td:nth-child(7) { width: 250px !important; }
/* 时间 / 类型 / 标题 / 模型 一律单行 + 省略号，绝不溢出到隔壁列 */
.tbl--genlog td:nth-child(1),
.tbl--genlog td:nth-child(2),
.tbl--genlog td:nth-child(3),
.tbl--genlog td:nth-child(4) {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---- 需求 9：我的作品排序（第二行唯一作品排到了第三列） ----
   🔴 真因：`.st-works__grid` 用的是 CSS **columns 瀑布流**（`columns: 4`）。
      columns 的填充规则是**纵向列优先**：它先把第 1 列填满、再填第 2 列……
      于是「5 条作品 + 4 列」时，第 1 列有 2 条、其余 3 列各 1 条 ——
      视觉上第二行的那一条落在**第 2 列**，若前一条恰好较高，就会被
      挤到更右边（用户截图里落在第三列）。用户期望的是**横向行优先**：
      第 1 行 4 条、第 2 行第 1 列起。
   改回 CSS Grid（`grid-template-columns: repeat(4, 1fr)` + `align-items:start`），
   行优先填充；卡片高度不一的问题由每张卡的 stage 自带 `aspect-ratio`
   （JS `fixStageAspect` 校正）解决，不会像旧 grid 那样被拉成等高留白。
   ⚠️ 响应式列数改用**既有断点块**里的 `grid-template-columns`（见本文件
      中部「st-works__grid 列数」三块），**不在文件末尾新增断点**
      （避 §3 铁律：CSS 末尾禁止追加断点块）。
   ⚠️ `.st-work` 的 `break-inside: avoid` 在 grid 下无害，保留即可。 */
.st-works__grid {
  /* 🔴🔴 v1.16.17 需求 3（用户报障）：改回 CSS **columns 瀑布流**，
     与「预设作品墙」的 .st-masonry 同一套做法 —— 用户明确要求
     「我的作品页面罗列的作品还是改为瀑布流，和作品墙一样」。
     历史沿革（别再来回翻）：
       · v1.16.12 用 columns:4；v1.16.14 因「第二行唯一作品落到第三列」
         改成 CSS Grid（行优先）；v1.16.17 用户又要求回瀑布流 ——
         因为瀑布流下每列高度由图片真实比例决定，视觉更整齐无留白，
         且与作品墙一致。
     ⚠️ `display:grid` 与 `columns` 同时存在时 grid 胜出、columns 被忽略，
        所以这里必须显式 `display:block`。
     ⚠️ 卡片 `break-inside:avoid` 由下方 `.st-work` 规则保证，不被拆到两列。 */
  display: block;
  columns: 4;
  column-gap: 12px;
}
.st-works__grid .st-work { margin: 0 0 12px; }

/* ---- v1.16.14：我的作品 · 底部操作按钮图标化后的紧凑约束 ----
   按钮本身复用商品列表的 `.sku-iact`（默认图标 / hover 展开文字），
   这里只补两件事：
   ① 按钮行不换行（图标化后 4 个按钮约 150px，261px 卡宽放得下）；
   ② 按钮左右内边距收窄一点，窄卡片里更稳。 */
.st-work__acts { flex-wrap: nowrap; }
.st-work__acts .sku-iact { padding: 0 8px; }
/* 🔴🔴 v1.16.17 需求 4（用户报障：展开的按钮宽度不足，文字显示不全）：
   真因 = 全局 `.sku-iact__t { max-width: 60px }` 是按**商品列表**的短标签
   （查看 / 编辑 / 上下架 / 库存 / 删除，最长 3 字）定的；而「我的作品」的
   按钮文字更长（**发到自媒体 = 5 字**、**收录进预设墙 / 从作品墙下架 = 6 字**），
   60px 装不下 → hover 展开时文字被 max-width 截断。
   修法：作品页把展开上限放宽到 96px（6 个汉字约 78px + 余量），
   并允许按钮按内容自然撑开（width:auto），不再被 60px 卡住。
   ⚠️ 只覆盖 .st-work__acts 内的按钮，不动商品列表那一套（那边 60px 刚好）。 */
/* 🔴🔴 v1.16.17 需求 4（用户报障：展开的按钮宽度不足，文字显示不全）：
   真因 = 全局 `.sku-iact__t { max-width: 60px }` 是按**商品列表**的短标签
   （查看 / 编辑 / 上下架 / 库存 / 删除，最长 3 字）定的；而「我的作品」的
   按钮文字更长（**发到自媒体 = 5 字**、**收录进预设墙 / 从作品墙下架 = 6 字**），
   60px 装不下 → hover 展开时文字被 max-width 截断。
   🔴🔴 v1.16.20 用户报障第 11 项（「不是让你把默认状态的按钮拉长」）：
   上一版错在补了一条**无条件**的 `.sku-iact__t { max-width: 96px }` ——
   它把默认收拢态（max-width:0）也覆盖成 96px，按钮默认就带着文字。
   正确做法：默认态继续走全局的 max-width:0，**只在 hover / focus 时**放开到 96px。 */
.st-work__acts .sku-iact:hover .sku-iact__t,
.st-work__acts .sku-iact:focus-visible .sku-iact__t { max-width: 96px; }
/* 展开后按钮行**允许换行兜底**：4 个按钮全展开约 340px > 261px 卡宽，
   若仍 nowrap 会把最后一个按钮挤出卡片。hover 只展开 1 个（其余仍收拢），
   正常情况下不会换行；这里放开 wrap 只是防止极端窄列时溢出。 */
.st-work__acts { flex-wrap: wrap; row-gap: 6px; }

/* ---- 需求 8：生成台「参考图片」区上移到提示词上方 ----
   DOM 顺序由 admin.html 调整（见该文件注释）；这里只保证上移后
   两块之间的间距口径一致（原「提示词 → 附加提示词 → 参考图」三连的
   12px 间距保持不变，不因换序而塌陷或翻倍）。 */
.st-form > .st-field { margin: 0; }
.st-form > .st-field + .st-field { margin-top: 12px; }


/* ---- 🔴 v1.16.15 修复（用户报障：「添加仓库」表单区与下方仓库列表区紧挨着）----
   新增/编辑仓库时，`#inv-wh-form` 在 `#inv-wh-body`（列表）**正上方**内联展开。
   两个 div 相邻且都没有外边距 → 表单卡片的下沿直接贴上列表卡片的上沿，
   视觉上糊成一片。这里只在「表单正在显示」时给它补一段下边距：
   ① 用 `:not([style*="display:none"])` 限定 —— 表单隐藏时（style.display='none'）
      不产生任何多余空白，不改变折叠态的布局；
   ② 20px 与台账页各区块之间的呼吸感一致。
   ⚠️ 本规则追加在文件末尾、所有媒体查询之后（铁律），不新开断点。 */
#inv-wh-form:not([style*="display:none"]) { margin-bottom: 20px; }

/* ---- 🆕 v1.16.15 需求 1：「整款调整」弹窗的**批量填数量**工具条 ----
   场景：从商品列表对一整款开调整单时，所有规格（颜色×尺码）一次铺开，
   数量往往相同；逐个输入太慢。这条工具条给一个数量 + 一键应用。
   布局用 flex-wrap + 固定 basis（宽屏一行、窄屏折行），**不新增媒体查询**（铁律）。
   ⚠️ 追加在文件末尾、所有媒体查询之后。 */
.inv-bulk {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  margin: 0 0 10px; padding: 8px 10px;
  border: 1px dashed var(--panel-border, var(--line));
  border-radius: 10px;
  background: color-mix(in srgb, var(--accent, #b07a3c) 6%, transparent);
}
.inv-bulk__cap { font-size: 12px; color: var(--text-strong); flex: none; }
.inv-bulk__q { width: 110px; flex: none; }
.inv-bulk .tiny { flex: 1 1 180px; }

/* ==========================================================================
   🆕 v1.16.16 需求 2：登录页顶部「品牌三相」——Logo + 品牌名称 + 工作台名称
   --------------------------------------------------------------------------
   背景：旧登录页顶部是「MIRA Image Studio / 形象顾问后台 / 登录后管理客户问卷
   与 AI 初诊报告」三行文字，用户要求整段换成品牌三相（数据来自品牌设置）。
   视觉目标：三相自上而下、居中对齐，层次分明 ——
     · Logo  最大最醒目（64px 方框，圆角 + 细描边；有图放图，无图放品牌首字）
     · 品牌名 次之（26px 衬线，与后台侧栏 .sidebar__logo 同一字体语言）
     · 工作台名 再次（13px，字距拉开，弱化颜色，作副标题）
   深浅两主题一律走 CSS 变量，不硬编码颜色（项目铁律）。
   ⚠️ 本段追加在文件末尾、所有媒体查询之后；注释里不写媒体查询关键字
      （否则 check-v167 的 lastIndexOf 定位会被推到文件末尾，断言假红）。
   ========================================================================== */
/* v1.16.20 用户报障第 8 项：品牌区整体下移（顶距 30→58px，视觉重心更居中） */
.login-brand { padding: 58px 0 20px; text-align: center; }
.login-brand__logo {
  width: 64px; height: 64px; margin: 0 auto 14px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 18px; overflow: hidden;
  border: 1px solid var(--line);
  background: var(--panel-bg-solid, var(--surface));
  box-shadow: 0 4px 16px color-mix(in srgb, var(--accent) 14%, transparent);
}
.login-brand__logo img { width: 100%; height: 100%; object-fit: contain; display: block; }
.login-brand__logo--img { background: #fff; }
.login-brand__mark {
  font-family: var(--serif); font-size: 30px; font-weight: 600; line-height: 1;
  color: var(--accent); letter-spacing: .02em;
}
.login-brand__name {
  font-family: var(--serif); font-size: 26px; font-weight: 600; line-height: 1.2;
  letter-spacing: .16em; color: var(--text-strong, var(--ink)); margin: 0 0 6px;
}
.login-brand__work {
  font-size: 13px; letter-spacing: .22em; color: var(--muted, var(--ink-2));
  margin: 0;
}

/* ---- 🆕 v1.16.16 需求 4：单据类型下拉下方的**一句话简介**条 ----
   用户要求「每个类型右侧增加简短介绍（字体小一点，颜色不要太突出）」。
   原生 select 的 option 无法单独给右侧小字设样式，故：
     ① option 文案里以括号形式带上简介（见 inventory.js paintDocForm）；
     ② 下拉正下方补这条弱色小字，随选择实时更新，五类区别一眼可辨。
   颜色走 var(--muted)，字号 12px，刻意比正文弱一档。 */
.inv-kind-hint {
  margin-top: 5px; font-size: 12px; line-height: 1.5;
  color: var(--muted, var(--ink-2));
}

/* ---- 🆕 v1.16.17 需求 2：单据表单「单据类型」列加宽 / 「经手人」列收窄 ----
   用户报障：新建库存单据的「单据类型」下拉选项显示不完整（被截断）。
   真因：.inv-grid 原为 repeat(auto-fit, minmax(190px, 1fr)) —— **五列等宽**，
        而 v1.16.16 给每个 option 拼了「（增加库存）」这类简介后，
        文案长度翻倍，190px 的列宽放不下，下拉里出现省略号。
   修法：显式给「单据类型」列 2 份宽（约 1.6 倍）、「经手人」列 1 份窄，
        其余列（仓库 / 备注）各 1 份。用 grid-column 定位而不是改 DOM 顺序，
        保证 collectForm() 按 id 取值不受影响。
   ⚠️ 只在 .inv-doc-modal（弹窗态）内生效：仓库内联表单 .inv-form 另有用途，
      不动它，避免波及库存管理其它表单。
   ⚠️ 依项目铁律：本段追加在**所有媒体查询之后**，不插到中间。 */
/* ---- 🆕 v1.16.20 用户报障第 9 项：单据类型收窄 + 经手人回同一行 ----
   旧布局 4 列：类型 span2 + 仓库 + 备注正好占满一行，经手人掉到第二行独立一格。
   用户要求：类型下拉短一点、经手人不换行、输入框变窄、和单据类型同一行。
   改 6 列：类型 span2（约 33%，比旧 50% 窄）、仓库 1、经手人 1（窄）、备注 span2；
   DOM 顺序同步把经手人挪到备注之前（inventory.js paintDocForm），
   collectForm 按 id 取值不受影响。调拨单多一个「调入仓」时备注回绕到下一行，可接受。 */
/* 🔴🔴 v1.16.50 第 3 项：下面两条 :has(#id) 的 grid-column 已**整段废止**。
   真因：:has(#inv-f-kind) 会把参数里 #id 的特异性算进来（1,3,0），
   压过后面 v1.16.48 写的 `.inv-f-kind-cell { grid-column: span 4 }`（0,3,0）——
   所以「单据类型 3→4 格」当时改了 CSS 却**从未生效**，五项仍各占 2 格，
   头部右侧永远空出约 155px（备注右边对不齐明细行的删除按钮）。
   新口径统一在文件末尾的 v1.16.48/50 追加区，这里只保留无害的 min-width。 */
.inv-doc-modal #inv-f-kind { min-width: 0; }
.inv-doc-modal #inv-f-actor { min-width: 0; }

/* ---- 我的作品「类型筛选」分段 tab（v1.16.17）---- */
/* 与「预设作品墙」.st-walltabs 同一套视觉：图标 + 文字，图标不参与收缩。
   容器本身复用全局 .seg（药丸底色 + 内嵌 is-on 高亮），这里只补
   「图标与文字成组、不换行、不被压扁」三条。 */
.st-w-kindtabs { flex: none; }
.st-w-kindtabs .seg__btn { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.st-w-kindtabs .seg__btn svg { flex: none; }

/* ---- 安全库存设置弹窗：规格逐行输入（v1.16.17 需求 5）---- */
.sf-list { display: grid; gap: 8px; max-height: 46vh; overflow-y: auto; padding: 2px; }
.sf-row { display: grid; grid-template-columns: minmax(0, 1fr) auto 96px; gap: 10px; align-items: center; }
.sf-row__n { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13.5px; }
.sf-row__q { flex: none; white-space: nowrap; }
.sf-row__in { min-width: 0; }

/* ============ v1.16.18 场景权重表单：滑块 / 自定义权重 / 自定义勾选框 ============ */
/* 权重行：名称 + 滑块 + 数值回显 + （自定义项）删除按钮。
   v1.16.20 用户报障第 7 项：第 4 列由 auto 改固定 24px ——
   预设行没有删除按钮时 auto 列塌成 0，1fr 滑杆被撑宽；自定义行有按钮 → 滑杆变短，
   两种行滑杆长度不一。固定列宽后所有行滑杆等长，删除按钮固定在最右端（右移到位）。 */
.ai-weights { display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); gap: 10px 16px; }
.ai-weight { display: grid; grid-template-columns: 68px minmax(0, 1fr) 62px 24px; gap: 8px; align-items: center; font-size: 12.5px; color: var(--muted); }
.ai-weight__n { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ai-weight__r { width: 100%; min-width: 0; height: 4px; accent-color: var(--accent); cursor: pointer; }
.ai-weight__v { width: 100%; min-width: 0; padding: 4px 6px; text-align: center; }
.ai-weight__x {
  width: 24px; height: 24px; flex: none; justify-self: end; border: 1px solid var(--panel-border);
  border-radius: 6px; background: transparent; color: var(--muted);
  font-size: 15px; line-height: 1; cursor: pointer; padding: 0;
}
.ai-weight__x:hover { color: var(--danger, #c0392b); border-color: currentColor; }
/* 添加自定义权重 */
.ai-wadd { display: flex; gap: 8px; margin-top: 10px; }
.ai-wadd .input { flex: 1 1 auto; min-width: 0; }
.ai-wadd .btn { flex: none; }

/* 自定义勾选框（替换系统自带样式，符合本项目风格）
   🔴🔴 v1.16.18 修订（角色权限树勾选框消失事故）：
   首版把 `.chk` 基座与「隐藏原生 input」写成了**无差别全局规则** ——
   而全项目只有「场景启用」一处 DOM 带 `.chk__box` 代理显示，
   其余 8 处旧写法（`<label class="chk"><input type="checkbox"> 文案</label>`）
   都是**裸原生 checkbox**：input 被隐藏后又没有 box 顶上来 → 勾选框凭空消失。
   受害者清单（务必别再踩）：角色权限树 pt-l1/pt-l2/pt-act（5 处）、
   门店多选（admin.js 4856 / 9582）、「全选」全门店（4921）。
   规则收敛：以下样式**只对确实带 `.chk__box` 的 `.chk` 生效**，
   旧写法继续走上面 1710 行的 `.chk{display:flex}` + 原生 checkbox。
   ⚠️ 新增「自绘勾选框」必须带 `<span class="chk__box">`，否则等于把自己隐藏。 */
.chk:has(> .chk__box) { position: relative; display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 13.5px; color: var(--text); }
.chk:has(> .chk__box) input[type="checkbox"] { position: absolute; opacity: 0; width: 0; height: 0; }
.chk__box {
  width: 17px; height: 17px; flex: none; border-radius: 5px;
  border: 1.5px solid var(--panel-border); background: var(--panel-bg, transparent);
  display: inline-flex; align-items: center; justify-content: center;
  transition: background .15s, border-color .15s;
}
.chk__box::after {
  content: ''; width: 5px; height: 9px; margin-top: -2px;
  border: solid #fff; border-width: 0 2px 2px 0;
  transform: rotate(45deg) scale(0); transition: transform .15s;
}
.chk input[type="checkbox"]:checked + .chk__box { background: var(--accent); border-color: var(--accent); }
.chk input[type="checkbox"]:checked + .chk__box::after { transform: rotate(45deg) scale(1); }
.chk input[type="checkbox"]:focus-visible + .chk__box { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 28%, transparent); }
.chk__t { user-select: none; }

/* ============ v1.16.18：按钮通用忙态（.is-busy） ============
   知识库「载入基线知识 / 重建索引」等按钮点击后进入 loading：
   禁点 + 变淡 + 右侧转圈，直到操作完成再复位。
   （与 #ai-sync-all 同一套视觉，抽成通用类便于复用。） */
.btn.is-busy { pointer-events: none; opacity: .7; }
.btn.is-busy::after {
  content: ""; display: inline-block; width: 11px; height: 11px; margin-left: 7px;
  vertical-align: -1px; border-radius: 50%;
  border: 2px solid currentColor; border-top-color: transparent;
  animation: prefSpin .8s linear infinite;
}

/* ============ v1.16.18：可搜索客户下拉（.ppick） ============
   用户报障第 4/5 项：所有「选择客户」下拉统一为**可搜索**，
   列表呈现「左头像 / 右上名称 / 右下手机号」三要素。
   实现：原生 <select> 藏起来当值容器，前面插一个 .ppick__btn；
   点开弹出挂 body 的全屏居中面板（避开 .card 的 backdrop-filter 包含块）。 */
.ppick-src { display: none !important; }
.ppick__btn {
  display: inline-flex; align-items: center; justify-content: space-between; gap: 8px;
  width: 100%; min-width: 0; height: 34px; padding: 0 10px;
  border: 1px solid var(--panel-border); border-radius: 9px;
  background: var(--panel-bg, transparent); color: var(--text);
  font-size: 13.5px; font-family: inherit; cursor: pointer; text-align: left;
}
.ppick__btn:hover { border-color: var(--accent); }
.ppick__t { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ppick__btn.is-empty .ppick__t { color: var(--muted); }
.ppick__ar { flex: none; opacity: .65; }

.ppick-layer { position: fixed; inset: 0; z-index: 1260; background: rgba(20, 18, 14, .42); }
.ppick {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: min(520px, 92vw); max-height: min(560px, 84vh);
  display: flex; flex-direction: column; overflow: hidden;
  /* v1.16.20：--card 变量不存在（真实变量是 --panel-bg-solid），旧写法永远回落 #fff
     → 深色模式下弹窗是一整块白底。改用真变量 + 深浅各自正确。 */
  background: var(--panel-bg-solid, #fff); border: 1px solid var(--panel-border);
  border-radius: 14px; box-shadow: var(--shadow, 0 24px 60px rgba(0, 0, 0, .28));
}
.ppick__h { flex: none; display: flex; align-items: center; gap: 10px; padding: 14px 16px 10px; }
.ppick__ttl { font-size: 15px; font-weight: 600; }
.ppick__x {
  margin-left: auto; width: 30px; height: 30px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--panel-border); border-radius: 8px;
  background: transparent; color: var(--muted); cursor: pointer; padding: 0;
}
.ppick__x:hover { color: var(--text); border-color: currentColor; }
.ppick__sb { flex: none; position: relative; padding: 0 16px 10px; }
.ppick__si { position: absolute; left: 27px; top: 9px; color: var(--muted); pointer-events: none; }
.ppick__q { width: 100%; height: 34px; padding: 0 10px 0 34px; border-radius: 9px; }
.ppick__list { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 4px 10px 12px; }
.ppick__empty { padding: 26px 8px; text-align: center; font-size: 13px; color: var(--muted); }
.ppick__row {
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 8px 10px; border: 1px solid transparent; border-radius: 10px;
  background: transparent; cursor: pointer; text-align: left; font-family: inherit;
}
.ppick__row:hover { background: color-mix(in srgb, var(--accent) 9%, transparent); }
.ppick__row.is-on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.ppick__meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ppick__nm { font-size: 13.5px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ppick__ph { font-size: 12px; font-style: normal; color: var(--muted); }
/* 面板内的头像：与列表页 .pav 同口径，只是稍小 */
.ppick__row .pav { flex: none; }

/* ============ v1.16.18：形象档案名片区 + 照片库 ============ */
.ai-card--head { display: flex; align-items: center; gap: 14px; }
.ai-head__meta { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ai-head__nm { font-size: 16px; }
.ai-head__ph { font-size: 12.5px; color: var(--muted); }
.ai-head__side { margin-left: auto; display: flex; flex-direction: column; gap: 4px; align-items: flex-end; }
.ai-head__tag { font-size: 11.5px; color: var(--muted); white-space: nowrap; }
.ai-photos { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 8px; }
.ai-photos__i {
  width: 100%; aspect-ratio: 3 / 4; object-fit: contain;
  /* v1.16.20：白底写死在深色模式下刺眼，改随主题；无图时也是柔和的占位底 */
  background: var(--panel-bg-solid, #fff); border: 1px solid var(--panel-border); border-radius: 8px;
}

/* ============ v1.16.18：穿搭方案网格 + 人体分区 ============
   用户报障第 6 项：方案排版改网格，并按人体从上到下的顺序分隔区域；
   每件推荐服装显示商品主图（取 sku_media 主图，失败回落首字占位块）。 */
.ai-zone { margin: 10px 0 0; }
.ai-zone__h { display: flex; align-items: center; gap: 7px; margin-bottom: 7px; }
.ai-zone__nm { font-size: 12.5px; font-weight: 600; color: var(--text); }
.ai-zone__ct {
  font-size: 11px; color: var(--muted); padding: 1px 7px;
  border: 1px solid var(--panel-border); border-radius: 999px;
}
/* 🔴 v1.16.21 第 8 项：方案内商品卡由「左图右文」改为「上图下文」——
   旧布局是 52×66 的小图 + 右侧 1fr 文字，商品名/理由全被挤成一行省略号
   （用户原话：显示过于小气、内容挤压严重）。现在整卡竖向排布，主图占满卡宽
   （4:5 竖版，与商品列表的呈现一致），下方依次是名称 → 品类·颜色 → 推荐理由
   → 价格与「替换」按钮；名称与理由都放开成多行截断，不再 nowrap 吞字。 */
/* 🔴 v1.16.22：grid → flex 横排 —— 每个部位只推荐一件、一行平铺（宽度不足换行），
   单卡固定 216px；4:5 主图同时改 1:1 正方形（用户第 4② 项）。 */
.ai-zone__g { display: flex; flex-wrap: wrap; gap: 10px; }
.ai-cell { width: 216px; }
.ai-cell {
  display: flex; flex-direction: column; gap: 8px;
  padding: 10px;   border: 1px solid var(--panel-border); border-radius: 12px;
  background: var(--panel-bg, transparent);
}
.ai-cell__fig {
  width: 100%; aspect-ratio: 1 / 1; flex: none; display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--panel-border); border-radius: 10px;
  /* v1.16.20：占位与图片底色改随主题（商品白底图在深色下也不再是硬白块） */
  background: var(--panel-bg-solid, #fff); overflow: hidden; color: var(--muted); font-size: 20px; font-weight: 600;
}
.ai-cell__fig img { width: 100%; height: 100%; object-fit: contain; }
.ai-cell__bd { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.ai-cell__nm {
  font-size: 13.5px; line-height: 1.45; color: var(--text);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.ai-cell__sub { font-size: 12px; color: var(--muted); line-height: 1.4; }
.ai-cell__pr { font-size: 14px; font-weight: 600; color: var(--accent); }
.ai-cell__rep { flex: none; }

/* ============ v1.16.20：穿搭方案卡 —— 逐件理由 / 空分区提示 / 合计行 ============
   用户报障第 6 项：每件商品带推荐理由；商品库没货的分区明说，不默默隐藏；
   底部合计价格醒目化。全部走主题变量，深浅双模自适应。 */
.ai-zone--empty .ai-zone__ct { opacity: .6; }
.ai-zone__none {
  margin: 2px 0 10px; padding: 9px 12px; font-size: 12.5px; color: var(--muted);
  border: 1px dashed var(--panel-border); border-radius: 9px; background: transparent;
}
.ai-cell__why {
  font-size: 12px; color: var(--accent); line-height: 1.55;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
/* v1.16.21 第 8 项：竖向卡里「价格 + 替换」改横向一行（价格左、按钮右），
   不再像旧布局那样竖排挤在卡片右端。 */
.ai-cell__side {
  display: flex; flex-direction: row; align-items: center; justify-content: space-between; gap: 8px;
  margin-top: auto; padding-top: 2px;
}
.ai-outfit__total {
  display: flex; align-items: center; gap: 10px; margin-top: 10px; padding: 8px 12px;
  border: 1px solid var(--panel-border); border-radius: 9px;
  background: var(--accent-soft); font-size: 12.5px; color: var(--muted);
}
.ai-outfit__total b { margin-left: auto; font-size: 14.5px; color: var(--text); }

/* ============ v1.16.20：作品视频源失效占位（用户报障第 10 项） ============
   存量作品的百炼 OSS 链接过期后 video 必然加载失败 —— 与其无声黑屏，
   不如明确告知「链接已过期」。新增数据已在生成时转存自有 storage，不会再过期。 */
.st-work__stage { position: relative; }
.st-work__stage.is-broken::after {
  content: '视频源已过期，无法播放';
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 12.5px; color: var(--muted); text-align: center; padding: 0 14px;
  background: color-mix(in srgb, var(--bg) 78%, transparent);
}
.st-lb__expired {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 13.5px; color: var(--text); text-align: center; padding: 0 26px; line-height: 1.7;
}
#st-lb-stage { position: relative; }

/* ============ v1.16.21 十三项报障批次（新增规则统一追加在所有媒体查询之后） ============ */

/* ① 选择客户弹层里的搜索框：挂上全局 .input 后由 .input 统一供给边框/底色/圆角，
   这里只保留搜索框特有的「左侧留图标位」内边距与更圆一点的角，避免抢掉 .input 的皮肤。 */
.ppick__q.input { padding: 0 10px 0 34px; border-radius: 9px; height: 34px; }

/* ⑥ / ⑬ 弹窗字段两等分网格：
   🔴 旧的 .fgrid 是 auto-fill minmax(132px,1fr) —— 560px 弹窗排出 3 列、
   640px 弹窗排出 4 列，于是「作用域+级别」「模板名称+场景」各占一小截，
   合计宽度远小于下方整行的输入框，看起来就是没对齐。
   固定两列后两者之和（含 gap）等于整行宽度，与下方输入框左右边缘对齐。 */
.fgrid--pair { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* ⑥ 字段说明从标签行移到输入框下方：独立一行、不参与标签换行计算。 */
.field__hint { margin-top: 6px; font-size: 11.5px; line-height: 1.6; color: var(--muted); }

/* ④ 问卷 / 报告记录行里的「档案编号」列：等宽小标签，与编号、时间同一行不抢空间。 */
.ai-line__arch {
  font-size: 11.5px; color: var(--muted); padding: 1px 7px;
  border: 1px solid var(--panel-border); border-radius: 999px;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* ② 形象档案照片墙：可点开看大图（滚轮缩放 / 按钮缩放 / 1:1 恢复 / 拖拽平移）。 */
.ai-photos__i.is-zoomable { cursor: zoom-in; transition: transform .15s ease, box-shadow .15s ease; }
.ai-photos__i.is-zoomable:hover { transform: scale(1.04); box-shadow: 0 6px 18px rgba(0, 0, 0, .28); }

/* ⑪ AI 顾问会话：归档（hover 才出现的「归档」按钮 + 已归档标记）。
   🔴 .ai-sess 原本是 <button>，按钮里不能再套按钮（非法且点击会冒泡冲突），
      已改成带 role/tabindex 的 div；这里补上键盘可达的焦点样式。 */
.ai-sess { position: relative; }
.ai-sess__arch {
  flex: none; font-size: 11px; padding: 2px 7px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--panel-border); background: transparent; color: var(--muted);
  opacity: 0; transition: opacity .15s ease;
}
.ai-sess:hover .ai-sess__arch, .ai-sess:focus-within .ai-sess__arch { opacity: 1; }
.ai-sess__arch:hover { color: var(--accent); border-color: var(--accent); }
.ai-sess.is-archived { opacity: .62; }
.ai-sess__tag {
  flex: none; font-size: 10.5px; padding: 1px 6px; border-radius: 999px;
  border: 1px solid var(--panel-border); color: var(--muted);
}
.ai-ag-showarch {
  font-size: 11.5px; color: var(--muted); cursor: pointer;
  display: inline-flex; align-items: center; gap: 5px;
}

/* ⑪ 会话行的「元信息 + 归档按钮」横排容器（.ai-sess 本身是竖向 flex）。 */
.ai-sess__row { display: flex; align-items: center; gap: 6px; min-width: 0; }
.ai-sess__row > .tiny { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ⑪② AI 顾问侧栏「客户 / 模型」两个下拉之间的间距。
   🔴 不能写在 #ai-ag-model 的行内 margin 上：它会被 csel 增强壳包住，
   原生 select 变 display:none 后行内 margin 一起失效（实测间距归 0）。
   改由容器用 flex gap 统一给 —— display:none 的原生 select 不参与 flex 布局，
   所以 gap 恰好落在「客户下拉按钮」与「模型下拉外壳」之间。 */
.ai-agent__bind { display: flex; flex-direction: column; gap: 14px; }

/* ============ v1.16.22 十五项报障批次（统一追加在所有媒体查询之后） ============ */

/* ④① 商品详情「图片素材」格子：显示区改 1:1 正方形（旧实现高度随图，横图把格子拉扁）。 */
.mgrid .mcell img { width: 100%; aspect-ratio: 1 / 1; object-fit: contain; display: block; border-radius: 6px; background: var(--panel-bg-solid, #fff); }
.mcell--add { aspect-ratio: 1 / 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; }

/* ⑤ 替换商品列表：左图右文 —— 左侧正方形主图（水合失败回落首字占位），
   右侧上名称、下属性；价格仍靠右。 */
.ai-pick__row--card { align-items: center; padding: 8px 10px; }
.ai-pick__fig {
  flex: none; width: 56px; height: 56px; border-radius: 8px; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--panel-border); background: var(--panel-bg-solid, #fff);
  color: var(--muted); font-size: 18px; font-weight: 600;
}
.ai-pick__fig img { width: 100%; height: 100%; object-fit: contain; }
.ai-pick__bd { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ai-pick__attr { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ⑦ 「显示已归档」：缩小、变暗、退居辅助位（v1.16.21 的旧定义在同文件上方，这里覆盖）。 */
/* 🔴 特异性必须 ≥ .chk:has(> .chk__box)（0,2,0），否则 13.5px 会盖回来 —— 用 .chk.ai-ag-showarch。 */
.chk.ai-ag-showarch { margin: 8px 2px 0; font-size: 11px; color: var(--muted); opacity: .82; }
.chk.ai-ag-showarch .chk__box { width: 13px; height: 13px; }

/* ⑧ AI 顾问：输入框与发送按钮固定在可视区底部 —— 侧栏与聊天主区都锁高度、
   内部各自滚动（旧实现整个 ai-agent 随页面长高，输入区被顶到页面中部）。 */
.ai-agent__main { height: calc(100vh - 235px); min-height: 430px; }
.ai-agent__main .ai-chat { flex: 1 1 auto; min-height: 0; max-height: none; }
.ai-agent__main .ai-chat__input { flex: none; }

/* ⑨ AI 回复排版：思考过程折叠块（可展开），think 区用自动折行 ——
   模型吐的思考文本里夹着大量换行，pre-wrap 会碎成「每几个字一行」；normal 让浏览器重排。 */
.ai-msg__think {
  margin: 0 0 8px; border: 1px dashed var(--panel-border); border-radius: 8px;
  background: transparent; font-size: 12px;
}
.ai-msg__think summary { padding: 5px 9px; color: var(--muted); cursor: pointer; user-select: none; }
.ai-msg__think-b { padding: 2px 10px 8px; color: var(--muted); line-height: 1.65; white-space: normal; overflow-wrap: anywhere; }
.ai-msg__txt { white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.7; }
.ai-tool__raw summary { cursor: pointer; color: var(--muted); font-size: 11.5px; user-select: none; }
.ai-tool__raw summary:hover { color: var(--text); }

/* ⑩ 数字衣橱行主图：1:1 正方形（旧 48×60 竖版 + 首字占位），真实商品主图由 data-skuthumb 水合。 */
.ai-wd__fig { width: 56px; height: 56px; }
.ai-wd__fig img { width: 100%; height: 100%; object-fit: cover; }

/* ⑪ 新增单品弹窗的色卡点选：圆形色块 + 选中描边。 */
.aiw-swatches { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 2px; }
.aiw-sw {
  width: 22px; height: 22px; border-radius: 50%; padding: 0; cursor: pointer;
  border: 1px solid var(--panel-border); box-shadow: inset 0 0 0 2px var(--panel-bg-solid, #fff);
}
.aiw-sw.is-on { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ⑮ 反馈迭代行：动作标签与标题之间留出间距（旧写法 pill 紧贴文字）。 */
.ai-row__t .ai-pill { margin-right: 8px; }


/* ══════════════════════════════════════════════════════════
   v1.16.23 十四项报障批次
   ⚠️ 依项目铁律：本段追加在所有断点块之后，不插到中间。
   ══════════════════════════════════════════════════════════ */

/* ---- 第 5 项：替换 / 添加商品弹窗的部位筛选 tab（不用下拉） ---- */
.ai-pick__tabs { display: flex; flex-wrap: wrap; gap: 6px; }
.ai-pick__tab {
  padding: 4px 12px; border-radius: 999px; border: 1px solid var(--line-soft);
  background: var(--panel-bg); color: var(--muted); font-size: 12px; cursor: pointer;
}
.ai-pick__tab:hover { border-color: var(--accent); color: var(--text); }
.ai-pick__tab.is-on { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); font-weight: 600; }

/* ---- 第 6 项：多套方案左侧竖向 tab 导航 ---- */
.ai-rail { display: grid; grid-template-columns: 150px 1fr; gap: 12px; align-items: start; }
.ai-rail__tabs {
  position: sticky; top: 10px; display: flex; flex-direction: column; gap: 6px;
  padding: 8px; border: 1px solid var(--line-soft); border-radius: var(--radius);
  background: var(--panel-bg);
}
.ai-rail__tab {
  padding: 8px 10px; border-radius: var(--radius-sm); border: 0; cursor: pointer;
  background: transparent; color: var(--muted); font-size: 12.5px; text-align: left;
  overflow-wrap: anywhere;
}
.ai-rail__tab:hover { background: var(--hover); color: var(--text); }
.ai-rail__tab.is-on { background: var(--accent-soft); color: var(--accent); font-weight: 600; }

/* ---- 第 7 项：方案标题头与下方区域隔开 + 细节修饰；部位之间加间距 ---- */
.ai-outfit__hd {
  padding: 10px 12px; margin: 0 0 12px; border-radius: var(--radius-sm);
  background: var(--hover); border: 1px solid var(--line-soft);
  border-left: 3px solid var(--accent);
}
.ai-zone + .ai-zone { margin-top: 18px; padding-top: 14px; border-top: 1px dashed var(--line-soft); }
.ai-outfit__total { margin-top: 14px; }

/* ---- 第 11 项①：方案理由独立框选区域、字号放大、排版修饰 ---- */
.ai-outfit__reason {
  margin: 14px 0 0; padding: 12px 14px;
  border: 1px solid var(--accent-soft); border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm); background: var(--panel-bg);
  font-size: 13.5px; line-height: 1.9; color: var(--text-strong);
}
p.ai-outfit__reason { font-size: 12.5px; color: var(--muted); border-style: dashed; border-left-color: var(--line-soft); }

/* ---- 第 12 项：色卡改「颜色块 + 色名」组合 chip ---- */
.aiw-sw {
  width: auto; height: 26px; border-radius: 999px; padding: 2px 10px 2px 3px; cursor: pointer;
  border: 1px solid var(--panel-border); background: var(--panel-bg);
  display: inline-flex; align-items: center; gap: 6px; color: var(--text); font-size: 12px;
}
.aiw-sw i { width: 20px; height: 20px; border-radius: 50%; flex: none; display: block; box-shadow: inset 0 0 0 1px rgba(0,0,0,.12); }
.aiw-sw.is-on { outline: 2px solid var(--accent); outline-offset: 1px; font-weight: 600; }

/* ---- 第 13 项：衣橱首字占位与容器同尺寸正方形（旧 48×60 竖版残留） ---- */
.ai-wd__ph { width: 100%; height: 100%; }

/* ---- 第 14 项：配色板（同色系 / 对比点缀 / 中性打底） ---- */
.wd-pal { display: inline-flex; align-items: center; gap: 6px; margin: 0 10px 8px 0; }
.wd-pal i { width: 34px; height: 34px; border-radius: 8px; display: block; border: 1px solid var(--panel-border); }
.wd-pal code { font-size: 11.5px; color: var(--muted); }
.wd-pal__row { display: flex; flex-wrap: wrap; align-items: center; }
.wd-pal__hero { height: 64px; border-radius: var(--radius-sm); border: 1px solid var(--line-soft); margin: 12px 0 4px; }

/* ---- 第 15 项：方案详情理由框（复用配色与字号口径） ---- */
.op-reason {
  margin: 12px 0; padding: 12px 14px;
  border: 1px solid var(--accent-soft); border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm); background: var(--panel-bg);
}
.op-reason b { display: block; margin-bottom: 4px; font-size: 12px; color: var(--accent); }
.op-reason p { margin: 0; font-size: 13.5px; line-height: 1.9; color: var(--text-strong); }
/* ============================== v1.16.24 批次 ============================== */
/* 自动任务表单四行重排：行2 三等分 / 行3 两等分，行宽全部与容器对齐 */
.aau-grid3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 0 0 12px; }
.aau-grid2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 0 0 12px; }
.aau-grid3 .field, .aau-grid2 .field { min-width: 0; }
/* 门店范围：网格排布 + 统一自定义勾选框（.chk + .chk__box） */
.aau-stores { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 2px 16px; margin-top: 6px; }
.aau-stores .chk { padding: 4px 0; }
/* 批量选择客户弹窗：ppick 行样式 + 统一勾选框 + 底部固定操作条 */
.rcm__bar { display: flex; align-items: center; gap: 14px; margin: 0 0 8px; }
.rcm__list { max-height: 46vh; overflow-y: auto; border: 1px solid var(--line-soft); border-radius: 10px; padding: 4px; }
.chk.rcm-row { display: flex; width: 100%; padding: 7px 10px; border-radius: 10px; border: 1px solid transparent; }
.chk.rcm-row:hover { background: color-mix(in srgb, var(--accent) 9%, transparent); }
.rcm__foot { flex: none; display: flex; align-items: center; gap: 10px; padding: 12px 20px 14px; border-top: 1px solid var(--line-soft); }

/* ============================== v1.16.25 批次 ============================== */
/* 穿搭方案列表：编号不换行、整行可点 */
.op-tbl .ai-code { white-space: nowrap; }
.op-tbl__row { cursor: pointer; }
.op-tbl__row:hover td { background: color-mix(in srgb, var(--accent) 7%, transparent); }
/* 方案详情右侧抽屉（与客户详情同款 .drawer 形态，独立实例避免污染问卷抽屉） */
.op-drawer { z-index: 96; }
.op-drawer__scrim {
  position: fixed; inset: 0; z-index: 95; background: rgba(12, 9, 5, 0.45);
  opacity: 0; pointer-events: none; transition: opacity 0.22s ease;
}
.op-drawer__scrim.is-on { opacity: 1; pointer-events: auto; }
.opd__sum { display: flex; align-items: center; gap: 14px; padding: 10px 12px; margin-bottom: 12px;
  border: 1px solid var(--panel-border); border-radius: 12px; background: color-mix(in srgb, var(--panel-bg) 60%, transparent); }
.opd__sum-score, .opd__sum-total { font-size: 13px; color: var(--muted); }
.opd__sum-score b, .opd__sum-total b { color: var(--text-strong); font-size: 15px; margin-left: 4px; }
.opd__zone { margin-bottom: 14px; }
.opd__zone-h { display: flex; align-items: baseline; gap: 8px; font-size: 13.5px; font-weight: 600;
  color: var(--text-strong); padding-bottom: 6px; border-bottom: 1px dashed var(--line-soft); margin-bottom: 8px; }
.opd__zone-h span { font-weight: 400; font-size: 12px; color: var(--muted); }
.opd__item { display: flex; align-items: center; gap: 12px; padding: 7px 4px; }
.opd__item + .opd__item { border-top: 1px solid color-mix(in srgb, var(--line-soft) 60%, transparent); }
.opd__fig {
  flex: none; width: 54px; height: 54px; border-radius: 10px; overflow: hidden;
  background: #fff; border: 1px solid var(--panel-border);
  display: flex; align-items: center; justify-content: center; cursor: zoom-in;
}
.opd__fig img { width: 100%; height: 100%; object-fit: contain; }
.opd__ph { font-size: 18px; color: var(--muted); font-family: var(--serif); }
.opd__bd { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.opd__bd b { font-size: 13.5px; }
.opd__why { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.opd__pr { flex: none; font-size: 13.5px; color: var(--text-strong); }
/* 批量选择客户：搜索图标与输入框不再重叠（弹窗内去掉面板默认左右 padding 后图标需重新对位） */
.rcm__sb { position: relative; padding: 0 0 10px; }
.rcm__sb .ppick__si { left: 11px; top: 8px; }
.rcm__sb .ppick__q { padding-left: 32px; }
/* 档案聚合 · 数字衣橱主图卡片网格 */
.ai-wdgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); gap: 10px; }
.ai-wdcell { display: flex; flex-direction: column; gap: 4px; padding: 8px;
  border: 1px solid var(--panel-border); border-radius: 12px; background: color-mix(in srgb, var(--panel-bg) 55%, transparent); }
.ai-wdcell__fig {
  width: 100%; aspect-ratio: 1 / 1; border-radius: 8px; overflow: hidden;
  background: #fff; border: 1px solid var(--panel-border);
  display: flex; align-items: center; justify-content: center;
}
.ai-wdcell__fig[data-skuzoom] { cursor: zoom-in; }
.ai-wdcell__fig img { width: 100%; height: 100%; object-fit: contain; }
.ai-wdcell__ph { font-size: 22px; color: var(--muted); font-family: var(--serif); }
.ai-wdcell__nm { font-size: 12.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ai-wdcell__color { display: flex; align-items: center; gap: 5px; min-width: 0; }
.ai-wdcell__color em { font-style: normal; font-size: 11.5px; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ai-cdot { flex: none; width: 12px; height: 12px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--text) 25%, transparent); display: inline-block; }
/* 历史方案行：编号徽章不换行 */
.ai-line .ai-code { white-space: nowrap; }
/* 灯箱缩略图条：层级压过大图点击区，保证可点。
   🔴 v1.16.54 第 3 项修：原来写的是 `position: relative` —— 相对定位会留在
   .lbx__box 的普通流里（顶部），而 style.css 又给了 `bottom: 118px`，
   于是整条被**上移 118px**顶到视口外（实测 getBoundingClientRect().top = -118）：
   缩略图条常年看不见，但 .lbx.has-thumbs 仍按 196px 预留底部空间，
   把图片挤到屏幕上半部分 —— 这正是用户报的「内容没有上下居中」。
   这里必须回到 absolute（.lbx__box 是 inset:0 的定位父级），只把层级提高。 */
.lbx__thumbs { position: absolute; z-index: 6; }

/* ==================================================================
   v1.16.27 十项报障批次新增样式
   ⚠️ 依项目铁律：新规则追加在**所有媒体查询之后**（本文件最后一个媒体查询
      在 260914 处结束），靠源序覆盖；不新增媒体查询。
   ================================================================== */

/* ---- 第 6 项：穿搭推荐左右两栏上边框齐平 ----
   根因：右侧卡片容器 .ai-outfits 自带 margin-top:12px（为「非 rail 场景」加的
   与上一段的间距），一旦作为 .ai-rail 的右栏就变成比左侧 tab 低 12px。
   在 rail 内归零，两栏顶边即对齐。 */
.ai-rail__cards.ai-outfits, .ai-rail .ai-outfits { margin-top: 0; }

/* ---- 第 9 项：左侧方案 tab = 名称 + 生成时间小字 ---- */
.ai-rail__tab { display: flex; flex-direction: column; gap: 2px; line-height: 1.35; }
.ai-rail__tab-t { font-size: 12.5px; }
.ai-rail__tab-d { font-size: 11px; opacity: .68; font-weight: 400; }

/* ---- 第 1 项③④：私域触达设置 —— 分块卡片 + 统一内边距 ----
   上一版把说明文字直接堆在边框线上、整块还掉在最外层卡片之外；
   这里每个通道一个 .reach-box：标题条 + 16px 内边距内容区，
   字段之间 12px，说明文字独立成 .reach-note 有自己的留白。 */
.reach-set { display: flex; flex-direction: column; gap: 16px; }
.reach-box {
  border: 1px solid var(--line-soft); border-radius: var(--radius);
  background: var(--panel-bg); overflow: hidden;
}
.reach-box__h {
  padding: 10px 16px; font-size: 13px; font-weight: 600; color: var(--text-strong);
  background: var(--hover); border-bottom: 1px solid var(--line-soft);
}
.reach-box__b { padding: 16px; display: flex; flex-direction: column; gap: 14px; }
.reach-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.reach-field__k { font-size: 12.5px; color: var(--muted); }
.reach-field__n { font-size: 11.5px; line-height: 1.75; color: var(--muted); }
.reach-field .input { width: 100%; }
.reach-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.reach-note {
  padding: 10px 12px; border-radius: var(--radius-sm);
  background: var(--hover); border-left: 3px solid var(--accent);
  font-size: 11.5px; line-height: 1.8; color: var(--muted);
}
.reach-acts { display: flex; align-items: center; gap: 10px; }

/* ---- 第 2 项：触达任务筛选区 ---- */
.ai-rc-tabs { margin-top: 12px; }
.ai-rc-bulk {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 10px; padding: 10px 14px;
  border: 1px solid var(--line-soft); border-radius: var(--radius);
  background: var(--panel-bg);
}
.ai-row__pick { margin-top: 8px; }
.ai-row { position: relative; }

/* ---- 第 10 项：颜色三件套（色卡 + 中文名 + 色号） ---- */
.wd-color {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; color: var(--text);
}
.wd-color em { font-style: normal; }
.wd-color .ai-code { font-size: 11px; padding: 1px 5px; }
.ai-wdcell__color .wd-color { gap: 4px; font-size: 11.5px; }

.wd-color__tone { color: var(--muted); font-size: 11.5px; }

/* ==========================================================================
   v1.16.28 · 九项报障批次（私域助手一级菜单 / 查看器 / 占位块 / 自媒体表单）
   ⚠️ 本段追加在所有断点块之后：新规则只覆盖主题令牌，不再新增断点块。
   ========================================================================== */

/* ---- 1) 商品图可点（统一手型） -------------------------------------------
   ｜ 凡是挂了 data-skuzoom 的图格都进图片查看器；补 cursor 提示可点。 */
.ai-cell__fig[data-skuzoom],
.ai-pick__fig[data-skuzoom],
.opd__fig[data-skuzoom],
.ai-wdcell__fig[data-skuzoom] { cursor: zoom-in; }

/* ---- 2) 首字占位块统一（深色主题下不再出现刺眼白块 / 低对比灰字） --------
   ｜ 用户要求：同一个「没有图」的状态，跨页面必须是同一种样式。
   ｜ 统一口径 = 主题底色 + 香槟金细边 + 中性色衬线首字。 */
.opd__fig {
  background: var(--panel-bg-solid, #1E1A17);
  border-color: var(--panel-border-strong);
}
.opd__ph { color: var(--accent); opacity: .72; }
.ai-cell__fig { border-color: var(--panel-border-strong); }
.ai-cell__ph,
.ai-pick__ph,
.ai-wdcell__ph,
.ai-wd__ph { color: var(--accent); opacity: .72; }

/* ---- 3) Skill 配置：两段式表单 + 卡片右上角操作区 ------------------------
   ｜ 文本模型 / 图片模型 / 发布方式 各占一行；语气风格 / 内容形态 / 排版模板
   ｜ 同一行三列，宽度随容器（与配置名称输入框一致）。
   ｜ 用 auto-fit 而不是断点块：窄屏自动折成一列，不新增断点块。 */
.md-form3 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
  margin-top: 10px;
}
.md-skill-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.md-skill-ops {
  display: flex;
  gap: 6px;
  margin-left: auto;
}
.md-skill-ops .btn { padding: 5px 12px; font-size: 12.5px; }

/* ---- 4) 选题：模型下拉与生成按钮同排，状态行留出下间距 ------------------ */
#media-topic-pane .toolbar #md-topic-model { min-width: 150px; }

/* ============================================================
   v1.16.29 AI 自媒体：选题卡信息分层 · 配图工具条 · 排版 HTML 编辑
   ------------------------------------------------------------
   1) 选题卡：三段文案（切入角度 / 推荐理由 / 关键词）加**加粗小标题**，
      关键词改成小标签。原来三行灰字直接堆着，分不清哪句是哪段。
   2) 配图：模型下拉 + 张数输入同一行；单张操作里「删除」改成 26px 图标按钮，
      两个文字按钮在 120px 卡片里必然换行挤压（用户截图里的原症状）。
   3) 排版：新增「HTML（可编辑）」文本域，等宽小字，可改文字 / 删图 / 插图。
   注意：这段必须留在文件最末（前面已有多处断点块），且注释里不写断点字面量，
        否则会被 check-v225 的「CSS 末尾纪律」断言误判。
   ============================================================ */

/* ---- 1) 选题卡信息分层 ---- */
.md-item__rows { display: flex; flex-direction: column; gap: 8px; margin-top: 9px; }
.md-row {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  gap: 10px;
  align-items: start;
}
.md-row__k {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text);
  line-height: 1.7;
  letter-spacing: .2px;
}
.md-row__v {
  font-size: 12.5px;
  color: var(--muted);
  line-height: 1.78;
  word-break: break-word;
  min-width: 0;
}
/* 关键词行内是一串标签，用 flex 排；纯文本行不受影响 */
.md-row__v:has(.md-kw__i) { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.md-kw__i {
  display: inline-block;
  padding: 1px 9px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 28%, transparent);
  color: var(--text);
  font-size: 12px;
  line-height: 1.75;
}
[data-theme="dark"] .md-kw__i {
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  border-color: color-mix(in srgb, var(--accent) 32%, transparent);
}

/* ---- 2) 配图工具条 + 单张操作 ---- */
.md-imgbar { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; align-items: center; }
.md-imgbar__f { display: flex; align-items: center; gap: 8px; flex: 1 1 190px; min-width: 0; }
.md-imgbar__f--n { flex: 0 0 auto; }
.md-imgbar__k { flex: none; font-size: 12px; color: var(--muted); }
.md-imgbar .input { max-width: none; }
/* select 被 csel 壳接管后，壳才是实际盒模型 —— 弹性要给壳 */
.md-imgbar__f > .csel { flex: 1 1 auto; width: auto; min-width: 0; }
.md-imgbar__f--n > .input { width: 76px; }
.md-imgbar__f--n > .csel { flex: none; width: 76px; }

.md-img__cap { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.md-img__ops { display: flex; gap: 6px; align-items: center; flex-wrap: nowrap; }
.md-img__ops .btn { min-width: 0; padding: 4px 8px; font-size: 12px; white-space: nowrap; }
.md-iconbtn {
  flex: none;
  width: 26px; height: 26px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  padding: 0;
}
.md-iconbtn:hover {
  color: var(--danger);
  border-color: color-mix(in srgb, var(--danger) 45%, var(--line));
  background: color-mix(in srgb, var(--danger) 8%, transparent);
}
.md-iconbtn:disabled { opacity: .4; cursor: not-allowed; }
.md-imgops { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 10px; }

/* ---- 3) 排版：编辑区 ---- */
.md-laybar { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 10px; }
.md-laybar #md-ins-img { max-width: 180px; }
.md-laybar > .csel { flex: 0 1 180px; min-width: 120px; }
.md-html {
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.7;
  min-height: 124px;
  resize: vertical;
}

/* ==========================================================================
   v1.16.31 AI 自媒体稿件页批次（图标按钮 / 生成面板 / 比例行 / 图文模式 / 插图弹窗）
   放在文件最后：所有既有断点块都在上面，无需再穿插媒体查询。
   ========================================================================== */

/* 1) 图标 + 文字组合按钮（用户要求所有按钮统一这一款） */
.btn--ico { display: inline-flex; align-items: center; gap: 6px; }
.btn--ico > svg { flex: none; }
.btn--ico > span { white-space: nowrap; }

/* 2) 生成面板：思考区固定高度、正文区固定高度 —— 流式输出不许把下面内容顶下去 */
.md-stream__bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.md-think {
  max-height: 76px;
  overflow: auto;
  margin-bottom: 8px;
  padding: 8px 10px;
  border: 1px dashed var(--line);
  border-radius: 8px;
  background: color-mix(in srgb, var(--panel-bg-solid) 94%, #000);
  color: var(--muted);
  font-size: 12px;
  line-height: 1.7;
  white-space: pre-wrap;
  word-break: break-word;
}
.md-stream__box { height: 200px; max-height: 200px; overflow: auto; }

/* 3) 已停止 / 失败面板：内容与边框留出间距（用户第 3 项①） */
.md-stopbox { padding: 16px 18px; }
.md-stopbox__note { margin: 0 0 12px; }
.md-stopbox__ops { display: flex; gap: 8px; flex-wrap: wrap; }
.md-stopbox__hint { margin: 10px 0 0; }

/* 4) 配图比例行（生成配图按钮正上方） */
.md-ratio { margin-top: 10px; }
.md-ratio > .md-imgbar__k { display: block; margin-bottom: 6px; }
.md-ratio__box { margin-top: 0; }

/* 5) 排版：代码 / 图文 双模式 */
.md-hmode__row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.md-seg { display: inline-flex; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.md-seg > button {
  border: 0;
  background: transparent;
  color: var(--muted);
  font-size: 12px;
  line-height: 1;
  padding: 6px 11px;
  cursor: pointer;
}
.md-seg > button.is-on { background: var(--accent-soft); color: var(--accent); }
.md-rt {
  min-height: 200px;
  max-height: 460px;
  overflow: auto;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: #fff;
  color: #2A241E;
}
.md-rt img { max-width: 100%; height: auto; display: block; margin: 10px auto; }
.md-rt figure { margin: 14px 0; }
.md-rt:focus { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: 1px; }

/* 6) 下载图标：悬停走强调色（删除键才走危险色） */
.md-iconbtn[data-dlimg]:hover {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 45%, var(--line));
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}

/* 7) 稿件列表：AI 工作状态徽标贴右 */
.md-li__work { margin-left: auto; flex: none; }

/* 8) 插入配图弹窗（挂 body，scrim 与面板同级） */
.md-pick { position: fixed; inset: 0; z-index: 95; display: flex; align-items: center; justify-content: center; }
.md-pick__scrim { position: absolute; inset: 0; background: rgba(0, 0, 0, .42); }
.md-pick__panel {
  position: relative;
  width: min(720px, calc(100vw - 32px));
  max-height: 80vh;
  display: flex;
  flex-direction: column;
  background: var(--panel-bg-solid);
  border: 1px solid var(--panel-border);
  border-radius: 14px;
  box-shadow: 0 24px 70px rgba(0, 0, 0, .32);
  overflow: hidden;
}
.md-pick__h {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px;
  border-bottom: 1px solid var(--line);
}
.md-pick__x { border: 0; background: transparent; color: var(--muted); cursor: pointer; font-size: 14px; line-height: 1; }
.md-pick__tabs { display: flex; gap: 6px; padding: 10px 16px 0; }
.md-pick__tabs > button {
  border: 1px solid var(--line); background: transparent; color: var(--muted);
  border-radius: 999px; padding: 5px 12px; font-size: 12.5px; cursor: pointer;
}
.md-pick__tabs > button.is-on { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.md-pick__body { padding: 12px 16px; overflow: auto; }
.md-pick__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 10px; }
.md-pick__card {
  display: flex; flex-direction: column; gap: 6px; padding: 6px;
  border: 1px solid var(--line); border-radius: 10px;
  background: var(--panel-bg-solid); cursor: pointer;
}
.md-pick__card img { width: 100%; height: 84px; object-fit: cover; border-radius: 6px; background: var(--hover); }
.md-pick__card.is-on { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.md-pick__name { font-size: 11.5px; color: var(--muted); text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.md-pick__up { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.md-pick__f { display: flex; align-items: center; gap: 8px; padding: 12px 16px; border-top: 1px solid var(--line); }

/* 9) 正文区高度×2（用户第 2 项；原 340px） */
.md-ta { min-height: 680px; }

/* 10) 上传素材弹窗（素材库 v1.16.31） */
.st-up { position: fixed; inset: 0; z-index: 96; display: flex; align-items: center; justify-content: center; }
.st-up__scrim { position: absolute; inset: 0; background: rgba(0, 0, 0, .42); }
.st-up__panel {
  position: relative;
  width: min(560px, calc(100vw - 32px));
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  background: var(--panel-bg-solid);
  border: 1px solid var(--panel-border);
  border-radius: 14px;
  box-shadow: 0 24px 70px rgba(0, 0, 0, .32);
  overflow: hidden;
}
.st-up__h {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px; border-bottom: 1px solid var(--line);
}
.st-up__body { padding: 12px 16px; overflow: auto; display: flex; flex-direction: column; gap: 10px; }
.st-up__meta { line-height: 1.7; }
.st-up__f { display: flex; align-items: center; gap: 8px; padding: 12px 16px; border-top: 1px solid var(--line); }

/* ==========================================================================
   v1.16.32（2026-11-04）稿件页 / 发布页 / 素材库上传 新增样式
   全部追加在末尾：这里的规则要能覆盖上面的 .btn / .md-li / .md-imgs
   ========================================================================== */

/* 1) 稿件列表：标题行 + 形态标签 + 编号/时间 */
.md-li__hd { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.md-li__hd .md-li__t { display: inline; }
.md-li__m { display: block; margin-top: 3px; font-size: 11.5px; color: var(--muted); }
/* 形态角标（v1.16.33 第 3 项）：不再用合规标签那套「描边胶囊」，改成
   小而实的直角小角标，靠底色和字重区分；四个形态各一色。 */
.tag--kind {
  border: 0; border-radius: 4px;
  padding: 2px 6px; font-size: 10.5px; font-weight: 700;
  letter-spacing: .04em; line-height: 1.5;
  background: var(--hover); color: var(--muted);
}
.tag--kind-sticker { color: #fff; background: #B4614E; }
.tag--kind-long { color: #fff; background: #3E6B8A; }
.tag--kind-video { color: #fff; background: #6B5B9B; }
.tag--kind-image { color: #fff; background: #2E7D5B; }

/* 2) Skill 表单 / 稿件表单：两列栅格与行内组合 */
.md-form2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 14px; }
.md-form2 > .field { margin: 0; }
.md-inline { display: flex; gap: 8px; flex-wrap: wrap; }
.md-inline > .input { flex: 1 1 88px; min-width: 88px; }
.md-check--nowrap { white-space: nowrap; flex: none; }
.md-ta--desc { min-height: 130px; }
/* 标签行右侧放按钮（正文区右上角的「复制全文」） */
.md-field__row { display: flex; align-items: center; gap: 8px; }
.md-field__row > span:first-child { flex: 1; min-width: 0; }

/* 3) 排版区：插入配图单独一行靠右；工具行按序罗列 */
.md-insrow { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
.md-laybar--tools { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.btn.is-off { opacity: .5; }
.btn.is-off:hover { opacity: .62; }
.btn.is-off.btn--accent { background: var(--hover); color: var(--muted); border-color: var(--line); }

/* 4) 封面图区 */
.md-imgs--cover { grid-template-columns: repeat(auto-fill, minmax(148px, 1fr)); }
.md-cover-prompt { display: flex; gap: 8px; align-items: flex-start; margin: 10px 0 6px; }
.md-cover-prompt .input { flex: 1; }
.md-cover-n { display: flex; align-items: center; gap: 8px; }
.md-cover-n .input { width: 78px; }
/* 用户第 12 项：封面上压文字（不勾只显示说明，勾了才出输入框） */
.md-cover-text { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0 0 8px; }
.md-cover-text .input { flex: 1 1 260px; height: 32px; }

/* 稿件页底部条：「加入发布」靠右下角 + 左侧状态提示 */
.md-foot {
  display: flex; align-items: center; gap: 10px;
  margin-top: 14px; padding-top: 12px;
  border-top: 1px solid var(--line-soft);
}
.md-foot .btn { min-width: 116px; }

/* 按钮内联转圈（改写中 / 生成中这类局部忙态，不锁整页） */
.btn__spin {
  display: inline-block; width: 12px; height: 12px;
  border: 2px solid currentColor; border-right-color: transparent;
  border-radius: 50%; animation: spin .7s linear infinite;
  vertical-align: -2px; margin-right: 6px; opacity: .8;
}

/* 新建稿件：内容形态四选一（每张卡写清用途 / 物料 / 可复制项） */
.md-ctpick { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.md-ctpick__c {
  position: relative; display: flex; flex-direction: column; gap: 3px;
  padding: 11px 12px 12px; border: 1px solid var(--line); border-radius: 12px;
  background: var(--panel-soft); cursor: pointer;
  transition: border-color .15s, background .15s;
}
.md-ctpick__c:hover { border-color: var(--accent-soft); }
.md-ctpick__c.is-on { border-color: var(--accent); background: var(--accent-soft); }
.md-ctpick__c input { position: absolute; opacity: 0; pointer-events: none; }
.md-ctpick__c b { font-size: 13.5px; color: var(--text-strong); }
.md-ctpick__d { font-size: 12px; color: var(--text); }
.md-ctpick__n { font-size: 11.5px; color: var(--muted); line-height: 1.6; }
.md-ctpick__c2 { font-size: 11.5px; color: var(--accent); line-height: 1.6; }

/* 从稿件导入：可勾选列表 */
.md-impsel {
  display: flex; flex-direction: column; gap: 2px;
  max-height: 46vh; overflow: auto;
  border: 1px solid var(--line); border-radius: 10px; padding: 6px;
}
.md-impsel__r {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 8px; border-radius: 8px; cursor: pointer;
}
.md-impsel__r:hover { background: var(--hover); }
.md-impsel__t { flex: 1; min-width: 0; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 5) 选中文字的浮动格式工具条（图文模式） */
.md-fmt {
  position: absolute;
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 7px;
  border: 1px solid var(--panel-border);
  border-radius: 10px;
  background: var(--panel-bg-solid);
  box-shadow: 0 10px 28px rgba(0, 0, 0, .22);
}
.md-fmt[hidden] { display: none; }
.md-fmt__g { display: inline-flex; align-items: center; gap: 3px; }
.md-fmt__g + .md-fmt__g { padding-left: 6px; border-left: 1px solid var(--line); }
.md-fmt__b {
  min-width: 26px; height: 26px; padding: 0 6px;
  border: 1px solid transparent; border-radius: 6px;
  background: transparent; color: var(--text); cursor: pointer;
  font-size: 13px; line-height: 1;
}
.md-fmt__b:hover { background: var(--hover); border-color: var(--line); }
.md-fmt__b--txt { font-size: 11.5px; color: var(--muted); }
.md-fmt__sel {
  height: 26px; border: 1px solid var(--line); border-radius: 6px;
  background: var(--panel-bg-solid); color: var(--text); font-size: 12px; padding: 0 4px;
}
.md-fmt__c {
  width: 16px; height: 16px; border-radius: 50%; padding: 0; cursor: pointer;
  border: 1px solid rgba(0, 0, 0, .18);
  background: var(--c, #1F1F1F);
}
.md-fmt__c:hover { transform: scale(1.12); }
.md-fmt__cpick { width: 20px; height: 20px; display: inline-flex; cursor: pointer; }
.md-fmt__cpick input { width: 20px; height: 20px; padding: 0; border: 0; background: transparent; cursor: pointer; }

/* 6) 插入配图弹窗：多选序号与删除 */
.md-pick__card { position: relative; }
.md-pick__badge {
  position: absolute; top: 2px; right: 2px;
  min-width: 18px; height: 18px; padding: 0 4px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 999px; background: var(--accent); color: #fff;
  font-size: 11px; font-weight: 600; line-height: 1;
}
.md-pick__del {
  position: absolute; top: 2px; left: 2px;
  width: 18px; height: 18px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, .55); color: #fff; font-size: 10px; cursor: pointer;
}
.md-pick__del:hover { background: var(--danger); }

/* 7) 素材库上传弹窗：自定义选择按钮 + 缩略图预览列表 */
.st-up__pickrow { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.st-up__pick { cursor: pointer; }
.st-up__list { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; max-height: 244px; overflow: auto; }
.st-up__item {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 9px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--panel-soft);
}
.st-up__thumb {
  position: relative; width: 64px; height: 48px; flex: none;
  border-radius: 8px; overflow: hidden; background: #fff;
  border: 1px solid var(--line);
}
.st-up__thumb img, .st-up__thumb video { width: 100%; height: 100%; object-fit: contain; display: block; background: #fff; }
.st-up__play {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 14px; text-shadow: 0 1px 4px rgba(0, 0, 0, .6);
}
.st-up__info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.st-up__info b { font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 8) 发布页（重做）：筛选底板 + 列表 + 抽屉
   v1.16.33 第 23 项：统计条已删除，数量进 tab；第 21 项：稿件列收窄、
   操作列放宽、时间列不换行；抽屉改回通用 .drawer（见 admin.js）。 */
.md-pub2__toolbar { gap: 10px; }
.md-seg--lg { gap: 2px; padding: 4px; }
.md-seg--lg > button { height: 34px; padding: 0 18px; font-size: 13.5px; border-radius: 10px; }
.md-seg--lg > button b { font-weight: 700; margin-left: 4px; opacity: .72; }
.md-seg--lg > button.is-on b { opacity: 1; }
.md-pub2__bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.md-pub2__bar .input { height: 32px; }
.md-pub2__tbl { border: 1px solid var(--line); border-radius: 12px; overflow: hidden; background: var(--panel-bg-solid); }
.md-pub2__hd, .md-pub2__row {
  display: grid;
  grid-template-columns: 58px minmax(120px, .9fr) 66px 66px minmax(80px, .5fr) minmax(175px, 1.15fr) 140px 240px;
  gap: 8px; align-items: center;
  padding: 9px 12px;
}
.md-pub2__hd { font-size: 11.5px; color: var(--muted); background: var(--hover); border-bottom: 1px solid var(--line); }
.md-pub2__row { border-bottom: 1px solid var(--line-soft); cursor: pointer; }
.md-pub2__row:last-child { border-bottom: 0; }
.md-pub2__row:hover { background: var(--hover); }
.md-pub2__cover img, .md-pub2__cover .md-pub2__ph {
  width: 44px; height: 44px; border-radius: 8px; object-fit: cover;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); background: #fff; color: var(--muted); font-size: 11px;
}
.md-pub2__title { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.md-pub2__title b { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.md-pub2__nowrap { white-space: nowrap; }
.md-pub2__ops { display: flex; gap: 6px; justify-content: flex-end; flex-wrap: nowrap; }
.md-pub2__ops .btn { white-space: nowrap; }
.md-pubdlg .md-inline { margin-top: 2px; }

/* 抽屉内的图片缩略图墙（发布详情复用通用 .drawer，只补这一个网格） */
.md-thumbgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 8px; }
.md-thumbgrid img {
  width: 100%; height: 84px; object-fit: cover; border-radius: 8px;
  border: 1px solid var(--line); background: #fff; cursor: zoom-in;
}
.md-pubdrawer .op-reason p { max-height: none; }
.md-pubdrawer .mfoot { margin-top: 4px; }

@media (max-width: 1080px) {
  .md-pub2__hd, .md-pub2__row { grid-template-columns: 52px minmax(100px, .8fr) 58px 58px minmax(70px, .48fr) minmax(155px, 1.1fr) 132px 200px; }
  .md-seg--lg > button { padding: 0 12px; font-size: 12.5px; }
}

/* ==========================================================================
   v1.16.34 · 2026-11-04 用户 29 项批次（间距 / 即时提示 / 吸底发布栏 / 封面主图）
   ========================================================================== */

/* 1) 用户第 3 项 + 第 20 项③：按钮行与上下内容都要有间距，不再紧挨 */
.md-imgops { margin-top: 10px; margin-bottom: 12px; }
.md-imgs--cover { margin-top: 2px; }
.md-cover-text { margin: 10px 0 10px; }

/* 2) 用户第 14 项②：鼠标划过图标按钮立即出名称（原生 title 要等 ~1s） */
.md-iconbtn[data-tip] { position: relative; }
.md-iconbtn[data-tip]::after {
  content: attr(data-tip);
  position: absolute; left: 50%; bottom: calc(100% + 6px); transform: translateX(-50%);
  padding: 4px 7px; border-radius: 5px; white-space: nowrap;
  background: #1f1c18; color: #fff; font-size: 11px; line-height: 1.35;
  opacity: 0; visibility: hidden; pointer-events: none; z-index: 60;
  transition: opacity .06s linear;
}
.md-iconbtn[data-tip]:hover::after,
.md-iconbtn[data-tip]:focus-visible::after { opacity: 1; visibility: visible; }
.st-work__acts .sku-iact[data-tip] { position: relative; }

/* 3) 用户第 13 项：「加入发布」条固定在稿件页底部，不随内容滚走 */
.md-foot--fixed {
  position: sticky; bottom: 0; z-index: 12;
  margin: 18px -2px -2px; padding: 12px 14px;
  display: flex; align-items: center; gap: 10px;
  background: color-mix(in srgb, var(--panel-bg-solid, #fff) 94%, transparent);
  border-top: 1px solid var(--line);
  backdrop-filter: blur(8px);
  border-radius: 0 0 12px 12px;
}
.md-foot--fixed #md-addpub {
  height: 40px; padding: 0 26px; font-size: 14px; font-weight: 600;
  box-shadow: 0 6px 18px color-mix(in srgb, var(--accent, #B08A5A) 28%, transparent);
}
.md-foot--fixed #md-pub-hint { flex: 1; min-width: 0; }

/* 4) 用户第 20 项④：封面卡上的「设为主封面」是选中态，不是危险操作 */
.md-img__ops .md-iconbtn.is-main { color: var(--accent, #B08A5A); border-color: var(--accent, #B08A5A); background: color-mix(in srgb, var(--accent, #B08A5A) 12%, transparent); }

/* 5) 用户第 25 项：从稿件导入用统一自定义勾选 —— 🆕 v1.16.41 用户第 6 项，
   该功能已整体删除（改由发布自动归档 + 稿件/选题「加入资产库」），
   .md-importlist / .md-importlist__row / .md-importall 三条样式一并作废，不留死代码。 */

/* 6) 用户第 11 项：按钮里已经有内联转圈时，不要再叠 .is-busy 的 ::after（会两个圈） */
.btn.is-busy:has(> .btn__spin)::after,
.btn.is-busy:has(> .spinner)::after { content: none; display: none; }

/* 7) 用户第 12 项：合规单条操作行（改写 + 忽略） */
.md-hit__ops { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }

/* 8) 用户第 19 项：发布详情抽屉的蒙版盖住了详情，导致点不到。
   根因 = .drawer 的 z-index 是 50，而 .op-drawer__scrim 是 95 —— 蒙版必然在抽屉之上。
   这里给本抽屉提到 96（高于自己的蒙版 95），与方案详情抽屉同一口径。 */
.md-pubdrawer { z-index: 96; }

/* 9) 用户第 16 项：新建稿件的 AI 参考图预览 */
.md-refgrid { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.md-refgrid:empty { display: none; }

/* 9b) 🆕 v1.16.41 用户第 4 项：AI 参考图改成 4 个预设占位格。
   空格 = 虚线「点击选择图片」；选中 = 预览图 + 右上角 ✕。
   点已选图片放大查看（走 A.lightboxGallery），删掉后格子自动回到虚线态。 */
.md-refpick {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px; margin: 8px 0 6px;
}
.md-refpick__c {
  position: relative; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 6px; min-width: 0; padding: 8px;
  aspect-ratio: 1 / 1;
  border: 1.5px dashed var(--line); border-radius: 12px;
  background: var(--bg); color: var(--muted);
  font-size: 11.5px; line-height: 1.45; text-align: center;
  cursor: pointer; overflow: hidden;
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.md-refpick__c--add:hover { border-color: var(--accent); color: var(--accent); }
.md-refpick__c--add svg { width: 22px; height: 22px; }
.md-refpick__c--add i { font-style: normal; }
.md-refpick__c--add span { font-size: 10.5px; opacity: .7; }
.md-refpick__c.is-on { border-style: solid; padding: 0; background: #fff; cursor: default; }
.md-refpick__c > img { width: 100%; height: 100%; object-fit: contain; display: block; cursor: zoom-in; }
.md-refpick__x {
  position: absolute; top: 4px; right: 4px; width: 20px; height: 20px;
  border-radius: 50%; border: none; background: rgba(0,0,0,.62); color: #fff;
  font-size: 11px; line-height: 1; cursor: pointer; display: grid; place-items: center;
}
.md-refpick__x:hover { background: var(--danger); }
@media (max-width: 620px) { .md-refpick { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* 9c) 🆕 v1.16.41 用户第 6 项：稿件列表右侧的「加入资产库」图标按钮。
   外层 .md-li 由 <button> 改成 <div role="button">（button 不能嵌套 button），
   所以这里补 position:relative 给图标做定位，并把左侧内容右内边距让开。 */
.md-li { position: relative; }
.md-li__hd, .md-li__m { padding-right: 32px; }
.md-li__asset {
  position: absolute; top: 9px; right: 9px; z-index: 2;
  width: 26px; height: 26px; padding: 0; border-radius: 8px;
  border: 1px solid var(--line); background: var(--panel-bg-solid); color: var(--muted);
  display: grid; place-items: center; cursor: pointer;
  transition: color .15s ease, border-color .15s ease;
}
.md-li__asset svg { width: 15px; height: 15px; }
.md-li__asset:hover { color: var(--accent); border-color: var(--accent); }
.md-li__asset.is-on { color: var(--accent); border-color: transparent; background: transparent; cursor: default; }
.md-refgrid__i { position: relative; width: 74px; height: 74px; border-radius: 8px; overflow: hidden; border: 1px solid var(--line); }
.md-refgrid__i img { width: 100%; height: 100%; object-fit: cover; display: block; }
.md-refgrid__x {
  position: absolute; top: 2px; right: 2px; width: 18px; height: 18px; border-radius: 50%;
  border: none; background: rgba(0,0,0,.55); color: #fff; font-size: 10px; line-height: 1; cursor: pointer;
}
/* 参考图在稿件页只读展示（来自素材库 / 新建时上传） */
.md-refbar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin: 0 0 10px; }

/* 10) 用户第 6 项②：预设作品墙的视频也走瀑布流（原来固定 3 列网格，横竖混排很丑）。
   与照片墙同一套 CSS columns 做法。 */
.st-vwall { columns: 4; column-gap: 12px; display: block; }
.st-vwall .st-vcard { break-inside: avoid; margin: 0 0 12px; width: 100%; }
.st-vwall .st-card__media > img { aspect-ratio: auto; height: auto; }
@media (max-width: 1280px) { .st-vwall { columns: 3; } }
@media (max-width: 980px) { .st-vwall { columns: 2; } }
@media (max-width: 680px) { .st-vwall { columns: 1; } }

/* 11) 用户第 5 项②：上传素材的单选按钮（不用 tab） */
.st-up__radios { display: flex; gap: 18px; align-items: center; flex-wrap: wrap; padding: 4px 0 2px; }
.st-up__radios .chk { cursor: pointer; }
.chk input[type="radio"] + .chk__box { border-radius: 50%; }
.chk input[type="radio"]:checked + .chk__box::after {
  content: ""; position: absolute; inset: 3px; border-radius: 50%; background: currentColor;
}
.chk input[type="radio"] + .chk__box { position: relative; }

/* 12) 用户第 8 项：默认发布平台纵向排列（每行一个平台 + 该平台约束） */
.md-platrow {
  display: flex; align-items: baseline; gap: 8px;
  padding: 7px 10px; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--line); margin-bottom: 6px;
}
.md-platrow:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 5%, transparent); }
.md-platrow input { flex: none; }
.md-platrow__n { font-size: 13px; font-weight: 500; flex: none; min-width: 64px; }
.md-platrow__lim { font-size: 11.5px; color: var(--muted); flex: 1; min-width: 0; }

/* 13) 用户第 7 项④：稿件页的视频预览（话题下方） */
.md-vprev { border: 1px solid var(--line); border-radius: 10px; overflow: hidden; background: #000; display: flex; justify-content: center; }
.md-vprev video { display: block; width: 100%; max-height: 320px; object-fit: contain; background: #000; }

/* ============================================================================
   v1.16.35（2026-11-04）21 项报障批次 —— 全部追加在文件末尾，
   不改动上面任何既有规则（改写老规则最容易连带砸掉别处的布局）。
   ============================================================================ */

/* 1) 用户第 1 项：上传素材的单选按钮出现**两个圆**。
   根因：7636 行只隐藏了 input[type="checkbox"]，radio 的原生圆点一直露着，
   和 .chk__box 代理圆叠在一起。这里把 radio 也一起隐藏。 */
.chk input[type="radio"] {
  position: absolute; opacity: 0; width: 0; height: 0; margin: 0; pointer-events: none;
}
.chk:has(> .chk__box) { position: relative; }

/* 2) 用户第 2 项②：素材详情里的「素材简介」 */
.st-intro p { white-space: pre-wrap; }

/* 3) 用户第 3 项①②：上传弹窗 —— 单行提示词输入域 + 每条素材自带中英提示词 */
.md-ta--one { min-height: 54px; height: 54px; resize: vertical; }
.st-up__item--rich { display: block; }
.st-up__row { display: flex; align-items: center; gap: 10px; }
/* 🔴 v1.16.39 用户第 1 项：中英提示词改成**上下两行**（左右并排时弹窗只有
   560px 宽，每列 200px 出头，写两句就折成一行行碎片）；高度同时放大到 88px。 */
.st-up__prompts { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; margin: 8px 0 2px 0; }
.st-up__pf { display: block; }
.st-up__pf > span { display: block; font-size: 11.5px; color: var(--muted); margin-bottom: 4px; }
.st-up__pf textarea { width: 100%; font-size: 12.5px; height: 72px; min-height: 72px; line-height: 1.7; }
/* 一条素材的提示词要在弹窗里**默认全看见**：列表自身不再单独滚（原来
   max-height:244px 会把英文框裁在内部滚动区里），统一交给 .st-up__body。 */
.st-up__list { max-height: none; overflow: visible; }
/* 🔴 v1.16.39 用户第 5 项：新建稿件里的「AI 参考文案」原来吃 .md-ta 的
   min-height:680px，占了大半屏，标题与形态都被挤出可视区。收到 1/3 左右（210px）。 */
.md-ta--ref { min-height: 190px; height: 190px; }
@media (max-width: 720px) { .st-up__prompts { grid-template-columns: 1fr; margin-left: 0; } }

/* 4) 用户第 5 项：「加入发布」底板改圆角矩形 + 四边框 + 距底 5px，且**不随页面滚动**。
   旧实现 position:sticky，容器一到底它就停在半空中（用户截图里就是那样）。
   左右与宽度由 JS 按 #md-draft-main 的真实矩形写行内样式，这里只给兜底。 */
.md-foot--fixed {
  position: fixed; left: 24px; right: 24px; bottom: 5px; z-index: 60;
  margin: 0; padding: 12px 16px;
  background: var(--panel-bg-solid, #fff);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, .16);
  backdrop-filter: none;
}
.md-work__main { padding-bottom: 96px; }

/* 5) 用户第 6 项：帮助中心悬浮圆钮别贴着窗口右边缘（会被裁掉半个圆） */
.help-fab { right: 26px; bottom: 26px; }
body.has-mdfoot .help-fab { bottom: 92px; }

/* 6) 用户第 7 项：封面/配图的「全部存入素材库 + 打包下载」移到图片下方一行 */
.md-bulkrow { display: flex; gap: 8px; flex-wrap: wrap; margin: 12px 0 4px; }

/* 7) 用户第 8 项：Skill 配置按形态平铺（不用下拉切）+ 左侧编号标签 */
.md-skgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 12px; }
.md-skcard {
  border: 1px solid var(--line); border-radius: 12px; padding: 14px 16px;
  background: var(--panel-bg, #fff); cursor: pointer; position: relative;
  transition: border-color .16s, box-shadow .16s, transform .16s;
}
.md-skcard:hover { border-color: color-mix(in srgb, var(--accent) 55%, var(--line)); transform: translateY(-1px); }
.md-skcard.is-on { border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 22%, transparent); }
.md-skcard__hd { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.md-skcard__no {
  flex: none; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px; line-height: 1; padding: 4px 7px; border-radius: 6px;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent); font-weight: 700; letter-spacing: .5px;
}
.md-skcard__n { font-size: 14px; font-weight: 650; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.md-skcard__rows { display: grid; gap: 4px; }
.md-skcard__r { display: flex; gap: 8px; font-size: 12px; color: var(--muted); }
.md-skcard__r b { color: var(--text); font-weight: 500; min-width: 56px; flex: none; }
.md-skcard__ops { display: flex; gap: 6px; margin-top: 10px; }
.md-skgroup__t {
  font-size: 12px; font-weight: 650; color: var(--text-dim); letter-spacing: .06em;
  margin: 18px 0 8px; display: flex; align-items: center; gap: 8px;
}
.md-skgroup__t::after { content: ""; flex: 1; height: 1px; background: var(--line); }

/* 8) 用户第 17/18 项：发布详情的「数据」不再嵌套盒子，改成平铺表格式 */
.md-datarows { display: grid; gap: 6px; }
.md-datarow {
  display: grid; grid-template-columns: minmax(84px, 1.1fr) 1.4fr 1.6fr auto;
  gap: 10px; align-items: center; padding: 9px 11px;
  border: 1px solid var(--line); border-radius: 9px; font-size: 12.5px;
}
.md-datarow__pf { font-weight: 600; }
.md-datarow__url a { color: var(--accent); }
.md-datarow__st { display: flex; gap: 10px; flex-wrap: wrap; color: var(--muted); }
.md-datarow__st b { color: var(--text); font-weight: 600; }
.md-datarow__t { color: var(--muted); white-space: nowrap; font-size: 11.5px; }
@media (max-width: 900px) {
  .md-datarow { grid-template-columns: 1fr; gap: 4px; }
}

/* 9) 用户第 19 项：发布详情看图 —— 左右箭头 + X/Y 计数 */
.md-viewer { position: relative; }
.md-viewer__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 6px; }
.md-viewer__grid img { width: 100%; height: 84px; object-fit: cover; border-radius: 8px; cursor: zoom-in; display: block; }
.md-viewer__big { position: relative; display: flex; align-items: center; justify-content: center; background: #000; border-radius: 10px; overflow: hidden; }
.md-viewer__big img { max-width: 100%; max-height: 300px; object-fit: contain; display: block; }
.md-viewer__nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 30px; height: 30px; border-radius: 50%; border: none; cursor: pointer;
  background: rgba(0, 0, 0, .5); color: #fff; font-size: 16px; line-height: 1;
}
.md-viewer__nav--l { left: 8px; }
.md-viewer__nav--r { right: 8px; }
.md-viewer__idx {
  position: absolute; bottom: 8px; left: 50%; transform: translateX(-50%);
  padding: 3px 10px; border-radius: 999px; background: rgba(0, 0, 0, .55);
  color: #fff; font-size: 11.5px; letter-spacing: .5px;
}

/* 10) 用户第 18 项：标记已发布 / 补录数据的多平台区块 */
.md-pfblock { border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; margin-bottom: 8px; }
.md-pfblock__hd { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.md-pfblock__no { font-size: 11px; color: var(--accent); font-weight: 700; }
.md-pfblock__x { margin-left: auto; }
.md-pfadd { display: flex; gap: 8px; align-items: center; }

/* 11) 用户第 21 项：资产库列表更紧凑 */
.md-assetrow { display: flex; align-items: center; gap: 10px; }
.md-assetrow__m { flex: 1; min-width: 0; }

/* 12) v1.16.35 用户第 18 项：多平台区块的字段栅格（标记已发布 / 补录数据共用） */
.md-pflist { display: flex; flex-direction: column; gap: 8px; }
.md-pfblock__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 8px; }
.md-pfblock__grid--4 { grid-template-columns: repeat(4, 1fr); }
.md-pfblock__f { display: block; margin: 0; }
.md-pfblock__f > span { display: block; font-size: 11.5px; color: var(--muted); margin-bottom: 4px; }
.md-pfblock__f .input { width: 100%; }
@media (max-width: 720px) {
  .md-pfblock__grid, .md-pfblock__grid--4 { grid-template-columns: 1fr 1fr; }
}

/* 13) v1.16.35 用户第 19 项：看图器缩略图选中态 + 大图可点开原图 */
.md-viewer__grid img.is-on { outline: 2px solid var(--accent, #B08A5A); outline-offset: 1px; }
.md-viewer__big img { cursor: zoom-in; }
.md-viewer__grid { margin-top: 6px; }

/* ============================================================================
   v1.16.36（2026-11-04 夜）十五项报障批次
   ============================================================================ */

/* 1) 用户第 2 项①：上传弹窗的单选**点了没反应**（第二次修这个 bug）。
   真根因：`.chk__box::after` 是「勾」的造型（5×9、rotate(45deg) scale(0)），
   8741 行只给 radio 换成了圆点却**没把 transform 归零** —— 圆点一直 scale(0)，
   所以 checked 状态在视觉上完全看不出来。这里把 transform / 边框 / 尺寸全部复位。 */
.chk input[type="radio"]:checked + .chk__box {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 16%, transparent);
}
.chk input[type="radio"]:checked + .chk__box::after {
  content: ""; position: absolute; inset: 3px;
  width: auto; height: auto; margin: 0; border: 0; border-radius: 50%;
  background: var(--accent); transform: none;
  /* 勾选框的 ::after 带 transform .15s 过渡，切到圆点时会在中途读到 scale(0)，
     看起来像「点了没反应」。圆点是瞬时状态，不要过渡。 */
  transition: none;
}
.chk input[type="radio"]:focus-visible + .chk__box {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 28%, transparent);
}

/* 2) 用户第 2 项③：编辑素材弹窗的三个文本域默认 680px 高（.md-ta 的 min-height），
   现在统一固定 96px，超出在框内纵向滚动，不把弹窗撑成一整屏。 */
.md-ta--fix {
  min-height: 96px; height: 96px; max-height: 96px;
  overflow-y: auto; resize: none;
}

/* 3) 用户第 3 项④：工作流卡片显示全部要素（写作人格 / 排版模板 / 账号定位 / 目标读者）。
   卡片变宽一点，长文案允许换行，不再被一行省略号吃掉。 */
.md-skgrid { grid-template-columns: repeat(auto-fill, minmax(370px, 1fr)); }
.md-skcard__rows { gap: 6px; }
.md-skcard__r { align-items: flex-start; line-height: 1.6; }
.md-skcard__r b { min-width: 60px; }
.md-skcard__r span { flex: 1; min-width: 0; color: var(--text); word-break: break-word; }

/* 4) 用户第 9 项：发布列表一稿一行 —— 稿件列收窄、平台列加宽，平台名并排显示。
   （列序：封面 / 稿件 / 形态 / 状态 / 平台 / 添加 / 发布 / 操作） */
.md-pub2__hd, .md-pub2__row {
  grid-template-columns: 58px minmax(120px, .9fr) 66px 66px minmax(80px, .5fr) minmax(175px, 1.15fr) 140px 240px;
}
.md-pub2__pfs { display: flex; flex-wrap: wrap; gap: 4px 6px; align-items: center; }
.md-pub2__pf {
  display: inline-block; padding: 1px 7px; border-radius: 6px; font-size: 11.5px;
  border: 1px solid var(--line); background: var(--hover); color: var(--text-dim);
  white-space: nowrap;
}
@media (max-width: 1080px) {
  .md-pub2__hd, .md-pub2__row { grid-template-columns: 52px minmax(100px, .8fr) 58px 58px minmax(70px, .48fr) minmax(155px, 1.1fr) 132px 200px; }
}

/* 5) 用户第 8 项：发布详情的内容区拆成 标题 / 短标题 / 话题 / 描述 四段 */
.md-ctrows { display: grid; gap: 8px; margin-top: 8px; }
.md-ctrow { display: grid; grid-template-columns: 64px 1fr; gap: 10px; align-items: flex-start; }
.md-ctrow__k { font-size: 12px; color: var(--muted); line-height: 1.9; }
.md-ctrow__v { font-size: 13px; line-height: 1.9; white-space: pre-wrap; word-break: break-word; color: var(--text); }
@media (max-width: 720px) { .md-ctrow { grid-template-columns: 1fr; gap: 2px; } }

/* 6) 用户第 11 项：标记已发布弹窗里，内容链接与下面四项数据之间要留出间距 */
.md-pfblock__f + .md-pfblock__grid { margin-top: 12px; }
.md-pfblock__grid + .md-pfblock__f { margin-top: 10px; }

/* 7) 用户第 12/13 项：资产库 —— 操作按钮靠右对齐 + 左侧标题首字方块 */
.md-item > .md-assetrow { flex: 1; min-width: 0; }
.md-assetrow__ava {
  flex: none; width: 34px; height: 34px; border-radius: 9px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 14px; font-weight: 700; line-height: 1;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
}
.md-assetrow .md-item__ops { margin-left: auto; }

/* ==================== v1.16.37 ==================== */
/* 1) 用户第 4 项：选题页形态标签与标题别紧挨着（只作用于选题卡片 .md-item__t，
      稿件列表用的是 .md-li__hd，不受影响） */
.md-item__t > .tag { margin-right: 9px; vertical-align: 1px; }

/* 2) 用户第 5 项：「加入发布」条由 JS 实时写 left/width；这里保证宽度过渡平滑，
      且窗口极窄时 hint 不把按钮挤出可视区 */
.md-foot--fixed { transition: none; box-sizing: border-box; }
.md-foot--fixed #md-pub-hint { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.md-foot--fixed #md-addpub { flex: none; }

/* 3) 全盘审计：视频预览从「直塞签名 URL」改成 data-vsrc + 现签后水合 */
.md-vprev video { width: 100%; max-height: 360px; border-radius: 10px; background: #000; }
/* 🔴 v1.16.39 用户第 4 项：视频播不出来时的说明块（区分「素材已删」与「链接过期」） */
.md-vfail {
  border: 1px solid var(--line); border-radius: 10px;
  background: var(--panel-soft); padding: 12px 14px;
}
.md-vfail b { font-size: 12.5px; color: var(--danger); }
.md-vfail p { margin: 4px 0 0; font-size: 12px; color: var(--muted); line-height: 1.7; }

/* ==================== v1.16.38 提取服饰 ====================
   左「原始图片」→ 中「提取服饰」→ 右「提取结果」，与参考项目
   open-pose-costume 的上传服饰弹窗同一套信息结构（这里做成整页）。
   两栏等高用 aspect-ratio 撑开，窄屏自动堆叠（不靠 JS 量宽度）。 */
/* 🔴 v1.16.39 用户第 7 项：生图模型下拉把左侧「生图模型」挤成两行。
   根因：`.input{width:100%}` + select 的 min-width:auto（= 最宽 option 的文字宽，
   「阿里云百炼 (通义) (qwen-image-2.1-pro) · 本地」约 400px+）。
   flex 项里 min-width 优先于 max-width，所以原来的 max-width:300px 形同虚设。
   这里 width/min-width 一起放开，再用 flex-basis 钉死宽度。 */
.st-ex__model { width: 340px; min-width: 0; max-width: 340px; flex: 0 0 340px; }
/* 🔴 v1.16.39：真正显示的不是 select —— common.js 的 enhanceSelect 把它换成了
   `.csel` 自绘按钮（原 select display:none），而 `.csel{width:100%}` 只继承
   **行内**宽度。只给 select 写 max-width 等于没写，壳照样撑满 759px，
   把左边「生图模型」挤成两行。限宽必须落在壳上。
   🔴 v1.16.41 用户第 8 项：260px 仍然不够 —— 「直连（gpt-image-2-atomflow）」
   这种名字被截成「…atomflo」。加到 340px（窄屏 220px）。 */
.st-ex .sec-head > .csel { flex: 0 0 340px; width: 340px; min-width: 0; max-width: 340px; }
.st-ex__mlabel { flex: none; white-space: nowrap; }
.st-ex__cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 132px minmax(0, 1fr);
  gap: 18px;
  align-items: start;
  margin-top: 14px;
}
.st-ex__col { min-width: 0; }
.st-ex__label { font-size: 12.5px; font-weight: 600; color: var(--text); margin-bottom: 8px; }
.st-ex__drop {
  position: relative;
  display: grid; place-items: center;
  width: 100%;
  aspect-ratio: 3 / 4;
  max-height: 440px;
  padding: 0;
  border: 1.5px dashed var(--line);
  border-radius: 14px;
  background: var(--bg);
  color: var(--muted);
  cursor: pointer;
  overflow: hidden;
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.st-ex__drop:hover, .st-ex__drop.is-over {
  border-color: var(--accent);
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 6%, var(--bg));
}
.st-ex__drop--out { cursor: zoom-in; }
/* 🔴 v1.16.39 用户第 8 项：预览要**完整显示整张图**、四周留白。
   原来 img 用 width/height:100%，但容器是 display:grid + place-items:center，
   子项被按内容尺寸摆放，height:100% 拿不到确定高度 → 图按自身高度渲染再被
   overflow:hidden 裁掉脑袋。改成绝对定位铺满容器 + object-fit:contain。 */
.st-ex__drop > img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain; object-position: center;
  display: block; background: #fff;
}
/* 有图时预览框就是「看图」入口（点开查看器） */
.st-ex__drop--view { cursor: zoom-in; }
.st-ex__ph {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 22px; text-align: center; font-size: 12.5px; line-height: 1.5;
}
.st-ex__ph b { font-weight: 500; font-size: 13px; }
.st-ex__ph i { font-style: normal; font-size: 11.5px; opacity: .72; line-height: 1.6; }
/* v1.16.43 第 3 项：旧版是「居中黑胶囊 + 系统 spinner」，正好压住占位区
   的标题和说明文字。现在 busy 时整块占位隐藏（.st-ex__drop.is-busy），
   loading 自己独占中央：衣服图标做颜色/明暗循环，下面两行说明不再重叠。 */
.st-ex__busy {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: 14px 18px; border-radius: 12px;
  background: transparent; color: var(--muted); font-size: 12px;
  text-align: center; white-space: nowrap; pointer-events: none;
}
.st-ex__mid {
  display: flex; flex-direction: column; align-items: stretch; gap: 10px;
  padding-top: 108px;
}
.st-ex__run { justify-content: center; gap: 6px; white-space: nowrap; }
.st-ex__ops { display: flex; align-items: center; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.st-ex__fname {
  max-width: 46%; font-size: 11.5px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@media (max-width: 900px) {
  .st-ex__cols { grid-template-columns: minmax(0, 1fr); }
  .st-ex__mid { padding-top: 0; flex-direction: row; }
  .st-ex__drop { max-height: none; }
  .st-ex__model { width: 220px; max-width: 220px; flex: 0 0 220px; }
  .st-ex .sec-head > .csel { width: 220px; max-width: 220px; flex: 0 0 220px; }
}

/* ==================== v1.16.40 组合搭配 ====================
   左：9 个槽位（人物 + 8 个部位）+ 补充要求 + 生成按钮；
   右：结果预览 + 下载 / 存库；下方：生成记录（编号 / 组合服饰 / 结果 / 模型 / 时间）。
   槽位缩略图沿用提取服饰的「绝对定位 + contain」口径 ——
   商品主图有 3:4 也有 1:1，不 contain 就会被裁掉鞋头或包带。 */
.st-mx .sec-head { flex-wrap: wrap; row-gap: 10px; }
.st-mx__lab { flex: none; white-space: nowrap; }
/* v1.16.42 第 1 项：结果框从 400 加宽到 460，左列随之收窄 ——
   补充要求的 textarea 跟着左列走，就不会再越过上方占位区右边框。 */
.st-mx__cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 460px);
  gap: 20px;
  align-items: start;
  margin-top: 16px;
}
.st-mx__left { min-width: 0; }
.st-mx__right { min-width: 0; }
.st-mx__label { font-size: 12.5px; font-weight: 600; color: var(--text); margin-bottom: 8px; }
.st-mx__slotsHead { display: flex; align-items: baseline; gap: 10px; margin-bottom: 8px; }
.st-mx__slotsHead .st-mx__label { margin-bottom: 0; }
/* v1.16.42 第 3 项：8 个部位固定「两行 × 每行 4 个」，人物占左一列并跨两行。
   旧写法 auto-fill(96px) 在有 9 个槽位时会算出 6 列，第二行只剩 4 格、
   右边空两格 —— 占位区的视觉右边界因此比补充要求框窄一截（用户第 1 项）。 */
.st-mx__slots {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) repeat(4, minmax(0, 1fr));
  grid-template-rows: repeat(2, auto);
  gap: 10px;
}
.st-mx__slot {
  position: relative;
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 7px;
  background: var(--panel-bg-solid, var(--bg));
  transition: border-color .15s ease, box-shadow .15s ease;
}
.st-mx__slot.is-on { border-color: color-mix(in srgb, var(--accent) 55%, var(--line)); }
.st-mx__slot:hover { box-shadow: 0 2px 10px rgba(0, 0, 0, .06); }
/* 人物槽位：占第 1 列、跨两行（8 个部位按 DOM 顺序自动铺满第 2~5 列的两行）。
   图片用 object-fit:contain 居中，容器被拉高也不会把人压扁。 */
.st-mx__slot--person { grid-column: 1; grid-row: 1 / span 2; display: flex; flex-direction: column; }
.st-mx__slot--person .st-mx__thumb { flex: 1; aspect-ratio: auto; min-height: 220px; }
.st-mx__thumb {
  position: relative;
  display: grid; place-items: center;
  width: 100%;
  aspect-ratio: 3 / 4;
  padding: 0;
  border: 1.5px dashed var(--line);
  border-radius: 9px;
  background: var(--bg);
  color: var(--muted);
  cursor: pointer;
  overflow: hidden;
}
.st-mx__slot.is-on .st-mx__thumb { border-style: solid; border-color: transparent; cursor: zoom-in; }
.st-mx__thumb:hover { border-color: var(--accent); color: var(--accent); }
.st-mx__thumb > img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain; object-position: center;
  display: block; background: #fff;
}
.st-mx__add { display: flex; flex-direction: column; align-items: center; gap: 4px; font-size: 11.5px; }
.st-mx__add i { font-style: normal; }
.st-mx__cap {
  display: flex; align-items: baseline; gap: 4px;
  margin-top: 6px; font-size: 11.5px; line-height: 1.3;
  min-width: 0;
}
.st-mx__cap b { font-weight: 600; color: var(--text); flex: none; }
.st-mx__from {
  color: var(--muted); font-size: 10.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.st-mx__slot.is-on .st-mx__from { color: var(--accent); }
/* 移除按钮：只有已选时才渲染；不占常驻版面 */
.st-mx__x {
  position: absolute; top: 3px; right: 3px;
  width: 20px; height: 20px; border-radius: 50%;
  border: 1px solid var(--line); background: var(--panel-bg, #fff);
  color: var(--muted); font-size: 11px; line-height: 1;
  cursor: pointer; display: grid; place-items: center;
  opacity: 0; transition: opacity .15s ease;
}
.st-mx__slot:hover .st-mx__x { opacity: 1; }
.st-mx__x:hover { color: #fff; background: var(--danger, #d33); border-color: var(--danger, #d33); }
/* v1.16.42 第 1/5 项：补充要求与上方占位区同宽（不越过它的右边框），
   标题与上下都拉开距离 —— 原来 margin-top:16px / label margin-bottom:3px 太挤。
   🔴 <label> 默认 display:inline，垂直 margin-top 对 inline 元素**完全不生效** ——
      16px 白写了，标题一直贴着上方占位区。必须显式 display:block。 */
.st-mx__req { display: block; margin-top: 28px; max-width: 100%; box-sizing: border-box; }
.st-mx__req .field__label { margin-bottom: 10px; }
.st-mx__req textarea { min-height: 74px; max-width: 100%; box-sizing: border-box; }
.st-mx__bar { display: flex; align-items: center; gap: 10px; margin-top: 14px; flex-wrap: wrap; }
.st-mx__bar .st-warn { line-height: 1.6; }
/* v1.16.47 第 4 项：组合搭配的画面比例 / 分辨率 / 清晰度（复用生成台样式，只补间距） */
.st-mx__ratio { display: block; margin-top: 24px; }
.st-mx__ratio > span { display: block; font-size: 12.5px; font-weight: 600; color: var(--text); }
.st-mx__params { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 16px; }
.st-mx__params .st-field { flex: 1 1 160px; min-width: 0; }
.st-mx__params select:disabled { opacity: .5; cursor: not-allowed; }
/* v1.16.42 第 7 项：只在人物来自客户档案时出现 */
.st-mx__bodyopt {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 18px; padding: 10px 12px;
  border: 1px solid var(--line); border-radius: 10px;
  background: var(--panel-bg-solid, var(--bg));
}
.st-mx__bodyopt[hidden] { display: none; }
.st-mx__bodyopt .chk { cursor: pointer; }
.st-mx__bodyopt .tiny { line-height: 1.6; }

/* 生成记录 */
.st-mx__logwrap { margin-top: 26px; border-top: 1px solid var(--line); padding-top: 16px; }
.st-mx__loghead { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.st-mx__tbl { width: 100%; }
.st-mx__tbl th { white-space: nowrap; }
.st-mx__tbl td { vertical-align: middle; }
/* v1.16.42 第 6 项②：编号与生成时间两列不换行 */
.st-mx__tbl .st-mx__cell-code, .st-mx__tbl .st-mx__cell-at { white-space: nowrap; }
.st-mx__code { font-family: var(--ff-mono, ui-monospace, monospace); font-size: 12px; letter-spacing: .2px; }
.st-mx__thumbs { display: flex; flex-wrap: wrap; gap: 5px; }
.st-mx__lt {
  width: 38px; height: 38px; padding: 0;
  border: 1px solid var(--line); border-radius: 6px;
  background: #fff; overflow: hidden; cursor: zoom-in;
  display: grid; place-items: center;
}
.st-mx__lt img { width: 100%; height: 100%; object-fit: contain; display: block; }
.st-mx__lt:hover { border-color: var(--accent); }
.st-mx__lt--none { color: var(--muted); cursor: default; font-size: 11px; }
/* v1.16.47 第 5 项：缩略图下方标部位（人物 / 上装 / 下装 …） */
.st-mx__fig { display: flex; flex-direction: column; align-items: center; gap: 3px; margin: 0; }
.st-mx__figcap { font-size: 10px; line-height: 1.2; color: var(--muted); max-width: 42px; text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-mx__figcap--none { opacity: .55; }

/* 取图弹窗（商品库 / 客户档案 / 本机 / 链接） */
.st-mxp__panel { width: 880px; max-width: 94vw; max-height: 88vh; display: flex; flex-direction: column; }
/* v1.16.42 第 2 项：tab 按钮组与标题头要有横向缩进 + 上下呼吸，
   原来 padding-top:0 让按钮紧贴标题头下边框，左侧只和标题齐平。 */
.st-mxp__tabs { display: flex; gap: 6px; padding: 12px 22px 12px; flex: none; }
.st-mxp__tab {
  border: 1px solid var(--line); background: transparent; color: var(--muted);
  border-radius: 999px; padding: 5px 14px; font-size: 12.5px; cursor: pointer;
}
.st-mxp__tab.is-on { border-color: var(--accent); color: var(--accent); background: color-mix(in srgb, var(--accent) 9%, transparent); }
.st-mxp__body { overflow: auto; flex: 1; min-height: 260px; }
.st-mxp__search { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.st-mxp__search .input { flex: 1; min-width: 0; }
.st-mxp__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));
  gap: 10px;
}
.st-mxp__grid--person { grid-template-columns: repeat(auto-fill, minmax(108px, 1fr)); }
.st-mxp__card {
  display: flex; flex-direction: column; gap: 2px;
  padding: 6px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--panel-bg-solid, var(--bg));
  text-align: left; cursor: pointer; min-width: 0;
}
.st-mxp__card:hover { border-color: var(--accent); }
.st-mxp__card.is-noimg { opacity: .55; }
.st-mxp__ph {
  display: grid; place-items: center;
  width: 100%; aspect-ratio: 1 / 1;
  border-radius: 7px; overflow: hidden; background: #fff; margin-bottom: 4px;
}
.st-mxp__ph img { width: 100%; height: 100%; object-fit: contain; display: block; }
/* 🆕 v1.16.46 需求 1：组合搭配「选择人物图像」弹窗里的**客户头像**改 4:5。
   🔴 只改人物卡片（.st-mxp__card--person），商品主图 / 素材库图片维持 1:1 ——
      那两类是服装图与作品图，比例另有其道理，不能跟着客户头像一起改。
   ⚠️ .st-mxp__ph 的 img 本来就是 contain（完整显示），只需把容器比例改掉。 */
.st-mxp__card--person .st-mxp__ph { aspect-ratio: 4 / 5; }
/* 4:5 后卡片变高，网格列宽略收，避免一行放不下几张 */
.st-mxp__grid--person { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); }
.st-mxp__ph i { font-style: normal; font-size: 11px; color: var(--muted); }
.st-mxp__nm {
  font-size: 12px; color: var(--text); font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.st-mxp__sub {
  font-size: 10.5px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.st-mxp__drop {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  height: 190px; padding: 18px; text-align: center;
  border: 1.5px dashed var(--line); border-radius: 12px;
  background: var(--bg); color: var(--muted); cursor: pointer;
}
.st-mxp__drop:hover, .st-mxp__drop.is-over { border-color: var(--accent); color: var(--accent); }
.st-mxp__drop b { font-size: 13px; font-weight: 500; }
.st-mxp__drop i { font-style: normal; font-size: 11.5px; opacity: .75; line-height: 1.6; }
.st-mxp__urlorow { display: flex; gap: 10px; align-items: center; }
.st-mxp__urlorow .input { flex: 1; min-width: 0; }

@media (max-width: 1080px) {
  .st-mx__cols { grid-template-columns: minmax(0, 1fr); }
  .st-mx__slots { grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); }
}

/* ==========================================================================
   v1.16.43 · 五报障修正（选题卡片 / 即时提示 / loading / 提示条 / 回复搭配）
   ⚠️ 依项目铁律：本段追加在所有 @media 之后，靠顺序覆盖旧规则。
   ========================================================================== */

/* ① 选题卡片：编辑 / 删除固定右下角，评分与主操作留在右上 */
.md-item { align-items: stretch; }
.md-item__side {
  flex: none; align-self: stretch; min-width: 0;
  display: flex; flex-direction: column; align-items: flex-end; justify-content: space-between;
  gap: 14px;
}
.md-item__top { display: flex; align-items: flex-start; gap: 12px; }
.md-item__ops--bot { justify-content: flex-end; max-width: none; }

/* ② 稿件列表「加入资产库」图标：原生 title 要等 ~1s，改自绘气泡立即出 */
.md-li__asset[data-tip]::after {
  content: attr(data-tip);
  position: absolute; right: 0; top: calc(100% + 6px);
  padding: 4px 7px; border-radius: 5px; white-space: nowrap;
  background: #1f1c18; border: 1px solid var(--line);
  color: #fff; font-size: 11px; line-height: 1.35;
  opacity: 0; visibility: hidden; pointer-events: none; z-index: 60;
  transition: opacity .06s linear;
}
.md-li__asset[data-tip]:hover::after,
.md-li__asset[data-tip]:focus-visible::after { opacity: 1; visibility: visible; }

/* ③ loading：衣服图标颜色循环（不用系统 spinner），busy 时占位文字让位 */
.st-ex__drop.is-busy .st-ex__ph { visibility: hidden; }
.st-ex__busy b { font-weight: 500; font-size: 12.5px; color: var(--text); }
.st-ex__busy i { font-style: normal; font-size: 11px; opacity: .72; line-height: 1.6; }
.st-ex__pulse {
  width: 38px; height: 38px;
  animation: st-ex-pulse 1.35s ease-in-out infinite;
  filter: drop-shadow(0 0 6px rgba(200, 160, 90, .25));
}
@keyframes st-ex-pulse {
  0%, 100% { color: var(--muted-dim); opacity: .45; transform: scale(.95); }
  50% { color: var(--accent); opacity: 1; transform: scale(1.07); }
}
@media (prefers-reduced-motion: reduce) { .st-ex__pulse { animation-duration: 2.6s; } }

/* ④ 说明文字：小字号 + 有容器，不再孤零零一行 */
.st-note--box {
  display: block; position: relative;
  margin: 14px 0 2px; padding: 10px 14px 10px 32px;
  font-size: 11.5px; line-height: 1.8;
  color: var(--muted-dim);
  background: color-mix(in srgb, var(--accent) 5%, var(--panel-soft));
  border: 1px solid var(--line);
  border-left: 2px solid var(--accent);
  border-radius: 8px;
}
.st-note--box::before {
  content: 'ⓘ';
  position: absolute; left: 12px; top: 9px;
  color: var(--accent); font-size: 12px; line-height: 1.8;
}
.st-note--box b { color: var(--text); font-weight: 600; }

/* 生成记录标题与「提取记录」的金色竖线对齐 */
.st-mx__logtitle {
  font-size: 15.5px; color: var(--text-strong);
  padding-left: 10px; border-left: 2px solid var(--accent); line-height: 1.3;
}

/* ⑤ 回复搭配：放在编号格内，不动表头 / 不加列 */
.st-mx__restore {
  margin-top: 6px; padding: 2px 8px; font-size: 11px; line-height: 1.6;
  border: 1px solid var(--line); border-radius: 6px;
  background: transparent; color: var(--muted); cursor: pointer;
  white-space: nowrap;
}
.st-mx__restore:hover { color: var(--accent); border-color: var(--accent); }
.st-mx__restore[disabled] { opacity: .5; cursor: default; }

@media (max-width: 720px) {
  .md-item { flex-wrap: wrap; }
  .md-item__side { width: 100%; flex-direction: row; align-items: flex-end; }
}

/* ==========================================================================
   v1.16.44 · 2026-11-06 · 十六项需求（15 项开发 + 1 项可行性研究）
   ⚠️ 依项目铁律：追加在**所有 @media 之后**；覆盖既有样式时自带窄屏回落，
      否则会盖掉前面 @media 里的单列布局（v1.16.42 踩过）。
   ========================================================================== */

/* ① 顶栏「MIRA 文章同步助手插件」按钮（带 logo） */
.topbar__plug { display: inline-flex; align-items: center; gap: 6px; }
.topbar__plug img { width: 17px; height: 17px; border-radius: 4px; flex: none; object-fit: contain; }
@media (max-width: 1280px) { .topbar__plug .btn__txt { display: none; } }
@media (max-width: 640px) { .topbar__plug { padding: 0 8px; } }

/* ② 插件弹窗：下载 / 安装 / 使用 三步图文流程 */
.plug-intro { display: flex; align-items: center; gap: 14px; margin: 2px 0 18px; }
.plug-intro__logo { flex: none; border-radius: 12px; }
.plug-intro b { font-size: 14px; color: var(--text-strong, var(--text)); }
.plug-intro p { margin: 5px 0 0; font-size: 12px; line-height: 1.6; color: var(--muted); }
.plug-flow { display: flex; align-items: stretch; gap: 8px; }
.plug-step { flex: 1 1 0; min-width: 0; padding: 13px 12px 12px; border: 1px solid var(--line); border-radius: 12px; background: color-mix(in srgb, var(--accent, #B08A5A) 5%, transparent); }
.plug-step__top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 9px; }
.plug-step__n { font: 600 12px/1 var(--serif, serif); letter-spacing: .08em; color: var(--accent, #B08A5A); }
.plug-step__ico { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 10px; background: color-mix(in srgb, var(--accent, #B08A5A) 14%, transparent); color: var(--accent, #B08A5A); }
.plug-step__t { display: block; font-size: 13px; margin-bottom: 6px; }
.plug-step__d { margin: 0; font-size: 11.5px; line-height: 1.65; color: var(--muted); }
.plug-step__d code { font-size: 11px; padding: 1px 4px; border-radius: 4px; background: rgba(127, 127, 127, .16); }
/* v1.16.47 第 2 项：chrome://extensions 做成可点击（下划线 + 手型 + hover 高亮） */
.plug-step__d code.plug-extlink { color: var(--accent, #B08A5A); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; transition: background .15s ease; }
.plug-step__d code.plug-extlink:hover { background: color-mix(in srgb, var(--accent, #B08A5A) 18%, transparent); }
.plug-step__d code.plug-extlink:focus-visible { outline: 2px solid var(--accent, #B08A5A); outline-offset: 1px; }
.plug-flow__arrow { align-self: center; flex: none; color: var(--accent, #B08A5A); font-size: 18px; }
.plug-mini { display: flex; align-items: center; flex-wrap: wrap; gap: 5px; margin-top: 10px; }
.plug-mini span { font-size: 10.5px; padding: 3px 7px; border: 1px solid var(--line); border-radius: 999px; color: var(--muted); }
.plug-mini i { font-style: normal; color: var(--accent, #B08A5A); font-size: 11px; }
.plug-note { margin-top: 14px; padding: 10px 12px; border-left: 2px solid var(--accent, #B08A5A); border-radius: 8px; background: color-mix(in srgb, var(--accent, #B08A5A) 7%, transparent); font-size: 11.5px; line-height: 1.7; color: var(--muted); }
.plug-note b { color: var(--text); }
.plug-bottom { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); }
@media (max-width: 720px) {
  .plug-flow { flex-direction: column; }
  .plug-flow__arrow { transform: rotate(90deg); align-self: flex-start; margin-left: 20px; }
}

/* ③ 经营驾驶舱欢迎板块右侧「logo + MIRA 虚拟试衣间」上下结构 */
.cpt-fit { display: flex; flex-direction: column; align-items: center; gap: 5px; flex: none; padding: 6px 12px; border: 1px solid var(--line); border-radius: 12px; text-decoration: none; color: var(--text); transition: border-color .15s ease, transform .15s ease; }
.cpt-fit:hover { border-color: var(--accent); transform: translateY(-2px); }
.cpt-fit img { width: 46px; height: 46px; object-fit: contain; }
.cpt-fit span { font-size: 11px; white-space: nowrap; color: var(--muted); }

/* ④ 记录表格：删除按钮 + 生成日志缩略图 */
.st-logdel { padding: 2px 9px !important; font-size: 11px !important; height: auto !important; min-height: 0 !important; }
.st-mx__cell-at .au-t { white-space: nowrap; }
.st-mx__cell-at .st-logdel { margin-top: 5px; }
.st-gl__th { position: relative; display: inline-grid; place-items: center; width: 46px; height: 46px; padding: 0; border: 1px solid var(--line); border-radius: 8px; background: var(--bg); overflow: hidden; cursor: zoom-in; vertical-align: middle; }
.st-gl__th img { width: 100%; height: 100%; object-fit: cover; display: block; }
.st-gl__th i { position: absolute; right: 2px; bottom: 2px; min-width: 15px; padding: 0 3px; border-radius: 6px; background: rgba(0, 0, 0, .72); color: #fff; font-size: 10px; font-style: normal; line-height: 15px; text-align: center; }
.st-gl__th:hover { border-color: var(--accent); }
.st-gl__th--none { border-style: dashed; color: var(--muted); cursor: default; }
.st-gl__th--video { color: var(--accent); }
.tbl--genlog td { vertical-align: middle; }

/* ⑤ 灯箱底部两侧：保存到素材库 / 下载（缩放条居中不动） */
.st-lb__tool { position: absolute; bottom: 12px; z-index: 3; padding: 0 14px; height: 32px; border: 1px solid rgba(255, 255, 255, .22); border-radius: 999px; background: rgba(22, 20, 18, .7); color: #fff; font-size: 11.5px; cursor: pointer; backdrop-filter: blur(6px); }
.st-lb__tool:hover { border-color: var(--accent, #B08A5A); color: var(--accent, #B08A5A); }
.st-lb__tool.is-busy { opacity: .6; pointer-events: none; }
.st-lb__tool--save { left: 14px; }
.st-lb__tool--dl { right: 14px; }
.st-lb.has-tools .st-zoom__hint { display: none; }
@media (max-width: 720px) { .st-lb__tool { padding: 0 9px; font-size: 10.5px; } }

/* ⑥ 组合搭配槽位删除按钮：SVG 几何居中、常驻可见、更醒目 */
.st-mx__x { width: 24px; height: 24px; top: 6px; right: 6px; opacity: 1; line-height: 0; padding: 0; display: flex; align-items: center; justify-content: center; background: rgba(18, 16, 14, .82); border: 1px solid rgba(255, 255, 255, .35); color: #fff; box-shadow: 0 2px 8px rgba(0, 0, 0, .35); }
.st-mx__x svg { display: block; flex: none; }
.st-mx__x:hover { background: var(--danger, #d33); border-color: var(--danger, #d33); color: #fff; }

/* ⑦ 组合搭配：生成结果框拉到与左侧人物/部位区域等高 */
.st-mx__cols { align-items: stretch; }
.st-mx__right { display: flex; flex-direction: column; }
.st-mx__right > .st-mx__label { flex: none; }
.st-mx__right > .st-ex__drop--out { flex: 1 1 auto; aspect-ratio: auto; max-height: none; min-height: 340px; }
.st-mx__right > .st-ex__ops, .st-mx__right > #st-mx-state { flex: none; }
@media (max-width: 1080px) {
  .st-mx__cols { grid-template-columns: minmax(0, 1fr); }
  .st-mx__right > .st-ex__drop--out { min-height: 360px; }
}

/* ⑧ 稿件底部：四形态创作流程 stepper + 精简说明靠按钮 */
.md-foot--fixed { align-items: center; gap: 14px; }
.md-flow { flex: 1 1 auto; min-width: 0; max-width: calc(100% - 390px); }
.md-flow__h { font-size: 10.5px; letter-spacing: .06em; color: var(--accent, #B08A5A); margin-bottom: 5px; }
.md-flow__steps { display: flex; align-items: center; gap: 3px; overflow-x: auto; scrollbar-width: thin; padding-bottom: 2px; }
.md-flow__s { display: inline-flex; align-items: center; gap: 4px; flex: none; }
.md-flow__s i { display: grid; place-items: center; width: 16px; height: 16px; border-radius: 50%; background: color-mix(in srgb, var(--accent, #B08A5A) 18%, transparent); color: var(--accent, #B08A5A); font-size: 9.5px; font-style: normal; }
.md-flow__s b { font-size: 10.5px; font-weight: 500; color: var(--muted); white-space: nowrap; }
.md-flow__s.is-last i { background: var(--accent, #B08A5A); color: #fff; }
.md-flow__s.is-last b { color: var(--accent, #B08A5A); }
.md-flow__arrow { flex: none; color: var(--muted-dim, var(--muted)); font-size: 13px; opacity: .6; }
.md-foot--fixed #md-pub-hint.md-foot__hint { flex: none; max-width: 230px; text-align: right; }
@media (max-width: 1100px) {
  .md-flow { max-width: calc(100% - 250px); }
  .md-foot--fixed #md-pub-hint.md-foot__hint { display: none; }
}

/* ⑨ 角色权限树：菜单查看权 / 操作权两类颗粒度图例 */
.pt-legend { display: flex; flex-wrap: wrap; gap: 6px 18px; margin: 4px 0 10px; font-size: 11.5px; color: var(--muted); }
.pt-legend span { display: inline-flex; align-items: center; gap: 6px; }
.pt-legend b { color: var(--text); font-weight: 600; }
.pt-legend__k { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.pt-legend__k--menu { background: var(--accent, #B08A5A); }
.pt-legend__k--act { background: transparent; border: 2px solid var(--muted); }

/* ⑩ 穿搭推荐方案标题上的「生成组合穿搭」 */
.ai-outfit__mix { flex: none; }

/* ==========================================================================
   v1.16.45 追加样式：放在所有旧 @media 之后，每条自带窄屏回落
   ========================================================================== */

/* ① 顶栏插件按钮：16×16 原生图标 1:1 显示（高分屏由 srcset 换 48×48） */
.topbar__plug img { image-rendering: -webkit-optimize-contrast; }

/* ② 插件弹窗：功能 / 须知两栏 + 底部操作栏里的安装包说明 */
.plug-about { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin: 0 0 16px; }
.plug-about__card { padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px; background: color-mix(in srgb, var(--accent, #B08A5A) 4%, transparent); }
.plug-about__card--warn { border-color: color-mix(in srgb, var(--accent, #B08A5A) 34%, var(--line)); background: color-mix(in srgb, var(--accent, #B08A5A) 8%, transparent); }
.plug-about h4 { display: flex; align-items: center; gap: 7px; margin: 0 0 8px; font-size: 12.5px; color: var(--text); }
.plug-about__ico { display: grid; place-items: center; width: 20px; height: 20px; border-radius: 6px; flex: none; font-size: 12px; color: var(--accent, #B08A5A); background: color-mix(in srgb, var(--accent, #B08A5A) 16%, transparent); }
.plug-about ul { margin: 0; padding-left: 16px; }
.plug-about li { margin-bottom: 3px; font-size: 11.5px; line-height: 1.7; color: var(--muted); }
.plug-about li:last-child { margin-bottom: 0; }
.plug-about li b { color: var(--text); }
.plug-foot { align-items: center; }
.plug-foot__file { margin-right: auto; text-align: left; line-height: 1.5; }
.plug-foot__file code { font-size: 11px; padding: 1px 5px; border-radius: 4px; background: rgba(127, 127, 127, .16); color: var(--text); }
.plug-bottom { display: none; }
@media (max-width: 720px) {
  .plug-about { grid-template-columns: minmax(0, 1fr); }
  .plug-foot { flex-wrap: wrap; }
  .plug-foot__file { width: 100%; margin-bottom: 6px; }
}

/* ③ 驾驶舱欢迎板块：同步助手入口与「MIRA 虚拟试衣间」同款、等高 */
.cpt-fit--plug { appearance: none; background: transparent; font: inherit; line-height: 1.2; cursor: pointer; min-height: 84px; justify-content: center; }
.cpt-fit--plug:hover { border-color: var(--accent); transform: translateY(-2px); }
.cpt-fit--plug img { border-radius: 8px; }

/* ④ 灯箱保存 / 下载：
   🔴 根因：.st-lb__box 是 pointer-events:none，按钮没补 auto → 点击穿透到
      scrim 直接 closeLb()，看起来就是「一点就关、什么都没做」。
   位置从贴屏幕两边改到图片下方两侧（以中心为基准 ±340px，窄屏回落贴边）。 */
.st-lb__tool { pointer-events: auto; }
.st-lb__tool--save { left: max(14px, calc(50% - 340px)); }
.st-lb__tool--dl { right: max(14px, calc(50% - 340px)); }

/* ⑤ 稿件底板提示：完整显示，不再 nowrap + ellipsis 截断。
   🔴 早前 v1.16.44 的窄屏规则里还有 `display:none`，只改 white-space 不够 ——
      ≤1100px 时整句话仍会被隐藏（比省略号更糟）。这里显式把 display 抢回来。 */
.md-foot--fixed #md-pub-hint.md-foot__hint {
  display: inline; flex: 0 1 auto; max-width: 330px; text-align: right;
  white-space: normal; overflow: visible; text-overflow: clip; line-height: 1.35;
}
@media (max-width: 1100px) {
  .md-foot--fixed #md-pub-hint.md-foot__hint { display: inline; max-width: 180px; }
}

/* ⑥ 稿件创作流程：第 5 步之后的分支（共用「加入发布登记」端点） */
.md-flow__branch { display: flex; align-items: center; gap: 5px; margin-top: 3px; overflow-x: auto; scrollbar-width: thin; font-size: 10px; color: var(--muted-dim, var(--muted)); white-space: nowrap; }
.md-flow__bl { flex: none; color: var(--accent, #B08A5A); font-weight: 600; }
.md-flow__branch b { color: var(--text); font-weight: 500; }
.md-flow__branch em { font-style: normal; opacity: .6; }
@media (max-width: 1100px) {
  .md-flow__branch { max-width: calc(100% - 200px); }
}

/* ⑦ v1.16.45 第 13 项：入库 / 出库「二级类型」下拉。
   🔴 不新增 .inv-grid 的 .field —— 那里是写死的 6 列网格，多一格会挤坏
      仓库 / 经手人 / 备注的跨度。挂在「单据类型」同一个 .field 内第二行即可。 */
.inv-subtype { margin-top: 9px; }
.inv-subtype__lb { margin-bottom: 5px; font-size: 11.5px; color: var(--text); }
.inv-subtype__lb .tiny { font-weight: 400; }
.inv-doc-modal #inv-f-subtype { width: 100%; min-width: 0; }
@media (max-width: 720px) {
  .inv-subtype__lb .tiny { display: none; }
}

/* ⑧ v1.16.45 第 9 项：穿搭方案「成交」弹框 / 效果图缩略图 / 详情扩展块 */
.op-deal__row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; padding: 7px 0; border-bottom: 1px dashed var(--line); font-size: 12px; }
.op-deal__row > span { color: var(--muted); flex: none; }
.op-deal__row > b { color: var(--text); font-weight: 600; text-align: right; }
.op-deal__row:last-of-type > b { color: var(--accent, #B08A5A); font-size: 15px; }
.op-mixthumb { padding: 0; border: 1px solid var(--line); border-radius: 6px; background: transparent; cursor: zoom-in; overflow: hidden; line-height: 0; }
.op-mixthumb img { display: block; object-fit: cover; }
.op-mixthumb:hover { border-color: var(--accent, #B08A5A); }
.opd__ext { margin-top: 14px; padding: 12px; border: 1px solid var(--line); border-radius: 10px; background: color-mix(in srgb, var(--accent, #B08A5A) 4%, transparent); }
.opd__ext-h { margin-bottom: 9px; font-size: 12px; font-weight: 600; color: var(--text); }
.opd__mix { display: block; max-width: 100%; max-height: 320px; margin: 0 auto; border-radius: 8px; cursor: zoom-in; object-fit: contain; }
@media (max-width: 720px) {
  .op-mixthumb img { width: 34px; height: 42px; }
}

/* ══════════════════════════════════════════════════════════
   v1.16.46 追加样式
   ⚠️ 必须追加在所有 @media 之后（项目铁律）。
   ══════════════════════════════════════════════════════════ */

/* 🆕 需求 2：穿搭方案列表「客户」列 —— 姓名左侧显示 4:5 客户头像 */
.op-cust { display: flex; align-items: center; gap: 8px; min-width: 0; }
.op-cust .pav { flex: none; }
.op-cust__nm {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* 🆕 需求 3：阳历生日选择器（后台）——
   与 H5 端（style.css 的 .fdp）同一套视觉语言：
   输入框可点 + 右侧显示推导出的年龄。 */
.date-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.date-input { cursor: pointer; font-variant-numeric: tabular-nums; }
.date-row__age {
  font-size: 11.5px; color: var(--muted);
  background: var(--hover); border-radius: 999px; padding: 2px 9px; white-space: nowrap;
}
@media (max-width: 720px) {
  .op-cust .pav { width: 38px; }
}

/* ══════════════════════════════════════════════════════════
   v1.16.47 追加样式
   ⚠️ 必须追加在所有 @media 之后（项目铁律）。
   ══════════════════════════════════════════════════════════ */

/* 🆕 第 11 项③：新建单据的头部五项（单据类型 / 二级类型 / 仓库 / 经手人 / 备注）
   要**同一行**放得下。
   🔴 旧布局是 6 等分网格，且二级类型挂在「单据类型」格子内的第二行 ——
      入库 / 出库时那一格变成两行高，整行被撑开，其余四项也被挤窄。
   改法：
     ① 二级类型从「类型格内第二行」提为**独立格子**（inventory.js 已挪出）；
     ② 网格改 12 等分，按需分配：类型 3 / 二级类型 2 / 仓库 2 / 经手人 2 / 备注 3；
     ③ 单据类型下拉相对旧版（6 格中的 2 格 = 33%）收窄到 25%（≈ -1/3），
        二级类型只要 2/12（≈ 16.7%，相对旧版整行宽度的一半还少）。
   ⚠️ 盘点 / 调整 / 调拨没有二级类型格 —— 此时让类型格自动占 3 格，
      其余照旧，不会留下空洞（网格是 auto-flow，不需要额外规则）。 */
.inv-doc-modal .inv-grid {
  grid-template-columns: repeat(12, minmax(0, 1fr));
}
/* 🆕 v1.16.48 第 4 项：单据类型下拉框加宽，让「入库（增加库存）」这类文案完整显示。
   🔴 v1.16.47 把类型格压到 3/12（25%），实测**放不下**（option 文案带括号简介，
      一截就变成「入库（增加…」），而备注右侧还空着一大块 —— 空间分配失衡。
   改法：类型 3→4 格、二级类型 2→2、仓库 2→2、经手人 2→2、备注 3→2。
   合计仍 12，五项仍同一行不换行；备注是自由文本，2 格完全够用。 */
.inv-doc-modal .inv-grid > .inv-f-kind-cell { grid-column: span 4; min-width: 0; }
.inv-doc-modal .inv-grid > .inv-f-subtype-cell { grid-column: span 2; min-width: 0; }
/* 仓库 / 经手人：不显式指定 span，靠默认 1 格会太窄 —— 统一给 2 格。
   ⚠️ 用 :not() 排除上面三个已显式定位的格子，避免规则互相打架。 */
.inv-doc-modal .inv-grid > .field:not(.inv-f-kind-cell):not(.inv-f-subtype-cell):not(.inv-f-remark-cell) {
  grid-column: span 2; min-width: 0;
}
/* 备注：2 格（12 - 4 - 2 - 2 - 2 = 2）；没有二级类型时变成 4 格，也放得下 */
.inv-doc-modal .inv-grid > .inv-f-remark-cell { grid-column: span 2; min-width: 0; }
.inv-doc-modal #inv-f-kind,
.inv-doc-modal #inv-f-subtype,
.inv-doc-modal #inv-f-wh,
.inv-doc-modal #inv-f-wh2 { min-width: 0; }
/* 二级类型不再需要「第二行」的上边距 */
.inv-doc-modal .inv-subtype { margin-top: 0; }
/* 窄屏：12 格太挤，退回两行（类型 / 二级类型一行，其余一行） */
@media (max-width: 900px) {
  .inv-doc-modal .inv-grid > .inv-f-kind-cell { grid-column: span 6; }
  .inv-doc-modal .inv-grid > .inv-f-subtype-cell { grid-column: span 6; }
  .inv-doc-modal .inv-grid > .field:not(.inv-f-kind-cell):not(.inv-f-subtype-cell):not(.inv-f-remark-cell) { grid-column: span 6; }
  .inv-doc-modal .inv-grid > .inv-f-remark-cell { grid-column: span 12; }
}

/* 🆕 第 10 项①：明细行 —— 规格与行备注收窄，把宽度让给「商品」下拉，
   让商品名称尽量完整显示。
   🔴 旧列宽 1.35fr / 1.1fr / 92px / 1fr / 34px 里，商品那一格还被
      「搜索框 128px + 下拉」切成两半 → 商品名几乎只能看到 3 个字。
   改：搜索框收到 96px、规格列降到 0.7fr、备注降到 0.65fr，商品列升到 1.9fr。
   🆕 v1.16.48 第 5 项①：数量列 84→104px（要放「可出库 N 件」小字），
      规格列 0.7→0.85fr（规格格里不再塞 avail 文字，下拉框可以正常伸展）。
   ⚠️ align-items 从 center 改 start —— 各行组件**顶部对齐**，
      下方多出来的「可出库」小字不会把别的格子的输入框挤歪。 */
.inv-line {
  grid-template-columns: minmax(0, 1.9fr) minmax(0, 0.85fr) 104px minmax(0, 0.65fr) 34px;
  align-items: start;
}
.inv-line__skuq { flex: 0 0 96px; }

/* 🆕 第 11 项①：规格格（v1.16.48 起本格只放下拉框） */
.inv-line__v-cell { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.inv-line__v-cell .inv-line__v { width: 100%; }
.inv-line__v:disabled { cursor: not-allowed; opacity: .65; }

/* 🆕 v1.16.48 第 5 项①：数量格 —— 输入框在上，「可出库 N 件」在其正下方。 */
.inv-line__q-cell { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.inv-line__q-cell .inv-line__q { width: 100%; }

/* 🆕 第 11 项②：数量下方的「可出库 N 件」提示 */
.inv-line__avail {
  font-size: 10.5px; line-height: 1.3; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.inv-line__avail.is-none { opacity: .6; }
.inv-line__avail.is-over { color: var(--danger, #C0453B); font-weight: 600; }
@media (max-width: 720px) {
  .inv-line__avail { white-space: normal; }
}

/* 🆕 第 13 项（第二处）：生成台改「左输入 / 右结果」两栏。
   🔴 右栏宽度沿用组合搭配的 460px 口径（同一套视觉语言）；窄屏（≤1080px）
      退回单栏，结果区落在输入区下方。
   ⚠️ 左栏必须 min-width:0 —— 否则里面的 textarea / 下拉会按内容宽度撑破网格。 */
/* 🆕 v1.16.48 第 7 项：生成结果虚线框「整体上移 + 宽度和高度都增加」。
   🔴 v1.16.47 的三个毛病（截图实测）：
      ① 右栏固定 460px 窄，结果框显得又窄又小；
      ② .st-gen__cols 用 align-items:start → 两栏各自按内容高度，
         右栏的 flex:1 无处可撑，虚线框只有 340px 高，**下方留一大片空白**；
      ③ 「生成结果」标签与虚线框之间还隔着一段。
   改法：
      · 右栏 460 → 560px；
      · align-items 改 stretch → 右栏与左栏等高，虚线框 flex:1 真正撑满
        （视觉上就是「上移 + 增高」，不再留空）；
      · min-height 340 → 420px（窄屏单栏时的兜底高度也加大）；
      · 标签与框的间距压到 6px。 */
.st-gen__cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 560px);
  gap: 20px;
  align-items: stretch;
  margin-top: 14px;
}
.st-gen__left { min-width: 0; }
.st-gen__left .st-form { margin-top: 0 !important; }
.st-gen__right { min-width: 0; display: flex; flex-direction: column; }
.st-gen__right > .st-mx__label { flex: none; margin-bottom: 6px; }
/* 结果框撑满右栏高度，和组合搭配的「结果框与输入区等高」同一手感 */
.st-gen__right > .st-ex__drop--out { flex: 1 1 auto; aspect-ratio: auto; max-height: none; min-height: 420px; }
.st-gen__right > .st-ex__ops, .st-gen__right > #st-gn-out-note { flex: none; }
/* 结果区里的 <video> 与 <img> 同口径：铺满 + contain + 白底 */
.st-gen__right .st-ex__drop > video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain; background: #000;
}
@media (max-width: 1080px) {
  .st-gen__cols { grid-template-columns: minmax(0, 1fr); }
  .st-gen__right > .st-ex__drop--out { min-height: 420px; }
}

/* 🆕 v1.16.48 第 2 项：操作按钮固定两行（3 + 3）。
   🔴 原来用 .ai-row__acts + flex-wrap，六个按钮宽度不一 → 挤成三行。
      行数改由结构（两个 .op-acts__row）保证，不再依赖列宽碰运气。 */
.op-acts { display: flex; flex-direction: column; gap: 5px; align-items: flex-start; }
.op-acts__row { display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; }
.op-acts__row .btn { white-space: nowrap; }

/* 🆕 第 6 项①：方案列 —— 名称在上（主体），编号在下（小字暗色，不突出）
   🔴 v1.16.48 第 2 项：编号**不要底纹边框**，直接显示在方案名称下方。
      罪魁是通用类 .ai-code（border: 1px dashed + background: var(--hover)）——
      那是给「代码块 / 独立引用」用的框体样式，套在编号上就成了突兀的虚线框。
      这里既不用 ai-code 类，也显式把继承来的框体属性清零，双保险。 */
.op-plan { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.op-plan__nm {
  font-weight: 600; color: var(--text); font-size: 12.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.op-plan__no {
  display: block; padding: 0; margin: 0;
  border: 0; background: none;
  font-family: var(--mono); font-size: 10.5px; line-height: 1.35;
  color: var(--muted); opacity: .75; white-space: nowrap;
}

/* 🆕 第 6 项②：客户列 —— 上「客户名 · 顾问」，下「门店」，均小字暗色 */
.op-cust__info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.op-cust__nm { font-size: 12.5px; color: var(--text); }
.op-cust__adv { font-size: 11px; color: var(--muted); font-weight: 400; }
.op-cust__store { font-size: 10.5px; color: var(--muted); opacity: .8; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 🆕 第 6 项③：生成模型允许换行，长名称不被截断 */
.op-model { white-space: normal; word-break: break-word; line-height: 1.5; }

/* 🆕 v1.16.48 第 3 项：v1.16.47 的 n 形流程图样式（↑ 分叉 / ↓ 汇合 / 三行网格）
   已被用户否掉（渲染完全错乱，比旧版更差）→ **整段删除**，回退 v1.16.46 的两行画法。
   下面 .md-flow__branch / .md-flow__bl 是 v1.16.46 的原有样式，一直都在，未被删过。 */

/* ══════════════════════════════════════════════════════════════════════════
   v1.16.50（2026-11-07）新增样式 —— 必须追加在所有 @media 之后（项目铁律）
   ① 灯箱 toast 层级（已就地改 .toast z-index: 9999）
   ② 库存单据：头部栅格真正生效 + 明细行控件等高
   ③ 生成日志：视频首帧预览 + 「查看作品」灰色锁定态
   ④ 生成台：loading 图标按图片 / 视频切换
   ══════════════════════════════════════════════════════════════════════════ */

/* ---- ② 库存单据（需求 3） ----
   🔴 旧 :has(#inv-f-kind) 规则已在 v1.16.20 段废止，这里再显式声明一次，
      确保「单据类型 4 格 / 备注 2 格」这条口径不会因为后续插入样式被反超。
      五项 span 4+2+2+2+2 = 12，整行铺满 → 备注右边框与明细行删除按钮
      右边框落在同一条垂直线上（实测均 x=1179 / 弹窗宽 960）。 */
.inv-doc-modal .inv-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }
.inv-doc-modal .inv-grid > .inv-f-kind-cell { grid-column: span 4; min-width: 0; }
.inv-doc-modal .inv-grid > .inv-f-subtype-cell { grid-column: span 2; min-width: 0; }
.inv-doc-modal .inv-grid > .field:not(.inv-f-kind-cell):not(.inv-f-subtype-cell):not(.inv-f-remark-cell) { grid-column: span 2; min-width: 0; }
.inv-doc-modal .inv-grid > .inv-f-remark-cell { grid-column: span 2; min-width: 0; }
.inv-doc-modal .inv-grid > .field > .input { width: 100%; min-width: 0; }
/* 🔴 需求 3②：明细行里 <select> 的默认高度比 <input> 矮一截
   （select 的 box-sizing / line-height 与 input 不同，截图实测差 2~3px）。
   统一给整行控件写死等高 39px + border-box，五个格子顶部与底部都齐平。 */
.inv-doc-modal .inv-line > .input,
.inv-doc-modal .inv-line .inv-line__sku-cell > .input,
.inv-doc-modal .inv-line .inv-line__v-cell > .input,
.inv-doc-modal .inv-line .inv-line__q-cell > .inv-line__q {
  height: 39px; box-sizing: border-box;
}

/* ---- ③ 生成日志：视频结果显示首帧（需求 5①） ----
   黑色方块换成 <video preload="metadata">，浏览器直接渲染首帧；
   三角形播放图标作为绝对定位覆盖层保留，视觉与旧占位一致。 */
.st-gl__th--video { background: #000; }
.st-gl__th--video .st-gl__first {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block; pointer-events: none;
}
.st-gl__th--video .st-gl__play {
  position: absolute; inset: 0; display: grid; place-items: center;
  color: #fff; pointer-events: none;
  background: rgba(0, 0, 0, .28);
}
.st-gl__th--video .st-gl__play svg { filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .7)); }
.st-gl__th--video img.st-gl__first { object-fit: cover; }
/* 「查看作品」未保存到素材库时灰色、可点击但只给提示（不能真 disabled，
   否则点不到、用户不知道为什么） */
.btn.is-locked { opacity: .42; filter: grayscale(.65); cursor: not-allowed; }
.btn.is-locked:hover { border-color: var(--panel-border); }

/* ---- ④ 生成台：loading 图标按类型切换（需求 4） ---- */
.st-ex__busy .st-ex__ico--vid { display: none; color: var(--accent); }
.st-ex__busy[data-mode="video"] .st-ex__ico--img { display: none; }
.st-ex__busy[data-mode="video"] .st-ex__ico--vid { display: block; }

/* ---- ⑥ 穿搭方案：状态动作按钮两行排布（需求 6） ----
   按钮个数随状态变化（4~6 个），沿用 v1.16.48 的 .op-acts / .op-acts__row
   两行结构；这里只补「删除」的危险态和整组左对齐。 */
.op-acts__row .btn--danger { white-space: nowrap; }

/* ---- ⑦ 选人弹窗：越权客户隐藏后的说明条（需求 7） ---- */
.st-mxp__scope { margin: 0 0 8px; padding: 6px 10px; border: 1px dashed var(--panel-border); border-radius: 8px; }

/* ---- ⑥ 方案编辑弹窗（v1.16.50 第 6 项） ---- */
.op-edit__row {
  display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1.1fr) 96px 34px;
  gap: 6px; align-items: center; margin-bottom: 6px;
}
.op-edit__row .input { min-width: 0; }
.op-edit__acts { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding-top: 10px; border-top: 1px solid var(--line); }
@media (max-width: 700px) {
  .op-edit__row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 34px; }
  .op-edit__row [data-oif="price"] { grid-column: 1 / 3; }
}

/* 🔴🔴 需求 3② 真因（实测）：项目用 common.js 的 enhanceSelect 把原生 <select>
   包成 .csel 自绘下拉，`.csel > select { display:none !important }` ——
   用户眼睛看到的是 .csel__btn（min-height:38px / radius 10px / padding 8px 12px），
   而同行 .input 是 39px / --radius-sm / padding 10px 13px，所以「下拉小了一点」。
   只改隐藏的原生 select 完全无效，必须对齐**可见的 .csel__btn**。
   另：select 被包进 .csel 后，原先写在 select 上的 flex:1 也失效了，
   商品下拉会失去剩余宽度 —— 这里把 flex 补回外壳。 */
.inv-doc-modal .inv-grid > .field > .csel { width: 100%; min-width: 0; }
.inv-doc-modal .inv-line .csel { display: block; width: 100%; min-width: 0; }
.inv-doc-modal .inv-line__sku-cell > .csel { flex: 1 1 auto; }
.inv-doc-modal .inv-grid > .field > .csel > .csel__btn,
.inv-doc-modal .inv-line .csel__btn {
  height: 39px; min-height: 39px; box-sizing: border-box;
  padding: 8px 13px; border-radius: var(--radius-sm);
  border-color: var(--panel-border);
  background: color-mix(in srgb, var(--panel-bg-solid) 60%, transparent);
  color: var(--text); font-size: 13px;
}

/* ==================== v1.16.51 ==================== */
/* ① 统计卡窄屏对齐「库存台账」：2×2 网格、数字与文字一律横排。
   🔴 竖排真因不是 writing-mode，是 .stat--ring 不换行的 flex 里
      .stat__dial 硬占 62px + gap 14px，把 .stat__body 压到 1 个字宽，
      中文逐字换行看起来就像「竖着写」。所以必须同时做三件事：
      ① 固定 2 列 ② 缩小环形 ③ 文字 white-space:nowrap。 */
@media (max-width: 720px) {
  .statgrid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; gap: 8px; }
  .stat--ring { gap: 9px; padding: 11px 10px; align-items: center; }
  .stat__dial { width: 46px; height: 46px; flex: 0 0 46px; }
  .stat__dial-n { font-size: 12px; }
  .stat__body { min-width: 0; overflow: hidden; }
  .stat__k, .stat__v, .stat__u { white-space: nowrap; }
  .stat__k { font-size: 10px; letter-spacing: 0; }
  .stat__v { font-size: 21px; line-height: 1.15; }
  .stat__note { font-size: 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .stat__model { overflow: hidden; text-overflow: ellipsis; }
  .stat--model { min-width: 0; }
}
@media (max-width: 420px) {
  .statgrid { gap: 6px; }
  .stat--ring { gap: 6px; padding: 10px 8px; }
  .stat__dial { width: 40px; height: 40px; flex: 0 0 40px; }
  .stat__v { font-size: 19px; }
  .stat__k { font-size: 9.5px; }
}

/* ② 全站移动端兜底：把「窄屏被压成竖排 / 挤成一条线」的高风险组件统一放开。
   只挑 exploring 出来确认无断点的容器，不用通配 * 以免破坏有意不换行的工具栏。 */
@media (max-width: 720px) {
  .content { padding-left: 12px; padding-right: 12px; }
  .card { padding: 14px 12px; }
  .subtabs { flex-wrap: wrap; gap: 4px; }
  .subtab { flex: 0 0 auto; white-space: nowrap; padding: 8px 10px; font-size: 13px; }
  .sec-head { flex-wrap: wrap; row-gap: 8px; }
  .sec-head__t { flex: 0 0 auto; white-space: nowrap; }
  .st-ex .sec-head { flex-wrap: wrap; row-gap: 10px; }
  .st-ex .sec-head > .csel, .st-ex__model { flex: 1 1 160px; width: auto; min-width: 0; }
  .st-ex__mlabel { white-space: nowrap; }
  .st-ex__cols { grid-template-columns: 1fr; }
  .st-ex__mid { padding-top: 0; }
  .cfdp__week, .cfdp__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .covdiff__row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .mgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ai-weight { grid-template-columns: 56px minmax(0, 1fr) 52px 20px; }
  .sf-row { grid-template-columns: minmax(0, 1fr) auto; }
  .scard__head, .ms-card__row, .st-work__acts, .md-img__ops,
  .md-pub2__ops, .op-acts__row, .ai-outfit__acts, .ai-pick__tabs { flex-wrap: wrap; }
  .st-params, .md-refpick, .md-pfblock__grid--4, .st-mx__slots { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ai-pick__tab { white-space: nowrap; }
  .btn { white-space: nowrap; }
}
@media (max-width: 420px) {
  .subtab { padding: 7px 8px; font-size: 12px; }
  .card { padding: 12px 10px; }
  .st-ex .sec-head > .csel, .st-ex__model { flex: 1 1 100%; }
}

/* ③ 通用分页条（生成日志 / 提取记录 / 组合记录共用） */
.st-pager { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding: 10px 2px 2px; flex-wrap: wrap; }
.st-pager__info { font-size: 12px; color: var(--muted); }
.st-pager .btn { white-space: nowrap; }
@media (max-width: 720px) { .st-pager { justify-content: center; } }

/* ④ 选商品 → 选规格 两步弹窗 */
.ai-pick__step { margin: 0 0 10px; font-size: 12px; color: var(--muted); }
.ai-pick__speclist { max-height: 320px; overflow-y: auto; padding-right: 2px; }
.ai-pick__specrow {
  display: flex; align-items: center; gap: 10px; width: 100%; box-sizing: border-box;
  padding: 10px 12px; margin-bottom: 6px; text-align: left; cursor: pointer;
  border: 1px solid var(--panel-border); border-radius: 8px;
  background: color-mix(in srgb, var(--panel-bg-solid) 55%, transparent); color: var(--text);
}
.ai-pick__specrow.is-on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.ai-pick__specname { font-size: 13px; }
.ai-pick__specqty { margin-left: auto; white-space: nowrap; font-size: 12px; color: var(--muted); }
.ai-pick__specqty.is-zero { color: var(--muted); opacity: .8; }
.ai-pick__specacts { display: flex; align-items: center; gap: 8px; padding-top: 10px; border-top: 1px solid var(--line); }
.ai-pick__specacts .tiny { flex: 1 1 auto; min-width: 0; }
.ai-pick__back { margin-right: auto; }

/* ⑤ 修改方案：部位 → 名称 → 选择规格 → 价格 → 删除。
   🔴 旧 700px 断点只有 3 列，新增一列后必须按 grid-row 明排，否则会串行错位。 */
.op-edit__row { grid-template-columns: minmax(0, .8fr) minmax(0, 1.6fr) minmax(0, 1.4fr) 92px 34px; }
.op-edit__row [data-oif="spec"] { min-width: 0; }
/* 保留原生 select 后要自己对齐输入框高度（没有 .csel__btn 壳了） */
.op-edit__row select[data-oif="spec"] { height: 39px; box-sizing: border-box; padding: 0 10px; }
@media (max-width: 700px) {
  .op-edit__row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 34px; row-gap: 6px; }
  .op-edit__row [data-oif="role"]  { grid-column: 1; grid-row: 1; }
  .op-edit__row [data-oif="name"]  { grid-column: 2; grid-row: 1; }
  .op-edit__row [data-oif="spec"]  { grid-column: 1 / 3; grid-row: 2; }
  .op-edit__row [data-oif="price"] { grid-column: 1 / 3; grid-row: 3; }
  .op-edit__row [data-oidel]       { grid-column: 3; grid-row: 1 / 4; }
}

/* ⑥ 推荐卡片的规格行 */
.ai-cell__spec { display: block; margin-top: 2px; font-size: 11px; color: var(--accent); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ==================== v1.16.52 ====================
   🔴 本版全部移动端规则一律关进 @media (max-width:720px)（或更窄），
      PC 端一条都不碰 —— 用户明确要求「不要影响 PC 端的显示」。
      新组件自身的样式（loading / 成交出库）写在媒体查询外，PC 也能用。 */

/* ① 商品网格卡：主图居中 + 文字/标签绝不越出卡片 */
@media (max-width: 720px) {
  .dcard-list--grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .sku-card { align-items: stretch; min-width: 0; }
  .sku-card__hero {
    display: flex; align-items: center; justify-content: center;
    width: 100%; min-width: 0; overflow: hidden;
  }
  .sku-card__img { width: 100%; height: 100%; object-fit: contain; object-position: center; }
  .sku-card__body, .sku-card__acts { width: 100%; min-width: 0; box-sizing: border-box; }
  .sku-card__top, .sku-card__meta, .sku-card__chips { min-width: 0; max-width: 100%; }
  .sku-card__name {
    display: block; max-width: 100%; min-width: 0;
    overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  }
  .sku-card__no, .sku-card__flag, .sku-card__chips .dchip {
    max-width: 100%; min-width: 0; overflow: hidden;
    white-space: nowrap; text-overflow: ellipsis; flex: 0 1 auto;
  }
  .sku-card__acts { justify-content: space-between; gap: 4px; padding: 8px 8px 10px; }
  .sku-card__acts .sku-iact { flex: 1 1 0; padding: 0 4px; }
}

/* ② 新建库存单据弹窗：窄屏改成「表头 2 列 + 明细行每张一卡三段」，
      行与行之间区域分明，不再互相压叠。PC 端仍是 12 栅格单行明细。 */
@media (max-width: 720px) {
  .inv-doc-modal { width: calc(100vw - 20px); max-height: calc(100% - 20px); }
  .inv-doc-modal .inv-form__body { overflow-x: hidden; padding: 12px 10px 4px; }
  .inv-doc-modal .inv-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; gap: 9px; }
  .inv-doc-modal .inv-grid > .field { grid-column: span 1 !important; min-width: 0; }
  .inv-doc-modal .inv-grid > .inv-f-kind-cell,
  .inv-doc-modal .inv-grid > .inv-f-remark-cell { grid-column: span 2 !important; }
  .inv-doc-modal .inv-grid .field > .input,
  .inv-doc-modal .inv-grid .field > .csel { width: 100%; min-width: 0; }
  .inv-doc-modal .inv-grid .csel__btn { width: 100%; }
  .inv-doc-modal .inv-lines { gap: 10px; }
  .inv-doc-modal .inv-line {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 34px;
    grid-template-rows: auto auto auto; gap: 7px; align-items: start;
    padding: 9px; border: 1px solid var(--line); border-radius: 10px;
    background: color-mix(in srgb, var(--panel-bg-solid) 45%, transparent);
  }
  .inv-doc-modal .inv-line__sku-cell { grid-column: 1 / 3; grid-row: 1; flex-wrap: wrap; }
  .inv-doc-modal .inv-line__skuq,
  .inv-doc-modal .inv-line__sku-cell > .csel,
  .inv-doc-modal .inv-line__sku-cell > select { flex: 1 1 100%; width: 100%; min-width: 0; }
  .inv-doc-modal .inv-line__v-cell { grid-column: 1 / 3; grid-row: 2; min-width: 0; }
  .inv-doc-modal .inv-line__v-cell > .csel,
  .inv-doc-modal .inv-line__v-cell > select { width: 100%; min-width: 0; }
  .inv-doc-modal .inv-line__q-cell { grid-column: 1; grid-row: 3; min-width: 0; }
  .inv-doc-modal .inv-line > .input[data-lf="note"] { grid-column: 2; grid-row: 3; width: 100%; min-width: 0; }
  .inv-doc-modal .inv-line > [data-iact="line-del"] { grid-column: 3; grid-row: 1 / 4; align-self: center; }
  .inv-doc-modal .inv-form__acts { flex-wrap: wrap; gap: 8px; padding: 10px 12px 14px; }
  .inv-doc-modal .inv-form__acts .btn { flex: 1 1 auto; }
}

/* ③ 子页签：tab 再多也不换行，改为同一行左右滑动 */
@media (max-width: 720px) {
  .subtabs, .ms-tabs, .st-walltabs, .ai-pick__tabs, .md-seg--lg {
    flex-wrap: nowrap !important; overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch; scrollbar-width: none;
  }
  .subtabs::-webkit-scrollbar, .ms-tabs::-webkit-scrollbar,
  .st-walltabs::-webkit-scrollbar, .ai-pick__tabs::-webkit-scrollbar,
  .md-seg--lg::-webkit-scrollbar { display: none; }
  .subtabs > *, .ms-tabs > *, .st-walltabs > *, .ai-pick__tabs > *, .md-seg--lg > * {
    flex: 0 0 auto; white-space: nowrap;
  }
  .subtab, .ms-tab, .ai-pick__tab, .md-seg--lg > button { white-space: nowrap; }
}

/* ④ 帮助中心：头部不挤成竖排、目录改顶部横排 chip、正文独立滚动 */
@media (max-width: 720px) {
  .mhelp__box { width: calc(100vw - 16px); height: calc(100vh - 24px); border-radius: 10px; }
  .mhelp__head { flex-wrap: wrap; gap: 8px; padding: 10px 12px; }
  .mhelp__title { flex: 0 0 auto; font-size: 15px; white-space: nowrap; }
  /* 🆕 v1.16.54 第 8 项②：弹性占位**保留**（旧版把它 display:none 了，
     于是「新手引导 / 关闭」紧贴标题排在左边）。占位吃掉中间空隙后，
     这两个按钮自然被推到最右侧。 */
  .mhelp__head > span[style*="flex:1"] { display: block; flex: 1 1 auto; min-width: 0; }
  .mhelp__head > .btn { flex: 0 0 auto; padding: 0 9px; }
  .mhelp__search { order: 5; flex: 1 1 100%; width: 100%; min-width: 0; }
  .mhelp__main { flex-direction: column; min-height: 0; }
  /* 🆕 v1.16.54 第 8 项②：目录 chip 由「换行铺两排」改为**单行左右滑动** */
  .mhelp__nav {
    width: 100%; flex: 0 0 auto; max-height: none;
    display: flex; flex-wrap: nowrap; align-content: flex-start;
    align-items: center; gap: 6px; padding: 8px 10px;
    overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
    border-right: 0; border-bottom: 1px solid var(--line);
    scrollbar-width: none;
  }
  .mhelp__nav::-webkit-scrollbar { height: 0; display: none; }
  .mhelp__grp { display: contents; }
  .mhelp__navhead, .mhelp__navitem--flat .tiny, .mhelp__hits { display: none; }
  .mhelp__navitem {
    width: auto; flex: 0 0 auto; margin: 0; padding: 6px 10px;
    font-size: 12px; white-space: nowrap;
    border: 1px solid var(--line); border-radius: 999px;
  }
  .mhelp__navitem--c { padding-left: 10px; }
  .mhelp__doc { flex: 1 1 auto; min-height: 0; overflow-x: hidden; padding: 14px 14px 40px; }
  .mhelp__dochead h3 { white-space: nowrap; }
  .mhelp__brief, .mhelp__line, .mhelp__steps li, .mhelp__faqa, .mhelp__faq summary {
    overflow-wrap: anywhere;
  }
}

/* ⑤ 发布中心 / ⑨ 操作日志：表格外层可横向拖动，列宽保持 PC 口径 */
@media (max-width: 720px) {
  #md-pub-body, #au-body {
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
  }
  .md-pub2__tbl { min-width: 860px; }
  #au-body .tbl--au { min-width: 760px; }
}

/* ⑦ 门店列表卡片：不再越过外层右边框 */
@media (max-width: 720px) {
  .scards { grid-template-columns: minmax(0, 1fr); gap: 10px; }
  .scard { width: 100%; min-width: 0; box-sizing: border-box; }
  .scard__head { min-width: 0; flex-wrap: wrap; row-gap: 6px; }
  .scard__name { flex: 1 1 auto; min-width: 0; }
  .scard__code, .scard__flags { flex: 0 1 auto; min-width: 0; }
  .scard__stats, .scard__acts { width: 100%; box-sizing: border-box; min-width: 0; }
}

/* ⑧ 门店分布图：窄屏气泡上下停靠时不要被拉宽、文字不竖排 */
@media (max-width: 720px) {
  .stm3-bub { width: auto; min-width: 0; max-width: 156px; white-space: nowrap; }
  .stm3-bub b, .stm3-bub em { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
}

/* ⑫ 三处记录列表的加载占位（复用提取服饰「呼吸感衣服图标」的动画） */
.st-log-load {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 7px; min-height: 164px; padding: 20px 10px; color: var(--text-dim);
  border: 1px dashed var(--line); border-radius: 10px;
  background: color-mix(in srgb, var(--panel-bg-solid) 45%, transparent);
}
.st-log-load .st-ex__pulse { color: var(--accent); animation: st-ex-pulse 1.35s ease-in-out infinite; }
.st-log-load b { font-size: 13px; font-weight: 500; color: var(--text); }
.st-log-load i { font-size: 11px; font-style: normal; opacity: .8; }
@media (prefers-reduced-motion: reduce) {
  .st-log-load .st-ex__pulse { animation-duration: 2.6s; }
}

/* ⑭ 登记成交：规格出库勾选区 */
.op-deal__ship { margin-top: 14px; padding-top: 12px; border-top: 1px dashed var(--line); }
.op-deal__shiphead { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 9px; }
.op-deal__shiphead > b { font-size: 12px; color: var(--text-strong); }
.op-deal__shiphead .btn { flex: 0 0 auto; }
.op-deal__shiplist { display: grid; gap: 6px; max-height: 220px; overflow-y: auto; padding-right: 2px; }
.op-deal__item {
  display: flex; align-items: center; gap: 9px; padding: 8px 10px;
  border: 1px solid var(--panel-border); border-radius: 8px;
  background: color-mix(in srgb, var(--panel-bg-solid) 55%, transparent);
}
.op-deal__item > label { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 0; cursor: pointer; }
.op-deal__item input[type="checkbox"] { flex: 0 0 auto; width: 15px; height: 15px; accent-color: var(--accent); }
.op-deal__item b { display: block; font-size: 12.5px; font-weight: 500; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.op-deal__item .tiny { display: block; margin-top: 2px; font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.op-deal__qty { flex: 0 0 auto; font-size: 12px; color: var(--accent); }
.op-deal__none { padding: 10px 2px; font-size: 12px; color: var(--muted); line-height: 1.7; }
@media (max-width: 720px) {
  .op-deal__shiplist { max-height: 190px; }
}

/* ⑬ 部位列改成原生中文下拉后，自己对齐输入框高度（同规格下拉） */
.op-edit__row select[data-oif="role"] { height: 39px; box-sizing: border-box; padding: 0 10px; }

/* ==================== v1.16.53 ====================
   🔴 移动端规则全部关进 @media (max-width:720px)，PC 端一个字不改。
   新组件（客户墙 / 数据备份 / 上拉加载）的自身样式写在媒体查询外。 */

/* ① 商品列表上拉加载哨兵 */
.st-loadmore {
  margin: 12px 0 4px; padding: 12px; text-align: center;
  font-size: 12px; color: var(--muted);
  border: 1px dashed var(--line); border-radius: 10px; cursor: pointer;
  background: color-mix(in srgb, var(--panel-bg-solid) 40%, transparent);
}
.st-loadmore:hover { color: var(--accent); border-color: var(--accent); }
.st-loadmore--end { cursor: default; opacity: .7; }
.st-loadmore--end:hover { color: var(--muted); border-color: var(--line); }

/* ② 客户墙：只有头像 + 姓名的图片墙
   🆕 v1.16.54 第 7 项：
     ① 头像必须是 **4:5 竖版**（旧样式把 width/height 都写成 62px，
        等于硬把它压成了 1:1 —— 用户一眼就看出来了）；
     ② 姓名在头像**下方**（flex 纵向 + name 的 order 兜底，永不被别处样式挤到上面）；
     ③ PC 端头像放大（列最小宽 104 → 150，间距 10 → 14）；
     ④ 移动端一屏 **4 个**（4 等分列，不靠 auto-fill 碰运气）。 */
.pwall { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 14px; }
.pwall__item {
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 8px;
  padding: 12px 10px 10px; border: 1px solid var(--panel-border); border-radius: 12px;
  background: var(--panel-bg); cursor: pointer; min-width: 0;
  transition: border-color .16s ease, transform .16s ease;
}
.pwall__item:hover { border-color: var(--accent); transform: translateY(-2px); }
/* 🔴 只给宽度，高度由 4:5 派生；写死 height 会把比例压成 1:1（上一版的错） */
.pwall__item .pav--detail {
  width: 100%; height: auto; aspect-ratio: 4 / 5;
  border-radius: 12px; align-self: stretch;
}
.pwall__name {
  order: 2;
  max-width: 100%; font-size: 12.5px; font-weight: 500; color: var(--text-strong);
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}

/* ③ 成交出库：库存不足的行不可勾选 */
.op-deal__item.is-short { opacity: .58; }
.op-deal__item.is-short > label { cursor: not-allowed; }
.op-deal__item.is-short input[type="checkbox"] { cursor: not-allowed; }
.op-deal__short { color: var(--danger); font-style: normal; }

/* ④ 数据备份（v1.16.53 重做） */
.bk2 { display: flex; flex-direction: column; gap: 14px; }
.bk2__card {
  padding: 16px 18px; border: 1px solid var(--panel-border); border-radius: var(--radius);
  background: var(--panel-bg); backdrop-filter: var(--backdrop); -webkit-backdrop-filter: var(--backdrop);
}
.bk2__hd { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.bk2__hd b { font-family: var(--serif); font-size: 15px; color: var(--text-strong); }
.bk2__d { font-size: 12.5px; color: var(--muted); line-height: 1.75; margin: 0 0 10px; }
.bk2__acts { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin-bottom: 12px; }
.bk2__cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14px; }
.bk2__colhd { font-size: 12px; color: var(--text-dim); margin-bottom: 7px; }
.bk2__list {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 5px;
  max-height: 360px; overflow-y: auto; padding: 8px;
  border: 1px solid var(--line-soft); border-radius: 10px;
  background: color-mix(in srgb, var(--panel-bg-solid) 40%, transparent);
}
.bk2__item {
  display: flex; align-items: center; gap: 8px; min-width: 0;
  padding: 6px 8px; border-radius: 8px; cursor: pointer;
}
.bk2__item:hover { background: var(--hover); }
.bk2__item input[type="checkbox"] { flex: none; width: 15px; height: 15px; accent-color: var(--accent); }
.bk2__nm { min-width: 0; display: flex; flex-direction: column; }
.bk2__nm b { font-size: 12.5px; font-weight: 500; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.bk2__nm i { font-size: 10.5px; font-style: normal; color: var(--muted-dim); font-family: var(--mono);
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.bk2__opt { display: flex; align-items: flex-start; gap: 8px; font-size: 12.5px; color: var(--text-dim);
  line-height: 1.65; margin-bottom: 8px; cursor: pointer; }
.bk2__opt input { flex: none; margin-top: 3px; width: 15px; height: 15px; accent-color: var(--accent); }

.bk2__prog { display: flex; flex-direction: column; gap: 6px; margin: 6px 0 12px; }
.bk2__prog:empty { display: none; }
.bk2__row {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 10px; border: 1px solid var(--line-soft); border-radius: 8px;
  background: color-mix(in srgb, var(--panel-bg-solid) 35%, transparent);
}
.bk2__rowmain { flex: 0 0 auto; width: 190px; min-width: 0; display: flex; flex-direction: column; }
.bk2__rowmain b { font-size: 12.5px; font-weight: 500; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.bk2__rowsub { font-size: 10.5px; color: var(--muted-dim); font-family: var(--mono);
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.bk2__bar { flex: 1 1 auto; height: 6px; border-radius: 999px; background: var(--line-soft); overflow: hidden; }
.bk2__bar > i { display: block; height: 100%; width: 0; border-radius: 999px;
  background: var(--accent); transition: width .25s ease, background .25s ease; }
.bk2__pct { flex: none; width: 42px; text-align: right; font-size: 11.5px; font-family: var(--mono); color: var(--muted); }
/* 完成 = 绿色 + 100% */
.bk2__row.is-done { border-color: color-mix(in srgb, var(--ok) 40%, transparent); }
.bk2__row.is-done .bk2__bar > i { background: var(--ok); }
.bk2__row.is-done .bk2__pct { color: var(--ok); }
.bk2__row.is-err { border-color: color-mix(in srgb, var(--danger) 45%, transparent); }
.bk2__row.is-err .bk2__bar > i { background: var(--danger); }
.bk2__row.is-err .bk2__pct { color: var(--danger); }

.bk2__stat { border: 1px solid var(--line-soft); border-radius: 10px; padding: 12px 14px; }
.bk2__statrow { display: flex; align-items: baseline; gap: 12px; padding: 3px 0; font-size: 12.5px; }
.bk2__statrow > span { flex: 0 0 92px; color: var(--muted); }
.bk2__statrow > b { color: var(--text-strong); font-weight: 500; word-break: break-all; }
.bk2__ok { margin: 8px 0 0; font-size: 12.5px; color: var(--ok); }
.bk2__errs { margin-top: 9px; font-size: 12px; color: var(--danger); }
.bk2__errs ul { margin: 5px 0 0; padding-left: 18px; max-height: 180px; overflow-y: auto; }
.bk2__errs li { line-height: 1.7; word-break: break-all; }
.bk2__card--fold summary { cursor: pointer; display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.bk2__form { margin-top: 12px; display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px; }
.bk2__form .bk2__acts { grid-column: 1 / -1; margin: 0; }

/* ⑤ 移动端（PC 端不受影响） */
@media (max-width: 720px) {
  /* 5.1 作品墙「全部 / 照片墙」与素材库：一行一个，参考视频墙 */
  .st-flow { flex-direction: column; gap: 10px; }
  .st-flow__col { flex: 1 1 auto; width: 100%; }
  .st-works__grid { columns: 1 !important; column-gap: 0 !important; }
  .st-works__grid .st-work { width: 100%; margin: 0 0 10px; }
  .st-work__acts { flex-wrap: wrap; }
  .st-work__acts .sku-iact { flex: 1 1 0; justify-content: center; }

  /* 5.2 生成日志 / 提取记录 / 组合记录 / 报告记录 / 库存流水 / 仓库 / 商品列表：
       不再挤压换行，保持各列宽度，外层可左右拖动 */
  .tbl-wrap { overflow-x: auto !important; -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain; }
  /* 三处记录列表的容器是裸 div（不是 .tbl-wrap），单独给横滑 */
  #st-genlog, #st-ex-log, #st-mx-log {
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain; max-width: 100%;
  }
  .tbl-wrap > .tbl { min-width: 760px; }
  .tbl-wrap .tbl th, .tbl-wrap .tbl td { white-space: nowrap; }
  #rl-rows .tbl--rl { min-width: 1240px; }
  #op-rows .tbl { min-width: 1180px; }
  #inv-txn-body .tbl { min-width: 1000px; }
  #inv-wh-body .tbl { min-width: 880px; }
  #st-genlog .tbl { min-width: 1080px; }
  #st-ex-log .tbl { min-width: 840px; }
  #st-mx-log .tbl { min-width: 900px; }
  #sku-body .tbl { min-width: 1000px; }

  /* 5.3 问卷记录：头像 + 主信息一行，日期与按钮沉到底行，去掉中间大片空白 */
  #rows .dcard { flex-wrap: wrap; align-items: flex-start; gap: 8px 10px; padding: 10px 12px; }
  #rows .dcard__main { flex: 1 1 calc(100% - 60px); max-width: calc(100% - 60px); }
  #rows .dcard__side {
    flex: 1 1 100%; flex-direction: row; align-items: center;
    justify-content: space-between; gap: 8px; margin-left: 0;
    padding-top: 7px; border-top: 1px dashed var(--line-soft);
  }
  #rows .dcard__date { font-size: 10.5px; }
  #rows .dcard__acts { margin-left: auto; }
  #rows .dcard__top { gap: 6px; row-gap: 4px; }
  #rows .dcard__chips, #rows .dcard__contact { margin-top: 4px; }

  /* 5.4 穿搭方案：操作按钮固定一行三个、最多两行（表格可横拖，不靠挤压换行） */
  .op-acts { min-width: 226px; }
  .op-acts__row { flex-wrap: nowrap !important; gap: 5px; }
  .op-acts__row .btn { flex: 1 1 0; min-width: 66px; padding: 0 6px; }

  /* 5.5 客户墙：移动端一行 4 个（v1.16.54 第 7 项） */
  .pwall { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
  .pwall__item { gap: 6px; padding: 8px 5px 7px; border-radius: 10px; }
  .pwall__item .pav--detail { border-radius: 9px; }
  .pwall__name { font-size: 11px; }

  /* 5.6 数据备份 */
  .bk2__cols { grid-template-columns: minmax(0, 1fr); }
  .bk2__list { max-height: 260px; grid-template-columns: minmax(0, 1fr); }
  .bk2__row { flex-wrap: wrap; gap: 6px 8px; }
  .bk2__rowmain { width: 100%; }
  .bk2__bar { flex: 1 1 auto; }
  .bk2__card { padding: 12px; }
  .bk2__statrow > span { flex: 0 0 72px; }
  .bk2__form { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   v1.16.54 第 3 项：全站图片 / 视频查看器统一「内容居中 + 底部两行工具条」
   --------------------------------------------------------------------------
   🔴 线上报障：移动端灯箱里「保存到素材库 / 下载」是 absolute 贴左贴右，
   「− 100% ＋ 复位」又是 absolute 居中 —— 窄屏三者必然互相压住；同时底部
   这一排浮层把图片的视觉中心顶偏，看起来「没有上下居中」。
   修法：.st-lb__main 改成 flex 纵向流 —— 舞台吃掉扣除工具条后的剩余高度并
   在其中居中，工具条占底部正常流；工具条内部再拆两行（动作行 / 缩放行），
   两行都 nowrap + 居中，永不重叠，也不会把「复位」挤成两行。
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**。
   ========================================================================== */
.st-lb__main {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 10px; padding: 8px 0 10px;
  overflow: hidden;
}
.st-lb__stage {
  flex: 1 1 auto; min-height: 0; width: 100%;
  grid-column: auto; grid-row: auto;
  display: grid; place-items: center;
  max-height: 100%; max-width: 100%;
  pointer-events: auto;
}
.st-lb__bar {
  flex: 0 0 auto; z-index: 3;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  max-width: calc(100% - 16px);
  pointer-events: none;
}
.st-lb__barrow {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  flex-wrap: nowrap; white-space: nowrap;
}
.st-lb__barrow--acts:empty { display: none; }
.st-lb__tool {
  position: static; left: auto; right: auto; bottom: auto;
  padding: 0 14px; height: 32px; border-radius: 999px;
  pointer-events: auto;
}
.st-lb__tool--save, .st-lb__tool--dl { left: auto; right: auto; }
.st-zoom {
  position: static; left: auto; bottom: auto; transform: none;
  pointer-events: auto;
}
.st-zoom__btn { white-space: nowrap; }
.st-zoom__hint { position: static; right: auto; bottom: auto; }
@media (max-width: 960px) {
  .st-lb__main { flex: none; height: auto; padding: 4px 0 8px; }
  .st-lb__stage { flex: none; height: auto; }
  .st-lb__stage > img, .st-lb__stage > video { max-height: 48vh; }
  .st-lb__bar { width: 100%; }
  .st-lb__tool { padding: 0 10px; font-size: 11px; }
}

/* ==========================================================================
   v1.16.54 第 15 项③ / 第 20 项：记录类表格「表头两侧圆角」+ 审计日志按钮同行
   --------------------------------------------------------------------------
   🔴 表头背景是整条 `--accent-soft`，`border-collapse: collapse` 下 border-radius
   在单元格上会被浏览器直接忽略（合并边框模型没有圆角概念）。要让表头两端
   真的圆起来，必须先切到 `separate` + `border-spacing: 0`。
   只对用户点名的这四张表生效（生成日志 / 提取记录 / 组合记录 / 审计日志），
   不动全站 `.tbl`，避免影响其它已上线的表格观感。
   ========================================================================== */
.tbl--genlog, #st-ex-log .tbl, #st-mx-log .tbl, .tbl--au {
  border-collapse: separate; border-spacing: 0;
}
.tbl--genlog thead th:first-child,
#st-ex-log .tbl thead th:first-child,
#st-mx-log .tbl thead th:first-child,
.tbl--au thead th:first-child {
  border-top-left-radius: 10px; border-bottom-left-radius: 10px;
}
.tbl--genlog thead th:last-child,
#st-ex-log .tbl thead th:last-child,
#st-mx-log .tbl thead th:last-child,
.tbl--au thead th:last-child {
  border-top-right-radius: 10px; border-bottom-right-radius: 10px;
}

/* ---- 审计日志：查询 / 刷新 永远是同一行（一个 nowrap 的按钮组） ---- */
.au-acts { display: inline-flex; align-items: center; gap: 8px; flex: none; }
.au-acts__sp { flex: 1 1 auto; }
@media (max-width: 720px) {
  .au-acts { width: 100%; }
  .au-acts .btn { flex: 1 1 0; }
  .au-acts__sp { display: none; }
}

/* ==========================================================================
   v1.16.54 · 移动端适配批次（第 8 / 11 / 12 / 13 项）
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**，PC 基准一个字不动。
   ========================================================================== */

/* ---- 第 8 项①：uiDialog 右上角关闭（opt.closeX） ---- */
.uid-x {
  margin-left: auto; flex: none;
  width: 30px; height: 30px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); background: transparent;
  color: var(--muted); font-size: 13px; line-height: 1; cursor: pointer;
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.uid-x:hover { color: var(--accent); border-color: var(--accent); background: var(--hover); }

/* ---- 第 11 项：多套方案的「竖向 tab」窄屏改横向可滑 ---- */
@media (max-width: 720px) {
  .ai-rail { grid-template-columns: minmax(0, 1fr); gap: 10px; }
  .ai-rail__tabs {
    position: static;
    flex-direction: row; flex-wrap: nowrap; align-items: stretch;
    gap: 6px; padding: 6px;
    overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  .ai-rail__tabs::-webkit-scrollbar { height: 0; display: none; }
  .ai-rail__tab { flex: 0 0 auto; text-align: center; padding: 7px 12px; white-space: nowrap; }
  .ai-rail__tab-t, .ai-rail__tab-d { white-space: nowrap; }
  /* 部位商品：一行横滑，不换行、不越出卡片右边界 */
  .ai-zone__g {
    flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden;
    max-width: 100%; padding-bottom: 2px;
    -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  .ai-zone__g::-webkit-scrollbar { height: 0; display: none; }
  .ai-zone__g .ai-cell { flex: 0 0 auto; width: 168px; }

  /* ---- 第 12 项：数字衣橱工具条按钮两列等宽、整齐成行 ---- */
  #ai-wardrobe-pane .toolbar > .input { flex: 1 1 100%; max-width: 100% !important; }
  #ai-wardrobe-pane .toolbar > .toolbar__label { flex: 0 0 auto; }
  #ai-wardrobe-pane .toolbar > span[style*="flex:1"] { display: none; }
  #ai-wardrobe-pane .toolbar > .btn { flex: 1 1 calc(50% - 5px); min-width: 0; padding-left: 8px; padding-right: 8px; }

  /* ---- 第 13 项：AI 顾问 —— 会话列表抽屉 + 输入区贴底 ---- */
  .ai-agent { display: block; position: relative; }
  .ai-agent__main { height: auto; min-height: 0; }
  .ai-agent__sidbtn { display: inline-flex; align-self: flex-start; margin-bottom: 8px; }
  .ai-agent__side {
    position: fixed; top: 0; left: 0; bottom: 0; z-index: 1500;
    width: min(84vw, 320px); max-height: none;
    border-radius: 0 14px 14px 0;
    transform: translateX(-102%); transition: transform .24s ease;
    box-shadow: 0 20px 60px rgba(0, 0, 0, .45);
    overflow-y: auto;
  }
  .ai-agent.is-side-open .ai-agent__side { transform: translateX(0); }
  .ai-agent__scrim {
    position: fixed; inset: 0; z-index: 1490;
    background: rgba(10, 9, 8, .5);
    opacity: 0; pointer-events: none; transition: opacity .2s ease;
  }
  .ai-agent.is-side-open .ai-agent__scrim { opacity: 1; pointer-events: auto; }
  .ai-chat { max-height: none; }
  .ai-chat__input {
    position: sticky; bottom: 0; z-index: 5;
    margin: 0 -4px; padding: 8px 4px calc(10px + env(safe-area-inset-bottom, 0px));
    background: var(--panel-bg-solid);
    border-top: 1px solid var(--line-soft);
  }
}
/* 宽屏：抽屉按钮/遮罩不占位。
   🔴 必须写成 min-width 断点再隐藏 —— 直接写 `.ai-agent__sidbtn{display:none}`
   会因为它排在 @media 之后、优先级相同而**反压**掉窄屏的 inline-flex。 */
@media (min-width: 721px) {
  .ai-agent__sidbtn, .ai-agent__scrim { display: none; }
}

/* ==========================================================================
   v1.16.54 · 移动端适配批次二（第 15 项② / 第 16 项）
   ========================================================================== */
@media (max-width: 720px) {
  /* ---- 第 15 项②：生成台「三张参考图」窄屏必须排在同一行 ----
     旧口径 .st-pick 固定 132×132，三张 132*3 + 间距 36 = 432px > 手机可用宽，
     于是折成 2+1，第二行孤零零一张。改成三等分（宽度自适应、aspect-ratio 保方形），
     间距同时收窄，三张稳稳一行。 */
  #st-ref-pickers { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; align-items: start; }
  #st-ref-pickers .st-refcol { min-width: 0; }
  #st-ref-pickers .st-pick { width: 100%; height: auto; aspect-ratio: 1 / 1; }

  /* ---- 第 16 项：服饰组合搭配 ----
     ① 「客户档案 / 人物」占位符改**横向**并独占一行（原来竖着一整块 + 跨两行）；
     ② 人物不再跨行后，部位按两列平铺 —— 头部与上装落在同一行。 */
  .st-mx__slots { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: auto; gap: 8px; }
  .st-mx__slot--person {
    grid-column: 1 / -1; grid-row: auto;
    flex-direction: row; align-items: center; gap: 10px;
  }
  .st-mx__slot--person .st-mx__thumb {
    flex: 0 0 92px; width: 92px; min-height: 0; aspect-ratio: 3 / 4;
  }
  .st-mx__slot--person .st-mx__cap {
    margin-top: 0; flex: 1 1 auto; min-width: 0;
    flex-direction: column; align-items: flex-start; gap: 2px;
  }
}

/* ==========================================================================
   v1.16.54 · 移动端适配批次三（第 14 项 / 第 18 项）
   ========================================================================== */

/* ---- 第 14 项：触达任务筛选区两栏整齐排列 ----
   桌面端：.rcf / .rcf__range 都是 display:contents —— 包装层对 flex 完全透明，
   子元素照旧参与 #ai-rc-filter 的横向流，**PC 视觉一处不变**。
   窄屏才切 grid：搜索框独占一行，场景 + 清除筛选并排一行，
   发送时间（起始 / 至 / 截止）独占一行，计数贴右下。 */
.rcf, .rcf__range { display: contents; }
.rcf--clear { margin-left: auto; }

@media (max-width: 720px) {
  #ai-rc-filter {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
    align-items: end;
    margin-top: 10px;
  }
  #ai-rc-filter .rcf {
    display: flex; flex-direction: column; gap: 5px;
    min-width: 0;
  }
  #ai-rc-filter .rcf--q { grid-column: 1 / -1; grid-row: 1; }
  #ai-rc-filter .rcf--scene { grid-column: 1; grid-row: 2; }
  #ai-rc-filter .rcf--clear { grid-column: 2; grid-row: 2; margin-left: 0; }
  #ai-rc-filter .rcf--time { grid-column: 1 / -1; grid-row: 3; }
  #ai-rc-filter .rcf__sp { display: none; }
  #ai-rc-filter > #ai-rc-count { grid-column: 1 / -1; grid-row: 4; justify-self: end; }
  /* 内联的 max-width（220/160/152px）是桌面口径，窄屏一律拉满格子 */
  #ai-rc-filter .input, #ai-rc-filter select.input { width: 100%; max-width: none !important; }
  #ai-rc-filter .rcf--clear .btn { width: 100%; justify-content: center; }
  #ai-rc-filter .rcf__range { display: flex; align-items: center; gap: 6px; }
  #ai-rc-filter .rcf__range .input { flex: 1 1 0; min-width: 0; }
  #ai-rc-filter .rcf__range > .tiny { flex: 0 0 auto; }
}

/* ---- 第 18 项：资产库列表窄屏排版 ----
   目标：首字方块与标题同一行 → 标签单独一行在标题下方 → 操作按钮最后单独一行。 */
.md-item__tags { display: inline-flex; align-items: center; gap: 6px; margin-left: 8px; vertical-align: 1px; }

@media (max-width: 720px) {
  .md-item > .md-assetrow {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: 10px;
    row-gap: 7px;
    align-items: start;
    width: 100%;
  }
  .md-item > .md-assetrow > .md-assetrow__ava { grid-column: 1; grid-row: 1; align-self: start; }
  .md-item > .md-assetrow > .md-assetrow__m { grid-column: 2; grid-row: 1; min-width: 0; }
  /* 标题 / 标签拆成上下两行 */
  .md-assetrow__m .md-item__t {
    display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  }
  .md-item__tags { margin-left: 0; }
  /* 操作按钮收进最后一行，横跨两列 */
  .md-item > .md-assetrow > .md-item__ops {
    grid-column: 1 / -1; grid-row: 2;
    margin-left: 0; max-width: none; justify-content: flex-start;
    flex-wrap: nowrap; gap: 8px;
    padding-top: 8px; border-top: 1px dashed var(--line-soft);
  }
  .md-item > .md-assetrow > .md-item__ops .btn { flex: 0 0 auto; }
}

/* ---- 第 13 项（补）：AI 顾问窄屏「输入区贴屏幕底部」 ----
   10240 行段只做到 height:auto + sticky，实测 .ai-agent__main 仍被聊天区顶到 1036px 高，
   整页往下长、输入区停在中部（390×844 实测 input.bottom=820 但 main.bottom=1279）。
   这里把 pane 锁成视口高、逐层 flex 撑满，聊天区自己滚，输入区（含发送按钮）永远贴底。
   ⚠️ 100dvh 先写 100vh 兜底（老内核不认 dvh，整条会失效）。 */
@media (max-width: 720px) {
  #ai-agent-pane { display: flex; flex-direction: column; min-height: calc(100vh - 152px); min-height: calc(100dvh - 152px); }
  #ai-agent-pane > .ai-agent { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
  .ai-agent__main { height: auto; min-height: 0; flex: 1 1 auto; display: flex; flex-direction: column; }
  .ai-agent__main .ai-chat { flex: 1 1 auto; min-height: 240px; max-height: none; }
  .ai-agent__main .ai-chat__input { flex: none; position: sticky; bottom: 0; z-index: 5; }
}

/* ==========================================================================
   v1.16.55 · 12 项修复批次
   ⚠️ 本段按项目铁律追加在**所有既有 @media 之后**：窄屏规则关在自己的
      @media 里，宽屏基准不受影响。
   ========================================================================== */

/* --------------------------------------------------------------------------
   需求 1：移动端图片查看器 —— 「已保存到素材库 / 下载」与「缩放 / 复位」同一行
   --------------------------------------------------------------------------
   上一轮把它们拆成了两行（动作行 + 缩放行）。用户要的是**一行**：
   两个动作按钮分别贴在「− 100% ＋ 复位」这组的左右两侧。
   做法：两条 .barrow 用 display:contents 对 flex 完全透明，让三个块
   （保存 / 缩放组 / 下载）变成同一行的一级子项，再用 order 排成
   左 · 中 · 右。这样 DOM 不用动，也不会再出现「两行」的观感。
   -------------------------------------------------------------------------- */
.st-lb__bar {
  flex-direction: row; align-items: center; justify-content: center;
  gap: 8px; flex-wrap: nowrap;
}
.st-lb__barrow--acts,
.st-lb__barrow--zoom { display: contents; }
#st-lb-save { order: 1; }
.st-lb__bar .st-zoom { order: 2; }
#st-lb-dl { order: 3; }
.st-lb__tool { flex: 0 0 auto; }

@media (max-width: 960px) {
  .st-lb__bar { width: 100%; max-width: 100%; padding: 0 8px; gap: 6px; }
  .st-lb__tool { padding: 0 9px; font-size: 11px; height: 30px; }
  .st-lb__bar .st-zoom { gap: 4px; }
  .st-lb__bar .st-zoom__btn { padding: 0 8px; height: 30px; }
}
@media (max-width: 400px) {
  .st-lb__tool { padding: 0 7px; font-size: 10.5px; }
  .st-lb__bar .st-zoom__btn { padding: 0 6px; font-size: 11px; }
  .st-lb__bar .st-zoom__v { min-width: 38px; font-size: 11px; }
}

/* --------------------------------------------------------------------------
   需求 2：移动端顶部门店下拉「更宽」，尽量把门店名显示全
   --------------------------------------------------------------------------
   原规则在 ≤640px 把 max-width 压到 132px、还藏了图标，导致
   「MIRA 郑州店」被截成「MIRA …」。门店名是全局上下文，宁可压缩标题也要让它读全。
   这里放宽到视口的一半以上，并让名称自己 flex 吃满剩余宽度。
   -------------------------------------------------------------------------- */
@media (max-width: 720px) {
  .topbar .store-switch { flex: 1 1 0; min-width: 0; max-width: min(70vw, 300px); }
  /* 手机上顶栏被五枚图标按钮占满，门店胶囊只分到 ~110px：
     把内边距 / 图标 / 字距都收紧一点，省下来的全给门店名（实测 58px → 79px，
     「MIRA 郑州店」能完整显示，不再被截成「MIRA …」）。 */
  .topbar .store-switch__btn { padding: 0 7px 0 8px; gap: 5px; }
  .topbar .store-switch__name { flex: 1 1 auto; font-size: 11.5px; }
  .topbar .store-switch__caret { width: 11px; height: 11px; }
  /* 门店胶囊要真的变宽，只能从「间距 / 图标按钮内边距」里抠 ——
     实测顶栏在 390px 下已经超载约 10px；这里把 gap 10→8、按钮 9→8，
     一共让出 ~24px，全部给门店名（60 → 84px，「MIRA 郑州店」完整显示）。 */
  .topbar { gap: 8px; padding: 0 5px 0 8px; }
  .topbar__actions { gap: 6px; }
  .topbar__actions .btn { padding: 6px 8px; }
  /* 顶栏标题在手机上本来就只剩两三个字（实测只能分到 ~50px，还会被右侧图标挤掉），
     而页面内容区自己有完整的页头标题 —— 这里让位给门店下拉，把门店名尽量显示全。
     `.topbar__spacer` 是纯占位，手机上也收掉，把这点宽度全给门店名。 */
  .topbar__title { display: none; }
  .topbar__spacer { display: none; }
}
@media (max-width: 420px) {
  .topbar .store-switch { max-width: min(66vw, 240px); }
  .topbar .store-switch__btn { padding: 0 8px; gap: 5px; }
}

/* --------------------------------------------------------------------------
   需求 8：收起模式（图标轨）下的二级菜单浮窗
   --------------------------------------------------------------------------
   三个真实缺陷，全部来自第 637 行那条折叠态一级项规则：
     `.layout.left-collapsed .sidebar .menu-item { width:46px; padding:11px 0;
      justify-content:center }` —— 它把**二级项也**压成 46px 宽、文字居中，
   于是文字冲出 158px 的浮窗右边界、左侧也没有内缩间距。
   这里把二级项还原成「占满浮窗宽度 + 左对齐 + 左右留白」，
   并把整条侧栏在悬停时抬到顶层（浮窗不再被内容区盖住）。
   -------------------------------------------------------------------------- */
.layout.left-collapsed .sidebar:hover,
.layout.left-collapsed .sidebar:focus-within { z-index: 40; }
.layout.left-collapsed .sidebar .menu-sub {
  min-width: 176px;
  padding: 8px;
  gap: 2px;
  max-width: min(280px, calc(100vw - 100px));
}
.layout.left-collapsed .sidebar .menu-sub .menu-item--sub {
  width: 100%;
  justify-content: flex-start;
  align-items: center;
  text-align: left;
  gap: 8px;
  padding: 9px 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 二级项文字很长时宁可省略，也不许撑破浮窗 */
.layout.left-collapsed .sidebar .menu-sub .menu-item--sub > .menu-badge { margin-left: auto; }

/* --------------------------------------------------------------------------
   需求 9：移动端**不支持**收起模式（只 PC 端支持）
   --------------------------------------------------------------------------
   手机上侧栏是抽屉，没有「压成图标轨」的语义；折叠态还给 .sidebar /
   .sidebar__nav 打开了 overflow: visible（那是给桌面浮窗用的），
   抽屉因此丢掉滚动 —— 这就是「收起菜单导致菜单栏无法滚动」。
   JS 侧 setLeft() 已忽略移动端的收起请求，这里再兜住样式与按钮。
   -------------------------------------------------------------------------- */
@media (max-width: 720px) {
  .sidebar__collapse,
  .layout.left-collapsed .sidebar__collapse { display: none !important; }
  .layout.left-collapsed .sidebar { overflow: hidden; }
  .layout.left-collapsed .sidebar__nav,
  .layout:not(.left-collapsed) .sidebar__nav {
    overflow-y: auto; overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
  }
  .layout.left-collapsed .sidebar .menu-sub { position: static; min-width: 0; max-width: none; }
}

/* --------------------------------------------------------------------------
   需求 10：AI 顾问（移动端）—— 输入区要有底板且真正吸底；会话只留一个滚动容器
   --------------------------------------------------------------------------
   上一轮用「pane 锁视口高 + 内层 .ai-chat 自己滚 + sticky 输入区」，
   结果变成**双层滚动**：手势落在聊天区里时外层不响应，滚到底又会卡住，
   看起来就是「滚不动 / 卡顿」。而且输入区背景是半透明的，没有底板感。
   这里换成聊天的标准做法：
     · 取消锁高，整页只由 .content 一个容器滚动（不可能再冲突）；
     · 输入区 position: fixed 贴视口底部，实心底板 + 顶部描边 + 阴影；
     · pane 底部预留与底板等高的空白，最后一条消息不会被挡住。
   -------------------------------------------------------------------------- */
@media (max-width: 720px) {
  /* ⚠️ 不能用 position:fixed —— 这个 pane 的祖先卡片带 backdrop-filter，
     fixed 的包含块会变成那张卡片而不是视口（实测 bottom=1255，视口只有 844）。
     改用「高度链 + 单一滚动容器」：pane 高度由 JS 算成恰好填满内容区（fitAiPane），
     .ai-chat 吃剩余高度自己滚，输入区是它的兄弟 flex 子项，天然停在底部。 */
  #ai-agent-pane {
    display: flex; flex-direction: column;
    min-height: 0;
    padding-bottom: 0;
  }
  #ai-agent-pane > p { flex: 0 0 auto; }
  #ai-agent-pane > .ai-agent { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
  .ai-agent__main { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 8px; }
  .ai-agent__main .ai-chat {
    flex: 1 1 auto; min-height: 0; max-height: none;
    overflow-y: auto; overscroll-behavior: contain;
  }
  /* 输入区：实心底板（原来继承了半透明 panel-bg，看起来「没有底板」）*/
  .ai-agent__main .ai-chat__input {
    flex: 0 0 auto;
    position: static;
    margin: 0;
    padding: 9px 10px calc(9px + env(safe-area-inset-bottom, 0px));
    background: var(--panel-bg-solid);
    border: 1px solid var(--line-soft);
    border-radius: 12px;
    box-shadow: 0 -6px 20px rgba(0, 0, 0, .28);
  }
  .ai-agent__main .ai-chat__input textarea { min-height: 54px; }
}

/* --------------------------------------------------------------------------
   需求 11：服饰组合搭配（移动端）—— 人物占位居中，「人物 / 可不选」居中在下方
   --------------------------------------------------------------------------
   上一轮把人物槽改成横向（缩略图在左、文字在右），用户要的是：
   占位框在底板里左右居中，说明文字落在占位框**下方**并居中。
   -------------------------------------------------------------------------- */
@media (max-width: 720px) {
  .st-mx__slot--person {
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 10px 8px 9px;
  }
  .st-mx__slot--person .st-mx__thumb {
    flex: 0 0 auto;
    width: 96px; min-height: 0; aspect-ratio: 3 / 4;
    margin: 0 auto;
  }
  .st-mx__slot--person .st-mx__cap {
    width: 100%;
    margin-top: 0;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    text-align: center;
  }
}

/* --------------------------------------------------------------------------
   需求 6.1 / 6.3：数据备份 —— 下拉浮层置顶 + 历史记录表格
   --------------------------------------------------------------------------
   · .bk2__card 带 backdrop-filter，会自成层叠上下文；它自身 z-index:auto，
     后面的兄弟卡片天然压在它上面 → 自绘下拉怎么调 z-index 都白搭。
     哪张卡片的下拉打开，就把该卡片抬到顶层（.is-sel-open）。
   · 历史备份记录改成与全站一致的表格：容器独立横向滚动，窄屏不挤压列宽。
   -------------------------------------------------------------------------- */
.bk2__card { position: relative; }
.bk2__card.is-sel-open { z-index: 60; }
.bk-sel.is-open .bk-sel__menu { z-index: 1400; }
.bk2__histwrap { margin-top: 8px; overflow-x: auto; }
.tbl--bkhist { min-width: 760px; }
.tbl--bkhist td, .tbl--bkhist th { padding-top: 8px; padding-bottom: 8px; }
.bk2__hist { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line-soft); }

/* ==========================================================================
   v1.16.56
   ========================================================================== */

/* --------------------------------------------------------------------------
   需求 1：移动端顶部门店下拉「和标题栏一行同宽」
   --------------------------------------------------------------------------
   下拉面板是 `.store-switch`（相对定位）里的绝对定位元素，默认按内容撑宽
   （min-width 240px / max-width 62vw），手机上比顶栏窄一大截。
   这里把宽度放开，由 JS（storeMenuOpen）按顶栏实际宽度写 left/width ——
   CSS 只负责「别再自己限宽」，两边各留 0 才不会一宽一窄。
   -------------------------------------------------------------------------- */
@media (max-width: 720px) {
  .topbar .store-menu {
    left: 0;
    right: auto;
    width: auto;
    min-width: 0;
    max-width: none;
    max-height: min(58vh, 420px);
    box-sizing: border-box;
  }
}

/* --------------------------------------------------------------------------
   需求 3.3：收起态「MIRA 虚拟试衣间」图标偏右 —— 根因是分组与单项的对齐口径不同
   --------------------------------------------------------------------------
   收起态里 `菜单分组`（.menu-group）是 `width:100%` 的块，内部 46px 的按钮
   左对齐 → 图标中心落在 44px；而 `单项`（试衣间 / 驾驶舱 / 问卷记录 …）
   是 flex 子项、被 `align-items:center` 居中 → 图标中心落在 49px。
   同一列图标因此差了 5px，试衣间那一枚看起来「往右歪」。
   修法：让分组的按钮也居中（组本身仍是 relative，浮窗定位不受影响）。
   -------------------------------------------------------------------------- */
.layout.left-collapsed .sidebar .menu-group {
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* --------------------------------------------------------------------------
   需求 3.1 + 3.2：收起态菜单栏可滚动，二级浮窗不再被裁切且自动上下翻转
   --------------------------------------------------------------------------
   🔴 老做法是给 `.sidebar__nav` 开 `overflow: visible` 才能让二级浮窗伸出去，
      代价是图标栏永远滚不动（窗口一矮，底部「门店列表 / 门店分布图」就看不见）。
      而只要开了 `overflow-y:auto`，浮窗就会被裁在导航区里。
   正解：导航区正常滚动（overflow-y:auto），二级浮窗**改由 JS 渲染到 body**
      （#rail-fly，见 admin.js railFlyOpen），既不被裁切，也能在下方空间不够时
      自动改向上展开。收起态把原来的 CSS hover 浮窗与 data-tip 气泡关掉，
      避免两套并存时一上一下闪一下。
   -------------------------------------------------------------------------- */
.layout.left-collapsed .sidebar__nav {
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  /* 🔴🔴 v1.16.58 需求 5 真因：Chrome 121+ 只要读到标准属性 scrollbar-width，
     就会**整体忽略** ::-webkit-scrollbar 伪元素，改用系统自带滚动条（约 10px 粗灰条）。
     上一版只删了 6px 自定义，漏了这条 `scrollbar-width: thin`，所以收起态依旧是粗条 ——
     用户连着两轮报「没改」。这里彻底不写任何滚动条属性，与展开态一起回落
     本文件 164 行那条全局 `::-webkit-scrollbar{width:4px}` 半透明细线。 */
}
.layout.left-collapsed .sidebar .menu-group:hover > .menu-sub { display: none; }
.layout.left-collapsed .sidebar .menu-item[data-tip]::after { display: none; }

/* 浮窗本体（挂在 body 上，定位与翻转由 JS 写） */
.rail-fly {
  position: fixed;
  z-index: 95;
  display: none;
  box-sizing: border-box;
  padding: 7px;
  min-width: 180px;
  max-width: min(300px, calc(100vw - 24px));
  max-height: calc(100vh - 16px);
  overflow-y: auto;
  background: var(--panel-bg-solid, var(--panel-bg));
  border: 1px solid var(--panel-border-strong);
  border-radius: 12px;
  box-shadow: 0 16px 40px -12px rgba(0, 0, 0, .62), 0 0 0 1px rgba(255, 255, 255, .025) inset;
}
.rail-fly.is-on { display: block; }
.rail-fly .menu-sub {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 0;
  margin: 0;
}
.rail-fly .menu-item--sub {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 9px 12px;
  border: 0;
  border-radius: 9px;
  background: transparent;
  color: var(--text);
  font-family: inherit;
  font-size: 12.5px;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}
.rail-fly .menu-item--sub:hover { background: var(--hover); color: var(--text-strong); }
.rail-fly .menu-item--sub.is-on { color: var(--accent); font-weight: 600; background: color-mix(in srgb, var(--accent) 12%, transparent); }
.rail-fly .menu-badge { margin-left: auto; }
.rail-fly__tip {
  padding: 8px 12px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-strong);
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   需求 7：GPT 系模型总闸
   --------------------------------------------------------------------------
   与「包含文件内容」那类勾选项同一套视觉：整行可点、勾选框 15px、
   说明文字折行不挤压。不要做成开关滑杆 —— 它是**限制性**选项，
   复选框 + 明确文案比滑杆更难误触。
   -------------------------------------------------------------------------- */
.gptban {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 0 0 14px;
  padding: 11px 12px;
  border: 1px solid var(--panel-border);
  border-radius: 10px;
  background: var(--hover);
  cursor: pointer;
}
.gptban input[type="checkbox"] {
  flex: none;
  width: 15px; height: 15px;
  margin: 2px 0 0;
  accent-color: var(--accent);
  cursor: pointer;
}
.gptban__txt { display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; line-height: 1.55; }
.gptban__txt b { color: var(--text-strong); font-weight: 600; }
.gptban:hover { border-color: var(--panel-border-strong); }

/* ==========================================================================
   v1.16.57
   ⚠️ 依项目铁律：本段追加在**所有 @media 之后**，不改动任何旧规则。
   ========================================================================== */

/* --------------------------------------------------------------------------
   需求 1 / 8：图片·视频查看器「点空白 + 点关闭按钮」全都关不掉
   --------------------------------------------------------------------------
   🔴 根因（真浏览器 elementFromPoint 实测）：v1.16.54 把 .st-lb__stage 改成
      `flex:1 1 auto; width:100%` 后，舞台**铺满整个主区**；它又带着
      `pointer-events:auto`，于是关闭按钮所在坐标与画面四周空白处的命中元素
      都是 DIV.st-lb__stage —— 点击永远到不了 .st-lb__scrim / .st-lb__x。
      （.lbx 那套全局查看器没有这个问题，实测能正常关闭。）
   修法：舞台本身对鼠标透明，只让里面的 <img>/<video> 接收事件（缩放/拖拽
      照常，事件会冒泡到 stage / main 的滚轮与双击监听）；空白点击随即穿透到
      scrim。再把关闭按钮抬到 z-index:5，避免任何后续布局压住它。
   JS 侧另外在 #st-lightbox 上加了一层「非交互区点击即关闭」的兜底委托。
   -------------------------------------------------------------------------- */
.st-lb__stage { pointer-events: none; }
.st-lb__stage > img,
.st-lb__stage > video { pointer-events: auto; }
.st-lb__x { z-index: 5; }

/* --------------------------------------------------------------------------
   需求 7：折叠态头像 hover 底纹改成紧贴头像的正方形
   --------------------------------------------------------------------------
   .sidebar__me 是 width:100% 的横向按钮（border-radius:11px），收起态虽然
   隐藏了文字，底纹仍是一整条圆角横条。这里收成 46×46 方角方块，正好包住
   34px 头像，和图标轨里其它方形按钮同一种语言。
   -------------------------------------------------------------------------- */
.layout.left-collapsed .sidebar__me {
  width: 46px; height: 46px;
  padding: 5px; margin: 0 auto;
  justify-content: center;
  border-radius: 0;
}

/* --------------------------------------------------------------------------
   需求 2：生成记录「回填」按钮（与「恢复搭配」同排，主色描边区分动作）
   -------------------------------------------------------------------------- */
.st-mx__backfill {
  display: inline-flex; align-items: center; gap: 4px;
  margin-top: 6px; padding: 3px 8px;
  border: 1px solid var(--accent); border-radius: 7px;
  background: transparent; color: var(--accent);
  font-size: 11px; line-height: 1.5; cursor: pointer;
}
.st-mx__backfill:hover { background: var(--accent-soft); }
.st-mx__backfill:disabled { opacity: .55; cursor: default; }
.st-mx__planref {
  display: block; margin-top: 4px;
  font-size: 10.5px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  max-width: 132px;
}

/* --------------------------------------------------------------------------
   需求 5：备份「停止」按钮（与主按钮同排，危险色描边）
   -------------------------------------------------------------------------- */
.bk2__acts .btn--stop {
  border-color: var(--danger, #B4453B);
  color: var(--danger, #B4453B);
}
.bk2__acts .btn--stop:hover { background: rgba(180, 69, 59, .12); }

/* --------------------------------------------------------------------------
   需求 4：客户档案「服装人体测量尺寸图」
   --------------------------------------------------------------------------
   米色工程图纸 + 细线三视图（正视 / 侧视 / 背视）+ 尺寸引出线。
   整张图是纯 SVG，随客户围度数据实时生成，不依赖任何外部图片。
   -------------------------------------------------------------------------- */
.bm-fig { width: 100%; }
/* 图纸是 960×660 的横向工程图：窄容器允许横向滑动看全，点击整张图再进灯箱放大。 */
.bm-fig__scroll { width: 100%; overflow-x: auto; overflow-y: hidden; border-radius: 10px; }
.bm-svg {
  display: block; width: 100%; min-width: 720px; height: auto;
  border: 1px solid var(--line); border-radius: 10px;
  background: #FBF8F1;
  cursor: zoom-in;
}
.bm-zoom-hint {
  display: flex; align-items: center; gap: 6px;
  margin: 10px 0 0; font-size: 11.5px; line-height: 1.6; color: var(--muted);
}
.bm-zoom-hint b { color: var(--accent); font-weight: 600; }
.bm-note {
  margin-top: 10px; margin-bottom: 2px; font-size: 11.5px; line-height: 1.75; color: var(--muted);
}
.bm-note b { color: var(--text-strong); font-weight: 600; }
/* 🔴 测量图是 820×600 的横向工程图，塞进原来 220~290px 的左列会小到读不出字。
   客户档案这一处改成「整行上图、下方数据」；不复用 .sizelayout（问卷详情还在用）。 */
.bm-layout { display: flex; flex-direction: column; gap: 18px; }
.bm-layout__fig { min-width: 0; width: 100%; }
/* 🔴 v1.16.58 需求 3：比值卡片行与围度数据行原来是上下贴死的（.metrics 没有下边距），
   这里让数据区自己变成有间距的竖排，行与行不再紧挨。 */
.bm-layout__data { min-width: 0; width: 100%; display: flex; flex-direction: column; gap: 16px; }



/* ==========================================================================
   v1.16.58（6 项）
   ⚠️ 依项目铁律：本段追加在**所有规则之后**，不改动任何旧规则。
   ========================================================================== */

/* 需求 1：备份「撤销」按钮（与停止按钮同排，中性描边，区别于危险色的停止） */
.bk2__acts .btn--undo {
  border-color: var(--panel-border-strong);
  color: var(--muted);
}
.bk2__acts .btn--undo:hover { color: var(--text-strong); background: var(--hover); }

/* --------------------------------------------------------------------------
   需求 5 / 6：收起态滚动条 & 移动端侧栏
   --------------------------------------------------------------------------
   🔴 需求 5：全局 164 行已有 `::-webkit-scrollbar{width:4px}`。收起态只要再写
      `scrollbar-width` 就会让 Chrome 忽略伪元素、退回系统粗条 —— 所以这一版
      **不再给收起态补任何滚动条规则**，两态共用同一条 4px 细线。
   🔴 需求 6：本文件后半段（4452 / 5522 / 10812 / 10990 / 11154 附近）陆续追加过
      一批 `.layout.left-collapsed …` 规则，它们写在 `@media (max-width:860px)`
      那次「移动端还原」**之后**，同特异性下后写者胜 —— 于是窄屏即使保留了
      left-collapsed 类，也会出现 46×46 方形头像、静态定位被改、二级菜单浮窗
      飘到内容区。这里用末段媒体查询统一压回去，PC 端一条都不受影响。
   -------------------------------------------------------------------------- */
@media (max-width: 860px) {
  .layout.left-collapsed .sidebar,
  .layout:not(.left-collapsed) .sidebar { width: 264px; flex-basis: 264px; }
  .layout.left-collapsed .content { left: var(--pad); }
  .layout.left-collapsed .sidebar__brand {
    justify-content: flex-start; flex-direction: row; gap: 10px; padding: 15px 16px 13px;
  }
  .layout.left-collapsed .sidebar__mark,
  .layout.left-collapsed .sidebar__logo,
  .layout.left-collapsed .sidebar__name { display: revert; }
  /* 移动端没有收起态，折叠按钮一律不给 */
  .layout.left-collapsed .sidebar__collapse,
  .sidebar__collapse,
  #btn-collapse { display: none !important; }
  .layout.left-collapsed .sidebar__nav { padding: 12px 10px; align-items: stretch; gap: 0; }
  .layout.left-collapsed .sidebar .menu-label { display: block; }
  .layout.left-collapsed .sidebar .menu-txt,
  .layout.left-collapsed .sidebar .menu-badge,
  .layout.left-collapsed .sidebar .menu-caret,
  .layout.left-collapsed .sidebar .menu-tag-soon,
  .layout.left-collapsed .sidebar__foot,
  .layout.left-collapsed .sidebar__foot .sidebar__who-main,
  .layout.left-collapsed .sidebar__me .sidebar__who-main,
  .layout.left-collapsed .sidebar__me-caret { display: revert; }
  .layout.left-collapsed .sidebar .subnav__btn.menu-item,
  .layout.left-collapsed .sidebar .menu-item {
    width: 100%; justify-content: flex-start; gap: 11px; padding: 10px 12px;
  }
  .layout.left-collapsed .sidebar .menu-group {
    display: block; position: static; width: 100%;
  }
  .layout.left-collapsed .sidebar .menu-group + .menu-group { border-top: 0; padding-top: 0; margin-top: 0; }
  .layout.left-collapsed .sidebar .menu-sub,
  .layout.left-collapsed .sidebar .menu-group:hover > .menu-sub {
    display: flex;
    position: static; left: auto; top: auto;
    min-width: 0; padding: 0 0 0 22px;
    background: none; border: 0; box-shadow: none;
  }
  .layout.left-collapsed .sidebar .menu-item[data-tip]::after,
  .layout.left-collapsed .sidebar .menu-group:hover .menu-item--parent::after { display: none !important; }
  .layout.left-collapsed .sidebar__me {
    width: 100%; height: auto; padding: 6px 8px; margin: 0;
    justify-content: flex-start; border-radius: 11px;
  }
  .layout.left-collapsed .sidebar__foot .sidebar__avatar { width: 34px; height: 34px; }
  /* body 浮窗只在 PC 收起态用；移动端一律不渲染 */
  #rail-fly { display: none !important; }
}


/* ==========================================================================
   v1.16.60 · 2026-11-09（横竖封面 tab / 新形态媒体盒 / 发布中心素材列）
   🔴 用户长期偏好：相邻内容行一律显式留 margin / gap / line-height，不许贴死。
   ========================================================================== */

/* 新增形态标签色，跟原有四种同一套色阶 */
.tag--kind-moment { color: #fff; background: #A8732E; }
.tag--kind-podcast { color: #fff; background: #4C6B7A; }

/* 封面图：横版 / 竖版 tab */
.md-cover-tabs { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0 0 10px; }
.md-cover-tab {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 13px; border-radius: 9px; border: 1px solid var(--line);
  background: transparent; color: var(--text-dim); font-size: 12.5px; line-height: 1.5;
  cursor: pointer; transition: background .16s, color .16s, border-color .16s;
}
.md-cover-tab:hover { background: var(--hover); color: var(--text-strong); }
.md-cover-tab.is-on {
  border-color: rgba(198, 162, 106, .55); background: rgba(198, 162, 106, .13);
  color: var(--accent); font-weight: 600;
}
.md-cover-tab .tiny { opacity: .72; }
.md-cover-tabs__hint { margin: 0 0 14px; line-height: 1.8; }

/* 动态 / 播客 / 视频稿件的媒体文件板块 */
.md-media-ops { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.md-media-up { cursor: pointer; }
.md-media-msg { min-height: 18px; }
.md-media-prev { background: var(--hover) !important; padding: 8px; }
.md-media-prev audio { display: block; width: 100%; height: 38px; }
.md-media-prev video { max-height: 280px; }

/* v1.16.62：列序 封面/稿件/形态/状态/平台/素材/时间(添加+发布上下两行)/操作 */
.md-pub2__tbl { overflow-x: auto; overflow-y: hidden; }
.md-pub2__hd, .md-pub2__row {
  grid-template-columns: 58px minmax(120px, .9fr) 66px 66px minmax(80px, .5fr) minmax(175px, 1.15fr) 140px 240px;
  min-width: 1030px;
}
@media (max-width: 1080px) {
  .md-pub2__hd, .md-pub2__row {
    grid-template-columns: 52px minmax(100px, .8fr) 58px 58px minmax(70px, .48fr) minmax(155px, 1.1fr) 132px 200px;
    min-width: 930px;
  }
}
.md-pub2__mat { display: flex; flex-wrap: wrap; align-content: center; gap: 5px 9px; min-width: 0; }
.md-mat {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 11px; line-height: 1.55; white-space: nowrap;
}
.md-mat__i { font-style: normal; font-weight: 700; }
.md-mat.is-ok { color: var(--text-dim); }
.md-mat.is-ok .md-mat__i { color: #2E7D5B; }
.md-mat.is-miss { color: var(--muted); opacity: .82; }
.md-mat.is-miss .md-mat__i { color: var(--danger, #c0392b); }

/* 🆕 v1.16.61 需求 2：工作流配置从 4 个形态 tab 变 6 个。
   中等宽度允许换行，显式 row-gap 保证两行不贴死；窄屏仍由 720px 规则
   用 flex-wrap:nowrap !important 接管成单行横滑，PC 不受影响。 */
#md-skill-tabs { flex-wrap: wrap; row-gap: 6px; }

/* 🆕 v1.16.62 需求 1：发布中心「添加时间 / 发布时间」合并成一列上下排列。
   两行之间显式 row-gap + line-height，标签与时间之间显式 gap；
   平台列由 minmax(110px,1fr) 收到 minmax(80px,.5fr)，腾出的宽度给时间和操作列，
   操作列 210 → 240px，避免「同步发布 / 标记已发布 / 移除」与时间挤在一起。 */
.md-pub2__times {
  display: flex; flex-direction: column; justify-content: center;
  row-gap: 5px; min-width: 0; line-height: 1.55;
}
.md-pub2__tm {
  display: flex; align-items: baseline; gap: 6px;
  white-space: nowrap; font-size: 11.5px; color: var(--muted);
}
.md-pub2__tm i {
  flex: 0 0 auto; font-style: normal; font-size: 10.5px;
  opacity: .72; letter-spacing: .5px;
}
/* 三按钮同行放不下时允许换行，绝不横向挤压到时间列；换行也显式留行间距 */
.md-pub2__ops { flex-wrap: wrap; row-gap: 5px; justify-content: flex-end; }

/* 🆕 v1.16.63 需求 1：审计日志「操作人」列 —— 姓名与角色徽章必须同一行。
   原因：原来操作人列 130px、姓名与 .au-role 都是 inline-block，角色徽章
   「超级副管理员」自身就宽 ~88px，加上姓名与左右 padding 后总需求 >144px，
   浏览器只能把徽章挤到第二行，看起来像「被压扁」。
   做法：
   ① 操作人列 130 → 210px（内容区 182px：姓名 ≤88 + gap 6 + 徽章 88，刚好余量）；
   ② .au-who 用 flex + nowrap，姓名可省略号收缩（带 title 兜底），徽章 flex:none 绝不压缩；
   ③ 详情列从原自适应宽度里让出空间 —— 改用 table-layout:fixed 后它吃剩余宽度，
      配 .au-d 的 overflow-wrap:anywhere 自行折行，不再跟操作人抢宽；
   ④ 表格给 min-width 780px（固定四列合计 608 + 详情最少 ~172），1080 视口下
      仍不出现横向滚动条；只有真正窄屏才由 #au-body 独立横滚
      （项目铁律：各容器各自 overflow-x），宁横向滚动也不把姓名与角色挤成两行。 */
.tbl--au { table-layout: fixed; min-width: 780px; }
#au-body { overflow-x: auto; }
.tbl--au .au-who {
  display: flex; align-items: center; gap: 6px;
  flex-wrap: nowrap; min-width: 0;
}
.tbl--au .au-who__n {
  flex: 0 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tbl--au .au-role {
  flex: 0 0 auto; margin-left: 0; white-space: nowrap;
  line-height: 1.7;
}
/* 固定列宽后必须给「内容可能比列宽还长」的两列兜底，否则会溢出压到隔壁列：
   ① 对象列（手机号 / 邮箱，anyiisgodman@gmail.com 这种在 116px 列里放不下）
      —— 允许任意位置折行，信息完整优先，绝不横向溢出；
   ② 操作列的胶囊标签 —— 单行 nowrap，超长时自身省略号收缩（title 兜底全文），
      不允许它把右侧详情列顶开。 */
.tbl--au .au-obj {
  overflow-wrap: anywhere; word-break: break-word;
  line-height: 1.55;
}
.tbl--au .au-act {
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  vertical-align: top;
}
