/* =============================================================================
   Ozon → Yandex 采集刊登 ERP · 设计系统 v3
   -----------------------------------------------------------------------------
   设计原则
   1. 清晰优先：信息层级靠字重/字号/留白区分，不靠边框堆叠。
   2. 一致：所有页面共用同一套卡片、表格、表单、按钮与状态色。
   3. 高效：主操作固定在标题栏右侧；筛选在表格上方；分页在右下。
   4. 可预期：危险操作永远是红色、次要操作是描边、主操作是实心品牌色。
   5. 只做视觉：本文件不改变任何 id、事件与接口，仅重定义外观。

   字号阶梯（2026-10-25 评审 P1-2 收敛，原来有 9.5/10/10.5/11/11.5/12/12.5/13/13.5 共 9 档）
     14    正文
     13    控件文字（.btn / .chip / 输入框）
     12.5  表格正文、说明文字、次级信息（.data-table / .hint / .cell-gloss）
     11.5  标签、表头、徽标（.data-table th / .pill / .field > span）
     11    单位、序号等「不需要读」的极小字
   改字号请只用这五档，不要再造 10.5 / 12.2 这种中间值 —— 差 0.5px 肉眼分不出，只会让排版节奏散掉。
   ============================================================================= */

/* ================= 0. 字体 ================= */
/* Inter 自托管（不用 Google CDN：国内访问 fonts.gstatic.com 时快时慢，
   字体加载失败会退回系统字体，同一页在不同机器上长得不一样）。
   只下四片：latin / latin-ext / cyrillic / cyrillic-ext，合计 178KB。
   **必须带 cyrillic** —— 商品标题、参数名大量是俄文，缺了这片俄文字母会掉到
   系统西文字体上，跟中文混排时字重和 x-height 对不上，一眼就看出来。
   中文不嵌字体（Noto Sans SC 分片上百个、8MB 起），走系统栈。 */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url("/fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url("/fonts/inter-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4,
    U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url("/fonts/inter-cyrillic.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url("/fonts/inter-cyrillic-ext.woff2") format("woff2");
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}

/* ================= 1. 设计令牌 ================= */
/* 视觉语言：单证台（报关单 / 装箱单）。详见 设计系统-跨境电商风.html
   六个元素撑起辨识度：纸、墨、章、线、编号、条码。
   铁律：① 底色不用纯白，一用 #fff 就回到「屏幕」质感；
        ② 琥珀 #C97A0E 在纸面上只有 3.29:1，只做色条/图标/边框，文字一律用 --amber-text；
        ③ 琥珀底上不许放米白字（3.02:1），必须配墨字。 */
:root {
  /* 纸：暖白，不用纯白 */
  --bg: #f6f3ec;
  --bg-deep: #ede8de;
  --surface: #fffdf8;
  --surface-2: #f6f3ec;
  --surface-3: #ede8de;
  --border: #d9d2c3;
  --border-strong: #c4bca9;
  --rule: #d9d2c3;

  /* 墨与纸：单据语言的两个基础材料。
     踩过的坑：--ink / --paper-2 / --paper-3 先被用了、后才补定义，
     结果 var() 取不到值 → 整条声明失效（侧栏根本没变墨色、卡头墨条凭空消失，
     而且浏览器不报错，只在截图里看得出来）。新增令牌先定义再引用。
       --ink       骨架色：侧栏底、琥珀底上的字。两种模式下都恒为深墨，不翻转。
       --ink-rule  画在浅底上的墨线：顶栏下沿、卡头 3px、表头收口线。深色模式要提亮，否则线消失。
       --on-ink    墨底上的字色。
       --paper*    纸面 / 纸底 / 纸深三档，浅色下是暖白阶，深色模式整组翻暗。 */
  --ink: #0b2438;
  --ink-rule: #0b2438;
  --on-ink: #f2efe6;
  --paper: #fffdf8;
  --paper-2: #f6f3ec;
  --paper-3: #ede8de;

  /* 文本：墨三级 + 暖灰
     对比度（纸面 #FFFDF8）：--text 15.61 · --text-2 ~8.1 · --text-3 5.42 · --text-4 3.82(仅大字) */
  --text: #0b2438;
  --text-1: #12304a;
  --text-2: #33455a;
  --text-3: #5a6b78;
  --muted: #5a6b78;
  --text-4: #8a8071;

  /* 品牌：墨做骨架，琥珀做强调
     --primary 从靛蓝 #4f46e5 换成墨色：主按钮变墨底米白字（14.3:1），像单据上的签章位 */
  --primary: #0b2438;
  --primary-dark: #12304a;
  --primary-soft: #ede8de;
  --brand: #c97a0e;
  --brand-2: #e8a33d;
  --amber: #c97a0e;
  --amber-text: #8a5200;
  --amber-light: #e8a33d;
  --amber-soft: #fbf0dc;

  /* 语义色（纸面对比度）：ok 6.19 · bad 6.88 · warn 6.28 · info 6.89
     --warn 用深琥珀，因为它几乎只当文字色用；浅琥珀只出现在 --warn-soft 底上 */
  --ok: #2f6b4f;
  --ok-soft: #e6efe8;
  --bad: #a62b2b;
  --bad-soft: #f7e7e5;
  --warn: #8a5200;
  --warn-soft: #fbf0dc;
  --info: #2a5c8a;
  --info-soft: #e7eef5;

  /* 形状：近直角，工具感。16px → 3px，去掉大部分阴影（靠 1px 网格线分隔） */
  --radius: 3px;
  --radius-sm: 2px;
  --radius-xs: 2px;
  --shadow-xs: none;
  --shadow: none;
  --shadow-md: 0 2px 6px rgba(11, 36, 56, .06), 0 18px 40px -22px rgba(11, 36, 56, .28);
  --shadow-lg: 0 24px 70px -24px rgba(11, 36, 56, .32);
  --ring: 0 0 0 3px rgba(201, 122, 14, .22);

  /* 西文/数字走 Inter（自托管，见文件顶部 @font-face），中文走系统最清晰的那一层。
     中文顺序是有讲究的：
       PingFang SC       macOS / iOS，字形最匀；
       HarmonyOS Sans SC 华为系，随设备自带；
       MiSans            小米 / 部分国产系统；
       Microsoft YaHei UI Windows 8+ 的「UI 版本」，比 Microsoft YaHei 字面窄一档，
                         小字号下笔画更收得住 —— 老代码漏了它，14px 正文直接落到
                         YaHei，这是「看着不顺眼」的主要来源之一。
     西文一旦命中 Inter，后面的西文字体只在中文字体不覆盖该字符时才有机会 ——
     所以中文字体排在 Inter 之后是**对**的，不必担心中文盖掉 Inter。 */
  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text",
    "Segoe UI", "PingFang SC", "HarmonyOS Sans SC", "MiSans", "Hiragino Sans GB",
    "Microsoft YaHei UI", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans SC",
    sans-serif;
  /* 数字与编号统一走 Inter 的表格数字（tabular-nums）。
     原来这里打头是 JetBrains Mono，它的 0 中间带一个点 —— 金额 ¥0.00、
     订单数 0 上看着像沾了个脏点，跟 Inter 正文也不像一家人。Inter 与正文
     同源、0 是干净的椭圆，配 tabular-nums 照样逐列对齐。
     令牌因此从 --mono 改名 --num，别再往里塞等宽字体。 */
  --num: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text",
    "Segoe UI", "PingFang SC", "HarmonyOS Sans SC", "MiSans", "Hiragino Sans GB",
    "Microsoft YaHei UI", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans SC",
    sans-serif;
  /* 原来标题用宋体（Songti SC → SimSun）做「公文」辨识点。Windows 没有宋体粗体，
     20px/700 是浏览器伪粗，笔画发毛 —— 已改为无衬线，令牌留着免得别处引用失效。 */
  --serif: var(--sans);
  --sidebar-w: 240px;
  --ease: cubic-bezier(.22, .61, .36, 1);
}

* { box-sizing: border-box; }

/* hidden 属性必须真的隐藏。本文件里 .field / .card 这些类都设了 display，
   作者样式会盖掉浏览器默认的 [hidden] { display: none } —— 结果是「藏起来的」
   字段照样占着一块位置（踩过：细节图的「特写部位」hidden 是 true，页面上一直显示，
   只看 JS 里的 .hidden 值还查不出来）。 */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font: 14px/1.55 var(--sans);
  font-optical-sizing: auto;
  /* 全站数字用表格数字：金额/计数切换时不左右跳动，列也对得齐。
     Inter 支持 tnum，配合 --num 一起用（0 无点，跟正文同款）。 */
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

h1, h2, h3 { margin: 0; font-weight: 650; letter-spacing: -.01em; }
p { margin: 0; }
::selection { background: rgba(201, 122, 14, .22); }

/* 细滚动条：只在需要时出现，不抢视觉。颜色跟琥珀/纸走，不用冷灰 */
* { scrollbar-width: thin; scrollbar-color: #cfc7b6 transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb {
  background: #cfc7b6; border-radius: 2px; border: 3px solid transparent;
  background-clip: content-box;
}
*::-webkit-scrollbar-thumb:hover { background: #b8ae99; background-clip: content-box; }
*::-webkit-scrollbar-track { background: transparent; }

/* 焦点环用琥珀：这是全站唯一允许「亮」的地方，一眼能看到光标在哪 */
:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }

/* 通用文本工具类（表格金额、次要说明等高频使用） */
.mono { font-family: var(--num); font-variant-numeric: tabular-nums; }
.muted { color: var(--text-3); }
.brand { display: flex; align-items: center; gap: 11px; min-width: 0; }

/* ================= 2. 应用外壳 ================= */
.app-shell {
  display: flex;
  align-items: stretch;
  min-height: 100vh;
}

/* ---- 侧边栏 ---- */
.sidebar {
  flex: 0 0 var(--sidebar-w);
  width: var(--sidebar-w);
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 16px 14px 12px;
  /* 墨色侧栏：把内容区托起来，整屏立刻有「工具」的重量感。
     反白文字全部验过：#E8A33D on #0B2438 7.36:1、#9DB0BF 7.10:1、#F6F3EC 14.32:1 */
  background: var(--ink);
  border-right: 1px solid var(--ink);
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  z-index: 20;
}

.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 2px 4px 16px;
  margin-bottom: 6px;
  border-bottom: 1px solid rgba(246, 243, 236, .14);
  flex: 0 0 auto;
}
.brand-mark {
  width: 40px; height: 40px; border-radius: var(--radius-sm); flex: 0 0 auto;
  /* 琥珀底 + 墨字（4.74:1）：全站唯一允许「亮」的方块，一眼记住的点 */
  background: linear-gradient(160deg, #e8a33d 0%, #c97a0e 100%);
  color: var(--ink); font-weight: 800; letter-spacing: .4px;
  display: grid; place-items: center; font-size: 14px; font-family: var(--num);
  box-shadow: inset 0 1px 0 rgba(255, 253, 248, .35);
}
.brand-text { min-width: 0; }
.brand-text h1 { font-size: 14.5px; line-height: 1.25; white-space: nowrap; color: var(--on-ink); }
.brand-sub {
  margin: 2px 0 0; font-size: 11px; color: #9db0bf;
  white-space: nowrap; letter-spacing: .06em; font-family: var(--num);
}

/* 导航：图标用内联 SVG 掩膜，随文字颜色变化，不需要额外资源 */
.side-nav { display: flex; flex-direction: column; gap: 3px; flex: 1 1 auto; }
.side-nav button {
  --i: none;
  position: relative;
  display: flex; align-items: center; gap: 10px;
  width: 100%; text-align: left;
  border: 0; background: transparent; cursor: pointer;
  padding: 8px 11px; border-radius: var(--radius-sm);
  font-size: 12.5px; font-weight: 550; color: #9db0bf;
  font-family: inherit; line-height: 1.3;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.side-nav button::before {
  content: '';
  width: 17px; height: 17px; flex: 0 0 17px;
  background-color: currentColor;
  opacity: .68;
  -webkit-mask-image: var(--i);
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: center;
  -webkit-mask-size: 16px 16px;
  mask-image: var(--i);
  mask-repeat: no-repeat;
  mask-position: center;
  mask-size: 16px 16px;
  transition: opacity .15s var(--ease);
}
.side-nav button > .nav-badge { margin-left: auto; }
.side-nav button:hover { background: rgba(246, 243, 236, .07); color: var(--on-ink); }
.side-nav button:hover::before { opacity: .9; }
/* 当前页：左侧 3px 琥珀条 + 淡琥珀底 + 琥珀亮字（7.36:1）。
   比原来的圆角浅色高亮更利落，也更像单证上的「当前栏」标记 */
.side-nav button.active {
  background: rgba(232, 163, 61, .13);
  color: var(--amber-light);
  font-weight: 650;
  box-shadow: inset 3px 0 0 var(--amber-light);
}
.side-nav button.active::before { opacity: 1; }

/* 12 个页面图标（16×16 描边风格，统一线宽） */
.side-nav button[data-page="dashboard"] { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 11 12 4l9 7'/%3E%3Cpath d='M5 10v10h14V10'/%3E%3Cpath d='M10 20v-6h4v6'/%3E%3C/svg%3E"); }
.side-nav button[data-page="stores"] { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 20V9l8-5 8 5v11'/%3E%3Cpath d='M4 9h16'/%3E%3Cpath d='M9 20v-6h6v6'/%3E%3C/svg%3E"); }
.side-nav button[data-page="products"] { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3 3 8l9 5 9-5-9-5Z'/%3E%3Cpath d='M3 8v8l9 5 9-5V8'/%3E%3Cpath d='M12 13v8'/%3E%3C/svg%3E"); }
.side-nav button[data-page="orders"] { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 3h12v18l-3-2-3 2-3-2-3 2V3Z'/%3E%3Cpath d='M9 8h6M9 12h6M9 16h4'/%3E%3C/svg%3E"); }
.side-nav button[data-page="collectbox"] { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.5 5h15L21 13v6H3v-6l1.5-8Z'/%3E%3Cpath d='M3 13h5l1.5 2.5h5L16 13h5'/%3E%3C/svg%3E"); }
.side-nav button[data-page="profit"] { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 4v16h16'/%3E%3Cpath d='m8 15 3.5-4 3 2.5L20 7'/%3E%3Cpath d='M20 11V7h-4'/%3E%3C/svg%3E"); }
.side-nav button[data-page="favorites"] { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m12 4 2.4 4.9 5.4.8-3.9 3.8.9 5.4-4.8-2.5-4.8 2.5.9-5.4L4.2 9.7l5.4-.8L12 4Z'/%3E%3C/svg%3E"); }
/* AI 作图：相框 + 右上角四角星（星压在框外角上，像「图被 AI 处理过」）。
   原来这一项漏了 --i —— mask-image: none + background-color: currentColor 的结果是
   一个 17×17 纯琥珀方块，既不报错也不塌，所以一直没人发现（静态检查现在会拦这个，见 check_frontend.py）。
   造型上的三个决定：
   ① 星用 Q 曲线画凹边，直边四角星在 16px 下会糊成一个菱形色块；
   ② 框只占 12.4 单位、星放大到 4.6，让「AI」比「图」更抢眼 —— 这一项的本体是 AI；
   ③ 不画太阳、不做双山，16px 里第二座山会和星粘在一起（B/C 两版都试过，糊）。 */
.side-nav button[data-page="aiimage"] { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='6.2' width='12.4' height='12.4' rx='1.5'/%3E%3Cpath d='m3.6 16.2 3.4-3.4 2.8 2.6'/%3E%3Cpath d='M18.6 1 Q19.98 4.22 23.2 5.6 Q19.98 6.98 18.6 10.2 Q17.22 6.98 14 5.6 Q17.22 4.22 18.6 1 Z'/%3E%3C/svg%3E"); }
.side-nav button[data-page="records"] { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 7.5V12l3 2'/%3E%3Cpath d='M3.8 12a8.2 8.2 0 1 0 2.5-5.9'/%3E%3Cpath d='M3 4v4h4'/%3E%3C/svg%3E"); }
.side-nav button[data-page="credits"] { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='8.5'/%3E%3Cpath d='M14.5 9.2c-.6-.7-1.6-1.1-2.6-1.1-1.6 0-2.7.8-2.7 2s1.2 1.7 2.8 2c1.7.3 2.8.9 2.8 2.1s-1.2 2-2.9 2c-1.1 0-2.1-.4-2.7-1.2'/%3E%3Cpath d='M12 6v12'/%3E%3C/svg%3E"); }
.side-nav button[data-page="workbench"] { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4.5' width='18' height='12' rx='2'/%3E%3Cpath d='M9 20.5h6M12 16.5v4'/%3E%3Cpath d='m10.5 8.5 3.5 2-3.5 2v-4Z'/%3E%3C/svg%3E"); }
.side-nav button[data-page="billing"] { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='6.5' width='18' height='11' rx='2'/%3E%3Cpath d='M3 10.5h18'/%3E%3Cpath d='M7 14.5h3'/%3E%3C/svg%3E"); }
.side-nav button[data-page="downloads"] { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 4v10'/%3E%3Cpath d='m8 10.5 4 4 4-4'/%3E%3Cpath d='M5 19.5h14'/%3E%3C/svg%3E"); }
/* 成员管理：两个人形，一眼看出是「人」而不是「钱」 */
.side-nav button[data-page="team"] { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='9' cy='8' r='3.2'/%3E%3Cpath d='M3 20c0-3.3 2.7-5.4 6-5.4s6 2.1 6 5.4'/%3E%3Cpath d='M16.2 5.2a3.2 3.2 0 0 1 0 5.9'/%3E%3Cpath d='M17.6 14.9c2 .6 3.4 2.3 3.4 5.1'/%3E%3C/svg%3E"); }
/* 平台管理：三栋楼 —— 这里是「公司」，不是人（人已经给了成员管理） */
.side-nav button[data-page="platform"] { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 21V13h5.5v8'/%3E%3Cpath d='M8.5 21V4h7v17'/%3E%3Cpath d='M15.5 21v-6H21v6'/%3E%3Cpath d='M2.5 21h19'/%3E%3Cpath d='M11 8h2M11 12h2M11 16h2'/%3E%3C/svg%3E"); }

/* 数据大屏（独立页面入口，不是 data-page）：仪表盘造型。
   特意不用显示器轮廓 —— 采集工作台已经占了那个形状，
   两个一模一样的方框排在一起等于都没图标。 */
.side-nav button.nav-ext { --i: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.6 16.8a8.6 8.6 0 0 1 16.8 0'/%3E%3Cpath d='M12 16.8l4.2-5'/%3E%3Ccircle cx='12' cy='16.8' r='1.3'/%3E%3Cpath d='M3.6 20.4h16.8'/%3E%3C/svg%3E"); }

.nav-group {
  margin: 14px 0 5px; padding: 0 11px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .12em;
  color: #8fa3b2; text-transform: uppercase;
  font-family: var(--num);
}
.nav-group:first-of-type { margin-top: 8px; }

.nav-badge {
  font-style: normal; font-size: 11px; font-weight: 650;
  min-width: 20px; padding: 1px 6px; border-radius: var(--radius-sm);
  background: rgba(246, 243, 236, .1); border: 1px solid rgba(246, 243, 236, .13);
  color: #c8d5e0; text-align: center;
  font-variant-numeric: tabular-nums; font-family: var(--num);
}
.nav-badge.zero { color: #7e93a3; background: transparent; border-color: transparent; }
.side-nav button.active .nav-badge {
  background: var(--amber-light); color: var(--ink); border-color: var(--amber-light);
}

.sidebar-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 12px 4px 2px; border-top: 1px solid rgba(246, 243, 236, .14); margin-top: 10px;
  flex: 0 0 auto;
}
.sidebar-foot .hint { font-size: 11px; color: #8fa3b2; font-family: var(--num); }

/* ---- 主区与顶栏 ---- */
.main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }

.topbar {
  display: flex; align-items: center; justify-content: space-between; gap: 18px;
  padding: 11px 22px;
  /* 去掉毛玻璃：半透明 + blur 是「AI 感」的常见配料，也没有信息价值。
     单据抬头要的是一道实线，不是一层雾。 */
  background: var(--surface);
  border-bottom: 1.5px solid var(--ink-rule);
  position: sticky; top: 0; z-index: 30;
}
.topbar-left { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
/* 页面标题：原设计用宋体（Songti SC → SimSun）做「公文」辨识点，
   但 Windows 的 SimSun 没有真粗体，20px/700 是浏览器伪粗，笔画发毛发脏。
   改用无衬线 + 稍收紧字距，靠字重和下面的副标题拉开层级（--serif 已指向 --sans）。 */
.topbar-left h2 {
  position: relative;
  font-family: var(--serif);
  font-size: 20px; font-weight: 700; line-height: 1.25; letter-spacing: -.01em;
  white-space: nowrap;
}
.page-sub { margin: 0; font-size: 12px; color: var(--text-3); white-space: nowrap; font-family: var(--num); letter-spacing: .01em; }
.topbar-right { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; }
/* 汇率条：跨境卖家的第一信息，原来藏在「订单核算」页里。
   提到顶栏常驻 —— 它既是实用信息，也是「这软件是做跨境的」最直接的一块招牌。
   墨底等宽，是顶栏唯一的深色块，视觉上自动成为落点。 */
.fxbar {
  display: inline-flex; align-items: stretch;
  background: var(--ink); color: var(--on-ink);
  border-radius: var(--radius-sm); overflow: hidden;
  font-family: var(--num); font-size: 11px;
  height: 26px; flex: 0 0 auto;
}
.fxbar > span {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 0 9px; border-right: 1px solid rgba(246, 243, 236, .16);
  white-space: nowrap;
}
.fxbar > span:last-child { border-right: 0; }
.fxbar .lbl { color: #8fa3b2; font-size: 9.5px; letter-spacing: .08em; }
.fxbar b { color: var(--on-ink); font-weight: 700; font-variant-numeric: tabular-nums; }
.fxbar .fx-live { color: var(--amber-light); }
.topbar-right .btn { height: 34px; padding: 0 13px; font-size: 12.5px; }
/* 顶栏是「轻操作区」：默认无边框，hover 才浮出底色，减少视觉噪音 */
.topbar-right .btn-ghost { border-color: transparent; background: transparent; box-shadow: none; }
.topbar-right .btn-ghost:hover:not(:disabled) {
  background: var(--surface-3); border-color: transparent; color: var(--text);
}

/* 环境指示灯：用最轻的方式表达「系统是否就绪」 */
.env-dots {
  display: flex; gap: 7px; padding: 6px 10px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.env-dots .dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--border-strong); display: block; cursor: help;
  transition: box-shadow .2s;
}
.env-dots .dot.ok { background: var(--ok); box-shadow: 0 0 0 3px rgba(5, 150, 105, .14); }
.env-dots .dot.bad { background: var(--bad); box-shadow: 0 0 0 3px rgba(220, 38, 38, .14); }

.mode-switch {
  display: inline-flex; gap: 2px; padding: 3px;
  background: var(--surface-3); border: 1px solid var(--border);
  border-radius: var(--radius);
}
.mode-switch button {
  border: 0; background: transparent; padding: 5px 12px; border-radius: var(--radius);
  font-size: 12.5px; color: var(--text-2); cursor: pointer; font-weight: 550;
  font-family: inherit;
  transition: background .15s, color .15s, box-shadow .15s;
}
.mode-switch button:hover { color: var(--text); }
.mode-switch button.active {
  background: var(--primary); color: var(--surface); font-weight: 650;
}

/* ---- 页面容器 ---- */
/* 去掉了原来两层紫色径向光斑（rgba(99,102,241) / rgba(124,58,237)）——
   那是「AI 生成界面」最典型的一笔：背景发光但没有来源。
   单证风里背景就该是纸，干净、均匀，靠 1px 网格线分区。 */
.page-host {
  flex: 1 1 auto;
  width: 100%;
  max-width: 1680px;
  margin: 0 auto;
  padding: 16px 20px 40px;
  background: var(--bg);
}
.page { display: none; flex-direction: column; gap: 16px; }
.page.active { display: flex; animation: page-in .22s var(--ease); }
@keyframes page-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

/* ================= 3. 栅格与统计 ================= */
/* 统计条：不再是「一排大白卡」，而是一条连续的摘要带。
   做法是 gap:1px + 容器底色为边框色 —— 格子之间的 1px 缝隙自然露出来当分隔线，
   不用 :nth-child 判断行首，换行也不会错位。 */
.grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; align-items: start; }
.stat-grid, .stat-grid-3, .stat-grid-4, .stat-grid-6 {
  display: grid; gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.stat-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.stat-grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
/* 【评审 P0-1】原来 .stat-grid-6 是死 6 列：订单页 8 张卡排成 6+2，右边空出 4 格；
   ≤1440 又变 3 列，成 3+3+2 更碎。改成自适应：卡片数不是 6 的倍数也不会留洞。
   但订单页仍在标记上拆成「待办 4 / 结果 4」两组，语义上也分得清（见 index.html）。 */
.stat-grid-6 { grid-template-columns: repeat(auto-fit, minmax(172px, 1fr)); }

/* 一组统计卡 + 组标题：把 8 张拆成两排后，每排说清自己是什么 */
.stat-group { display: flex; flex-direction: column; gap: 6px; }
.stat-group-label {
  font-size: 10.5px; font-weight: 700; letter-spacing: .12em; color: var(--text-3);
  text-transform: uppercase; padding-left: 1px; font-family: var(--num);
}

.stat {
  position: relative;
  background: var(--surface);
  border: 0;
  border-radius: 0;
  padding: 11px 13px 12px;
  box-shadow: none;
  overflow: hidden;
  transition: background .14s var(--ease);
}
/* 去掉顶部渐变条：那是「每张卡都发一点光」的思路，8 张一起就是噪音 */
.stat::after { content: none; }
.stat:hover { background: var(--paper-2); }
.stat span {
  display: block; font-size: 10.5px; font-weight: 700; color: var(--text-3);
  letter-spacing: .1em; text-transform: uppercase; font-family: var(--num);
}
.stat b {
  display: block; margin-top: 2px;
  font-size: 21px; font-weight: 700; letter-spacing: -.02em; line-height: 1.16;
  color: var(--text); font-variant-numeric: tabular-nums; font-family: var(--num);
}

/* 【评审 P2-4】采集箱原来把三个数写成一句彩色文字（待补全 0 · 已补全 1 · 人工改过 3），
   数字不显眼、点不了。改成三张紧凑统计卡，卡片本身就是筛选入口（等价于点工具栏那个下拉）。 */
.stat-sm { padding: 11px 13px 12px; border-radius: 0; }
.stat-sm b { font-size: 18px; margin-top: 1px; }
.stat-link {
  display: block; width: 100%; text-align: left; font-family: inherit; cursor: pointer;
  background: var(--surface); border: 0; color: inherit;
}
.stat-link:hover { background: var(--paper-2); }
/* 选中态：浅琥珀底 + 左侧 3px 琥珀条，和侧栏当前项同一套语言 */
.stat-link.on { background: var(--amber-soft); box-shadow: inset 3px 0 0 var(--amber); }
.stat-sm.warn b { color: var(--amber-text); }
.stat-sm.ok b { color: var(--ok); }

/* 键值表：右侧对齐、虚线分隔，扫读更快 */
.kv-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 22px; }
.kv {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 9px 0; border-bottom: 1px dashed var(--border);
}
.kv:nth-last-child(-n+2) { border-bottom: 0; }
.kv span { font-size: 12.5px; color: var(--text-3); flex: 0 0 auto; }
.kv b {
  font-size: 13px; font-weight: 620; text-align: right;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* 账号操作条目 */
.op-row { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.op-item {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 11px 13px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-2);
  transition: border-color .15s, background .15s;
}
.op-item:hover { border-color: #dbe2ef; background: var(--surface); }
.op-item > div:first-child { min-width: 0; }
.op-item b { font-size: 12.5px; font-weight: 620; }
.op-item small { display: block; margin-top: 2px; font-size: 12.5px; color: var(--text-3); }
.inline-form { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.inline-form input { width: 138px; }
.default-freight-flag { color: var(--primary); font-weight: 700; }

/* ================= 4. 卡片与分组 ================= */
.card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  /* 单据抬头：顶部 3px 墨条。一页里每张卡都有，形成规则的节奏 —— 这是「单证台」的核心识别点 */
  border-top: 3px solid var(--ink-rule);
  border-radius: var(--radius);
  box-shadow: none;
  padding: 13px 15px 16px;
}
.card-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 11px; min-height: 26px;
}
.card-head h2 {
  font-size: 13px; font-weight: 700; letter-spacing: .02em;
  display: flex; align-items: center; gap: 9px;
}
/* 卡头右侧动作区
   【评审 P0-6】原来允许自由换行：商品管理里店铺下拉占满一整行（实测 368px），
   主按钮被挤到第二行、压在 KPI 卡边线上，卡头高 82px。
   现在默认不换行 + 给下拉封顶宽度，主按钮永远和标题同一行；窄屏（≤1180）再允许换行。 */
.card-head-actions { display: flex; gap: 8px; flex-wrap: nowrap; justify-content: flex-end; align-items: center; }
.card-head-actions select { min-width: 0; max-width: 210px; }
.card-head-actions .btn { flex: 0 0 auto; }

.step-no {
  width: 24px; height: 24px; border-radius: var(--radius); flex: 0 0 auto;
  background: var(--primary-soft); color: var(--primary);
  font-size: 12.5px; font-weight: 700; display: grid; place-items: center;
  box-shadow: inset 0 0 0 1px rgba(201, 122, 14, .16);
}

.advanced { padding-bottom: 8px; }
.adv-group { padding: 14px 0 8px; border-top: 1px dashed var(--border); }
.adv-group:first-of-type { border-top: 0; padding-top: 4px; }
.adv-group h3 {
  font-size: 11.5px; color: var(--text-3); font-weight: 700;
  letter-spacing: .08em; margin-bottom: 10px; text-transform: uppercase;
}

/* ================= 4b. 首页「实时数据」 ================= */
/* 一条横向的实时带：五格数字用 1px 拼缝连成一张单据（和统计条同一套做法），
   左对齐的等宽数字便于竖着比大小。 */
.rt-card .card-head { margin-bottom: 10px; }
.rt-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.rt-cell {
  background: var(--surface);
  padding: 13px 15px 14px;
  min-width: 0;
}
.rt-label {
  display: block;
  font-size: 10.5px; font-weight: 700; color: var(--text-3);
  letter-spacing: .1em; text-transform: uppercase; font-family: var(--num);
}
.rt-value {
  display: block; margin-top: 4px;
  font-family: var(--num); font-size: 26px; font-weight: 700;
  letter-spacing: -.02em; line-height: 1.1; color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 销售额格子里数字长（¥19,140.51），比订单数那两格收一点，五格才等宽不挤出省略号 */
.rt-cell:nth-child(1) .rt-value,
.rt-cell:nth-child(2) .rt-value { font-size: 23px; }
.rt-delta {
  display: block; margin-top: 5px;
  font-size: 11.5px; color: var(--text-4);
  font-family: var(--num); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
/* 涨绿跌红，和 Yandex 卖家后台的实时数据一致（跨境电商行业惯例，不是股市的红涨绿跌） */
.rt-up { color: var(--ok); }
.rt-down { color: var(--bad); }
.rt-flat { color: var(--text-4); }
.rt-foot {
  margin: 9px 0 0; font-size: 11.5px; color: var(--text-4); line-height: 1.5;
}
.rt-foot-warn { color: var(--amber-text); }

/* 首页右卡下方的四个入口：2×2 的方块，把半栏的空白填实
   （左卡账号信息高，右卡只放四格统计会剩一大片空） */
.quick-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
/* 服务方入口单独占满一行：2 列格里多出来的第 5 块会孤零零挂半格，看着像没排完 */
.quick-row .quick-item[data-platform] { grid-column: 1 / -1; }
.quick-item {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  padding: 9px 11px; text-align: left; font: inherit; color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color .15s var(--ease), background .15s var(--ease);
}
.quick-item:hover { border-color: var(--border-strong); background: var(--paper-2); }
.quick-item b { font-size: 12.5px; font-weight: 650; color: var(--text); }
.quick-item small { font-size: 11px; color: var(--text-4); }

/* 「实时」那两个字的呼吸点：不做动画就是一个普通项目符号 */
.rt-dot {
  width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto;
  background: var(--ok); box-shadow: 0 0 0 3px rgba(47, 107, 79, .14);
  animation: rt-pulse 2.4s ease-in-out infinite;
}
@keyframes rt-pulse {
  0%, 100% { opacity: 1; box-shadow: 0 0 0 3px rgba(47, 107, 79, .14); }
  50% { opacity: .55; box-shadow: 0 0 0 5px rgba(47, 107, 79, .04); }
}
@media (prefers-reduced-motion: reduce) {
  .rt-dot { animation: none; }
}

/* ================= 4c. 物流模板（弹窗内列表） ================= */
.logi-existing {
  margin-bottom: 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-2);
  overflow: hidden;
}
.logi-existing-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding: 7px 11px;
  border-bottom: 1px solid var(--border);
  font-size: 10.5px; font-weight: 700; letter-spacing: .1em;
  color: var(--text-3); text-transform: uppercase; font-family: var(--num);
}
.logi-list { max-height: 172px; overflow-y: auto; }
.logi-list .hint { margin: 0; padding: 11px 12px; font-size: 12px; }
.logi-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 11px;
  border-bottom: 1px dashed var(--border);
}
.logi-row:last-child { border-bottom: 0; }
.logi-row-main { min-width: 0; }
.logi-row-main b { font-size: 12.5px; color: var(--text); }
.logi-row-main .pill { margin-left: 6px; }
.logi-row-main small {
  display: block; margin-top: 2px;
  font-size: 11px; color: var(--text-4);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.logi-row-ops { display: flex; gap: 4px; flex: 0 0 auto; }

/* ================= 5. 按钮与标签 ================= */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 36px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text-1);
  border-radius: var(--radius-sm);
  padding: 0 14px;
  font-size: 13px; font-weight: 560;
  cursor: pointer; font-family: inherit; white-space: nowrap;
  box-shadow: var(--shadow-xs);
  transition: background .15s var(--ease), border-color .15s var(--ease),
              box-shadow .15s var(--ease), transform .06s, opacity .15s;
}
.btn:hover:not(:disabled) { background: var(--surface-2); border-color: #cdc4b0; }
.btn:active:not(:disabled) { transform: translateY(1px); box-shadow: none; }
.btn:disabled { opacity: .45; cursor: not-allowed; box-shadow: none; }

.btn-primary {
  /* 用令牌而不是写死墨色：深色模式下 --primary 会翻成琥珀，
     墨底墨字在深夜背景上等于隐身（踩过：深色下「同步订单」直接看不见） */
  background: linear-gradient(180deg, var(--primary-dark) 0%, var(--primary) 100%);
  border-color: var(--primary); color: var(--surface); font-weight: 600;
  /* 内高光：主按钮唯一的「立体感」来源，替代原来的大面积投影 */
  box-shadow: inset 0 1px 0 rgba(255, 253, 248, .16), 0 1px 2px rgba(11, 36, 56, .18);
}
.btn-primary:hover:not(:disabled) {
  background: linear-gradient(180deg, var(--primary) 0%, var(--primary-dark) 100%);
  border-color: var(--primary-dark);
}
.btn-danger { background: var(--bad-soft); border-color: #dfc2be; color: #a62b2b; }
.btn-danger:hover:not(:disabled) { background: #f2dbd8; border-color: var(--bad); }
.btn-warn { background: var(--warn-soft); border-color: #e5cda2; color: #8a5200; }
.btn-warn:hover:not(:disabled) { background: #f7e6c8; border-color: var(--warn); }
.btn-ghost { background: transparent; border-color: var(--border); color: var(--text-2); box-shadow: none; }
.btn-ghost:hover:not(:disabled) { background: var(--surface-3); color: var(--text-1); border-color: var(--border-strong); }

/* 【评审 P0-3】危险操作降级：原来「删除选中 / 清空清单」用的是 .btn-danger（浅红底+红字描边），
   跟普通按钮同尺寸同位置，和「上传店铺」并排时完全分不出主次，而且 4 个页面各放一次。
   现在危险操作统一走「透明底 + 红字 + 悬停才显红底」，并用 margin-left:auto 推到工具栏最右。
   功能不变（同一个 id、同一个点击事件），只是不再抢视觉。 */
.btn-ghost.danger { color: var(--bad); border-color: var(--border); }
.btn-ghost.danger:hover:not(:disabled) { background: var(--bad-soft); border-color: #f3c4c4; color: var(--bad); }
.btn-ghost.danger:disabled { color: var(--text-3); }

/* 【评审 P1-3】把长说明收进「?」：原生 title 悬停即看，不引入新交互、不占版面 */
.help-dot {
  display: inline-grid; place-items: center;
  width: 18px; height: 18px; border-radius: 50%;
  border: 1px solid var(--border-strong); background: var(--surface);
  color: var(--text-3); font-size: 11.5px; font-weight: 700; line-height: 1;
  cursor: help; padding: 0; font-family: inherit; margin-left: 6px;
  vertical-align: 1px;
}
.help-dot:hover { border-color: var(--primary); color: var(--primary); background: var(--primary-soft); }

.btn-xs { min-height: 26px; padding: 0 8px; font-size: 12px; border-radius: var(--radius-sm); gap: 4px; }
.btn-lg { min-height: 44px; padding: 0 24px; font-size: 14px; border-radius: var(--radius); }
.btn-block { width: 100%; }

.link-btn {
  margin: 0; padding: 0; border: 0; background: none;
  font: inherit; font-size: 12.5px; color: var(--primary);
  text-decoration: underline; text-underline-offset: 2px; cursor: pointer;
}
.link-btn:hover { color: var(--primary-dark); }

.chip-row { display: flex; flex-wrap: wrap; gap: 5px; margin: 8px 0 10px; }
.chip {
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text-2); padding: 3px 10px; border-radius: var(--radius-sm);
  font-size: 12px; font-weight: 550; cursor: pointer; font-family: inherit;
  transition: background .15s, color .15s, border-color .15s;
}
.chip:hover { background: var(--amber-soft); border-color: #e5cda2; color: var(--amber-text); }
/* 选中态用 --primary 而不是 --ink：深色模式下 --primary 会翻成琥珀，
   而写死墨底 + --surface 字就等于墨底墨字，选中项直接隐身。 */
.chip-active { background: var(--primary); border-color: var(--primary); color: var(--surface); }

/* ================= 6. 状态药丸 ================= */
/* 状态 = 盖章。原来是 999px 圆角胶囊 + 小圆点，是消费级 App 的语言；
   单证上盖的是方章：矩形、左侧 3px 实色条、等宽字。 */
.pill {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 1px 7px 1px 9px; border-radius: var(--radius-sm);
  font-size: 10.5px; font-weight: 700; white-space: nowrap;
  background: var(--surface-3); border: 1px solid var(--border); color: var(--text-2);
  letter-spacing: .03em; font-family: var(--num);
  box-shadow: inset 3px 0 0 currentColor;
}
.pill::before { content: none; }
.pill-ok { background: var(--ok-soft); border-color: #b8cfc0; color: #2f6b4f; }
.pill-active { background: var(--ok-soft); border-color: #a9c7b4; color: #2f6b4f; }
/* 进行中（处理中 / 配送中 / 待付款）：蓝色表示「还在流程里」，和绿/灰区分 */
.pill-pending { background: var(--info-soft); border-color: #bfd0e0; color: #2a5c8a; }
.pill-failed { background: var(--bad-soft); border-color: #dfc2be; color: #a62b2b; }
.pill-out { background: var(--warn-soft); border-color: #e5cda2; color: #8a5200; }
.pill-skipped { background: var(--surface-3); border-color: var(--border); color: var(--text-3); }
.pill-returned { background: var(--bad-soft); border-color: #dfc2be; color: #a62b2b; font-weight: 700; }
.row-returned td { background: #faf0ee; }

/* 采集来源标签（1688 / 拼多多 / Yandex）。
   Ozon 是默认来源不挂标签 —— 574 行里 500 多行都是 Ozon，挂满一屏等于噪音。
   形状跟 .pill 一致（单证上的方章 + 左侧实色条），只是更小、更淡，
   因为它挂在标题前面，占的是正文的位置。 */
.src-pill {
  display: inline-block; vertical-align: 1.5px;
  margin-right: 6px; padding: 0 5px 0 6px;
  font-size: 10px; font-weight: 700; line-height: 15px;
  border-radius: var(--radius-sm); white-space: nowrap;
  border: 1px solid var(--border); background: var(--surface-3);
  color: var(--text-2); font-family: var(--num); letter-spacing: .02em;
  box-shadow: inset 2px 0 0 currentColor;
}
.src-pill.p-1688 { background: var(--warn-soft); border-color: #e5cda2; color: #8a5200; }
.src-pill.p-pdd { background: var(--bad-soft); border-color: #dfc2be; color: #a62b2b; }
.src-pill.p-yandex { background: var(--info-soft); border-color: #bfd0e0; color: #2a5c8a; }
.row-returned td:first-child { box-shadow: inset 3px 0 0 #a62b2b; }
.row-cancelled td { background: var(--surface-3); }
.row-cancelled td:first-child { box-shadow: inset 3px 0 0 #9aa3b2; }
.order-flag-banner { padding: 9px 12px; border-radius: var(--radius-sm); font-size: 12.5px; margin: 0 0 12px; line-height: 1.5; }
.order-flag-returned { background: var(--bad-soft); border: 1px solid #dfc2be; color: #a62b2b; }
.order-flag-cancelled { background: var(--surface-3); border: 1px solid var(--border); color: var(--text-3); }
.pill-upload { margin-left: 4px; background: var(--info-soft); border-color: #bfd0e0; color: #2a5c8a; }

.badge {
  font-size: 10.5px; padding: 1px 7px; border-radius: var(--radius-sm); flex: 0 0 auto;
  background: var(--surface-3); color: var(--text-2); font-weight: 700;
  font-variant-numeric: tabular-nums; font-family: var(--num);
  border: 1px solid var(--border);
}
.badge.running { background: var(--primary-soft); color: var(--primary-dark); }
.badge.done { background: var(--ok-soft); color: #2f6b4f; }
.badge.failed, .badge.cancelled { background: var(--bad-soft); color: #a62b2b; }
.badge.idle { background: var(--surface-3); color: var(--text-3); }

.count-badge {
  font-style: normal; font-size: 11px; font-weight: 700;
  background: var(--primary); color: #fff;
  border-radius: var(--radius-sm); padding: 1px 6px; margin-left: 4px;
  font-variant-numeric: tabular-nums;
}
.count-badge.zero { background: var(--border-strong); color: #fff; opacity: .7; }

/* ================= 7. 表单 ================= */
.form-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
.field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.field > span {
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
  font-size: 12.5px; color: var(--text-2); font-weight: 600; letter-spacing: .01em;
}
.field small { font-size: 11px; color: var(--text-3); line-height: 1.4; }
.field-wide { grid-column: 1 / -1; }
.field-input { position: relative; }
.field-input .unit {
  position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
  font-size: 11.5px; color: var(--text-3); font-style: normal; pointer-events: none;
}
.field-input input { padding-right: 34px; }

/* 用 :where() 把基础样式的特异性降为 0：
   这样表格里的 .stock-input / .profit-cost / .box-inline 等类可以正常覆盖宽度，
   不会再被 input[type="number"]{width:100%} 顶成整格宽。 */
:where(textarea, input:not([type]), input[type="text"], input[type="number"], input[type="search"],
input[type="password"], input[type="date"], select) {
  width: 100%;
  min-height: 34px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  border-radius: var(--radius-sm);
  padding: 6px 9px;
  font-size: 13px;
  color: var(--text);
  font-family: inherit;
  transition: border-color .15s, box-shadow .15s, background .15s;
}
input::placeholder, textarea::placeholder { color: #a09582; }
/* 描述/参数是给运营读的正文，用正文字体更易读；URL 这类走 .mono 单独指定 */
textarea {
  resize: vertical; min-height: 84px;
  font-family: inherit; font-size: 12.5px; line-height: 1.68;
}
select {
  appearance: none; -webkit-appearance: none;
  padding-right: 32px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  cursor: pointer;
}
/* 数据表格里的数字框不需要原生上下箭头：它会吃掉约 15px，窄格里数字就被裁掉了 */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none; margin: 0;
}
input[type="number"] { -moz-appearance: textfield; }

/* 焦点用琥珀描边，不用原来的靛蓝光圈：琥珀是全站唯一的「亮」，
   出现在哪里就说明光标在哪里，不会和品牌色抢 */
textarea:focus, input:focus, select:focus {
  outline: 0; border-color: var(--amber);
  box-shadow: 0 0 0 2px rgba(201, 122, 14, .18);
}
input[type="checkbox"], input[type="radio"] { accent-color: var(--amber); width: 15px; height: 15px; }

/* 开关行 */
.switch-line {
  display: flex; align-items: center; gap: 8px;
  font-size: 12.5px; color: var(--text-2); cursor: pointer;
  min-height: 32px;
}
.switch-line input { width: 15px; height: 15px; flex: 0 0 auto; }
.field-wide.switch-line { grid-column: 1 / -1; }

.field-hint {
  grid-column: 1 / -1; margin: -4px 0 0;
  font-size: 12.5px; line-height: 1.65; color: var(--text-3);
}
.field-hint.warn { color: var(--warn); }
.field-hint.ok { color: var(--ok); }
.hint { font-size: 12.5px; color: var(--text-3); line-height: 1.55; }
.hint-row { display: flex; justify-content: space-between; gap: 10px; margin-top: 8px; flex-wrap: wrap; }
.hidden { display: none !important; }

/* 说明块 / 公式块 */
.modal-tip {
  margin: 0; padding: 11px 13px;
  background: linear-gradient(180deg, #fffdf8, #f6f3ec);
  border: 1px solid #dfe5fb; border-radius: var(--radius);
  font-size: 12.5px; line-height: 1.7; color: #3f4a86;
}
.modal-tip b { color: var(--primary-dark); }
.price-formula {
  margin-top: 12px; padding: 11px 13px;
  background: var(--surface-2); border: 1px dashed var(--border-strong);
  border-radius: var(--radius);
  font-size: 12.5px; color: var(--text-2); font-family: var(--num); line-height: 1.75;
  white-space: pre-wrap;
}
.guide-box {
  margin-bottom: 14px; padding: 13px 15px;
  background: linear-gradient(180deg, #fffdf8, #f6f3ec);
  border: 1px solid #e0e6fb; border-radius: var(--radius);
  font-size: 12.5px; color: #3f4a86;
}
.guide-box b { font-size: 12.5px; }
.guide-box ol { margin: 8px 0 6px; padding-left: 20px; line-height: 1.85; }
.guide-box code {
  background: #fff; border: 1px solid #e3e8f7; border-radius: 5px;
  padding: 1px 5px; font-family: var(--num); font-size: 12.5px; color: #453f8a;
}
.guide-box .hint { color: #5b6699; }

/* 公告 */
.notice-list { display: flex; flex-direction: column; gap: 9px; }
.notice {
  border: 1px solid var(--border); border-left: 3px solid var(--primary);
  border-radius: var(--radius); background: var(--surface-2); padding: 11px 13px;
}
.notice.lv-warn { border-left-color: var(--warn); background: var(--warn-soft); }
.notice.lv-error { border-left-color: var(--bad); background: var(--bad-soft); }
.notice-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.notice-head b { font-size: 12.5px; }
.notice p { margin: 5px 0 0; font-size: 12.5px; color: var(--text-2); white-space: pre-wrap; }
.notice-ops { display: flex; gap: 6px; flex: 0 0 auto; }

/* 套餐卡 */
.plan-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
.plan-card {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); padding: 16px;
  display: flex; flex-direction: column; gap: 8px;
  transition: border-color .15s, box-shadow .15s, transform .15s;
}
.plan-card:hover { border-color: #d7deec; box-shadow: var(--shadow); transform: translateY(-1px); }
.plan-card.current {
  border-color: rgba(201, 122, 14, .55);
  box-shadow: 0 0 0 4px rgba(79, 70, 229, .07);
}
.plan-card h3 { font-size: 14.5px; }
.plan-price { font-size: 24px; font-weight: 720; letter-spacing: -.03em; }
.plan-credits { font-size: 12.5px; color: var(--text-2); }
.plan-card ul { margin: 0; padding-left: 16px; font-size: 12.5px; color: var(--text-2); line-height: 1.8; }

/* 下载卡 */
.dl-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.dl-card {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-2); padding: 15px;
  display: flex; flex-direction: column; gap: 8px;
  transition: background .15s, border-color .15s;
}
.dl-card:hover { background: var(--surface); border-color: #dbe2ef; }
.dl-card b { font-size: 13px; }
.dl-card p { margin: 0; font-size: 12.5px; color: var(--text-2); line-height: 1.6; }

/* 流程条 */
.flow-row { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.flow-step {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 13px; border-radius: var(--radius-sm);
  background: var(--surface-2); border: 1px solid var(--border);
  font-size: 12.5px; font-weight: 600;
}
.flow-step i {
  font-style: normal; width: 18px; height: 18px; border-radius: 50%;
  background: var(--primary); color: #fff; font-size: 11px; font-weight: 700;
  display: grid; place-items: center;
}
.flow-arrow { color: var(--text-3); font-size: 13px; }

/* ================= 8. 表格 ================= */
/* ---- 跨境标记：币种小签 + 平台徽标 ----
   为什么不用纯文字：
   ① 币种。数字列里 "RUB" 三个字母没有形状，扫表时几乎读不到，也分不清这列到底是
      卢布还是人民币（采购价是 ₽、售价是 ¥，混着看最容易看反）。换成「符号 + 代码」的小签，
      ₽ / ¥ 一眼分得开，同时给每一行都带上「这是跨境单」的记号。
      三档底色是语义色，不是装饰：卢布=琥珀（要换算的那个）、人民币=通关绿（结算口径）、
      美元/欧元=运单蓝。字色全部用对应的深色档，底色只做区分。
   ② 平台。Ozon 官方蓝 #005BFF、Yandex 官方黄 #FFCC00，印在卡头当「抬头章」。
      字色按对比度选：白 on #005BFF 5.0:1、墨 on #FFCC00 11.5:1 —— 都不靠感觉。 */
.cur {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 48px; height: 18px; padding: 0 5px;
  border: 1px solid var(--border); border-radius: var(--radius-xs);
  background: var(--surface-2); color: var(--text-3);
  font: 500 10px/1 var(--num); font-style: normal;
  letter-spacing: .04em; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.cur-rub { background: var(--amber-soft); border-color: #e8cfa4; color: var(--amber-text); }
.cur-cny { background: var(--ok-soft); border-color: #bcd3c6; color: var(--ok); }
.cur-usd, .cur-eur { background: var(--info-soft); border-color: #bfd0e0; color: var(--info); }

.plat {
  display: inline-grid; place-items: center; flex: 0 0 auto;
  width: 20px; height: 20px; border-radius: var(--radius-xs);
  font: 800 11px/1 var(--num); font-style: normal;
  letter-spacing: 0; text-transform: none;
}
.plat-oz { background: #005bff; color: #fffdf8; }
.plat-yz { background: #ffcc00; color: #0b2438; }

/* ---- 表格通用 ---- */
.table-wrap {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: auto;
  max-height: calc(100vh - 250px);
  background: var(--surface);
}
.table-flat { max-height: none; border: 0; border-radius: 0; }

.data-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 12.5px; }
/* 表头：纸深底 + 1.5px 墨线收口，等宽大写。
   原来底部是 1px 浅灰，跟表体的行线同强度，表头和表体分不开。 */
.data-table th {
  position: sticky; top: 0; z-index: 2;
  background: var(--paper-3);
  color: var(--text-3); font-weight: 700;
  text-align: left; padding: 7px 9px;
  border-bottom: 1.5px solid var(--ink-rule);
  white-space: nowrap; font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase;
  font-family: var(--num);
}
/* 表头自动编号：像报关单的栏目号（01 02 03…）。
   用 CSS 计数器生成，不动一行 HTML —— 加一列、删一列都不用维护编号。
   首列（勾选框 / 缩略图）跳过：那列本来就窄，塞个 01 会和控件挤在一起。 */
.data-table thead tr { counter-reset: col; }
.data-table thead th::before {
  counter-increment: col;
  content: counter(col, decimal-leading-zero);
  font-size: 9px; font-weight: 500; opacity: .5;
  margin-right: 5px; letter-spacing: 0;
}
.data-table thead th:first-child::before { content: none; counter-increment: none; }
.data-table td {
  padding: 6px 9px; border-bottom: 1px solid var(--rule);
  vertical-align: middle; color: var(--text-1); line-height: 1.42;
}
.data-table tbody tr:last-child td { border-bottom: 0; }
.data-table tbody tr {
  transition: background .12s var(--ease);
  position: relative;
}
.data-table tbody tr:hover { background: #f9f5ec; }
.data-table tbody tr:hover td:first-child { box-shadow: inset 2px 0 0 rgba(201, 122, 14, .55); }
.data-table td a { color: var(--primary); text-decoration: none; }
.data-table td a:hover { text-decoration: underline; }
/* 表格里的操作按钮：给一个可见描边，避免被误认成普通文字 */
.data-table .btn-ghost { border-color: var(--border); background: var(--surface); }
.data-table .btn-ghost:hover:not(:disabled) { border-color: var(--border-strong); }
.data-table .num {
  text-align: right; font-variant-numeric: tabular-nums; font-family: var(--num);
  font-size: 12.5px; white-space: nowrap;
}
/* offerId / 时间这类编号必须单行显示：折成三行会把整张表的行高撑爆 */
.data-table td.mono {
  white-space: nowrap; font-family: var(--num);
  font-size: 12.5px; letter-spacing: -.01em;
}
.data-table td:has(.listing-check) { text-align: center; }
.listing-check { width: 16px; height: 16px; }

.empty-row td {
  text-align: center; color: var(--text-3); padding: 46px 12px;
  font-size: 12.5px;
}
.empty-row td::before {
  content: ''; display: block; width: 34px; height: 34px; margin: 0 auto 10px;
  border-radius: var(--radius); border: 1.5px dashed var(--border-strong);
  background: var(--surface-2);
}

.cell-title {
  font-weight: 560; display: block; max-width: 320px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cell-gloss {
  color: var(--text-3); font-size: 11.5px; display: block;
  max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.thumb {
  width: 38px; height: 38px; border-radius: var(--radius); object-fit: cover;
  border: 1px solid var(--border); background: var(--surface-2); display: block;
}
.thumb-ph {
  display: grid; place-items: center; color: var(--text-3); font-size: 11px;
  width: 38px; height: 38px; border-radius: var(--radius); background: var(--surface-3);
}
.thumb-lg { width: 64px; height: 64px; }
/* 订单列表：首图 + 多 SKU 角标 */
.thumb-wrap { position: relative; display: inline-block; line-height: 0; }
.thumb-wrap .thumb { cursor: zoom-in; transition: transform .15s; }
.thumb-wrap .thumb:hover { transform: scale(1.06); }
.thumb-more {
  position: absolute; right: -5px; bottom: -5px;
  min-width: 17px; height: 17px; padding: 0 4px;
  border-radius: var(--radius); border: 1.5px solid var(--surface);
  background: #0f172a; color: #fff;
  font-size: 11px; font-style: normal; font-weight: 600;
  line-height: 14px; text-align: center; letter-spacing: -.2px;
}
.order-thumb-cell { text-align: center; }

.row-pending td { background: #fffdf6; }
.row-pending:hover td { background: #fffaeb; }
.row-pending td:first-child { box-shadow: inset 2px 0 0 #f0b429; }
.row-published td { background: #f4fdf8; }
.row-published:hover td { background: #ecfbf2; }
.row-selected td { background: var(--primary-soft); }
.row-selected td:first-child { box-shadow: inset 2px 0 0 var(--primary); }
.row-flag { font-size: 11px; color: var(--warn); font-weight: 700; display: block; }

/* 行内小输入框（采集箱 / 库存 / 成本） */
.num-input {
  width: 88px; min-height: 30px; padding: 3px 7px;
  border: 1px solid var(--border); border-radius: 7px; font-size: 12.5px;
}
.stock-input {
  width: 100%; min-width: 48px; min-height: 30px;
  text-align: right; padding: 3px 6px;
  font-size: 12.5px; border: 1px solid var(--border); border-radius: 7px;
  background: #fff; font-family: var(--num);
}
.stock-input:disabled { background: var(--surface-3); color: var(--text-3); }

/* 采集箱行内编辑：窄格里必须能完整显示 0.85 / 40 */
.data-table input.box-inline {
  width: 100%; min-width: 68px; min-height: 28px;
  padding: 3px 6px; font-size: 12.5px;
  /* 底色比卡片面深一档：原来用 --surface 跟卡片同色，1px 描边在纸面上几乎看不见，
     结果是「这几个数能直接改」这件事完全没被提示出来（深色模式下更彻底，描边消失）。 */
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--text);
  font-family: var(--num); text-align: right;
  font-variant-numeric: tabular-nums;
  appearance: none; -webkit-appearance: none;
}
.data-table input.box-inline::-webkit-outer-spin-button,
.data-table input.box-inline::-webkit-inner-spin-button {
  -webkit-appearance: none; display: none; margin: 0;
}
.data-table input.box-inline:focus {
  outline: 0; border-color: var(--amber); box-shadow: 0 0 0 2px rgba(201, 122, 14, .18);
}
.data-table input.box-inline.dirty {
  border-color: var(--warn); background: var(--warn-soft);
}

/* 【评审 P0-2】长/宽/高/重 原来占 4 列（58+58+58+70 = 244px），13 列平分后每列只有 94px，
   佣金列被挤到 72px、要放三行 8.5px 小字。现在合成一格：
   第一行「长 × 宽 × 高」，第二行「重量 kg」，四列省成两列。
   行内还是 4 个独立输入框（data-field 不变、dirty 标记不变、保存逻辑完全不动）。 */
.data-table .box-dims { white-space: nowrap; }
.box-dims .dim-line { display: flex; align-items: center; gap: 2px; }
.box-dims .dim-line + .dim-line { margin-top: 2px; }
.box-dims .dim-sep { color: var(--text-3); font-size: 11px; flex: 0 0 auto; }
.box-dims .dim-unit { color: var(--text-3); font-size: 11px; margin-left: 3px; flex: 0 0 auto; }
.data-table .box-dims input.box-inline {
  width: 44px; min-width: 0; padding: 1px 3px; text-align: center;
  /* 紧凑：这个格子是两行输入框（长宽高 / 重量），行高被它一个人顶到 74px。
     输入框 28px → 23px、行距 3px → 2px，整行降到 60px，一屏多看得见两行商品；
     23px 装 12px 等宽数字还有 5px 余量，不会切字。 */
  min-height: 23px; font-size: 12px; line-height: 1.2;
}
.data-table .box-dims input.box-inline.dim-weight { width: 52px; }

/* 【评审 P0-2】采集箱表格改用固定列宽。
   table-layout:auto 下 <th style="width:96px"> 只是「建议值」，浏览器按内容重新分配：
   实测 9 个有声明的列里 5 个被改（SKU 104→94、采购价 70→62、佣金 96→77、状态 64→75、
   操作 128→114），也就是说佣金列从 72px 加宽到 96px 的改动在 auto 下等于没做。
   fixed 之后声明值才是硬约束，列宽可预期；代价是内容不会被撑开，所以每一列都
   单独验过放得下（见 scripts/ui_after_probe.py 的 列宽声明是否被遵守 一节）。
   标题列不写宽度，拿剩下的全部空间。 */
.box-table-wrap .data-table { table-layout: fixed; }
.box-table-wrap { max-height: calc(100vh - 250px); }
/* 10 列（选/图/SKU/标题/采购价/售价/佣金/尺寸重量/状态/操作），行内输入框左右各 5px，
   把表格压在容器宽度内，否则最右边的「✕」会被卡片边缘切掉。
   【评审 P0-2】原来是 13 列，尺寸四列合一后标题列从 310px 涨到 400px 以上。 */
.box-table-wrap .data-table td { padding: 7px 5px; }
.box-table-wrap .data-table th { padding: 9px 5px; }
/* 采集箱标题列：尺寸四列合一后腾出了宽度，别再把标题卡在 300px 上（俄文标题动辄 60 字符）。 */
.box-table-wrap .cell-title { max-width: 460px; }
/* fixed 的副作用：标题列没写宽度，窄屏时它是唯一能无限压缩的列，会被压到 0。
   实测 1280px 只剩 92px、1180px 直接 0px —— 俄文标题整列看不见，比原来更差。
   所以窄屏退回 auto，让浏览器按内容重新分配（代价是佣金列不再保证 96px，但标题可读；
   1600 与 1440 两档实测 title 仍有 412 / 252px，走 fixed）。
   注意这条必须写在上面的 .cell-title 之后 —— 同权重规则后写者胜。 */
@media (max-width: 1300px) {
  .box-table-wrap .data-table { table-layout: auto; }
  /* auto 下标题列会把 max-width 用满（460px），10 列硬撑到 1186px，
     窄屏要横拖半屏才看得到操作列。窄屏收回 320px，与其它表格一致。 */
  .box-table-wrap .cell-title,
  .box-table-wrap .cell-gloss { max-width: 320px; }
}
.box-toolbar .hint { margin-left: auto; }
/* 操作列不折行：table-layout:auto 会把 111px 的列压到放不下三个按钮，
   结果是「详情 / Yandex / 删除」竖着排、行高翻三倍 */
#boxBody tr td:last-child,
#favBody tr td:last-child { white-space: nowrap; }
/* 首页「物流模板」表：卡片只占右半屏（约 470px），5 列里操作列声明 112px 被压到 58px，
   编辑 / 设为默认 / 删除 三个按钮竖着排，行高从 34px 涨到 50px、右侧还留一截空。
   nowrap 让 auto 布局按 min-content 撑开这一列，三个按钮回到一行。 */
#logisticsBody tr td:last-child { white-space: nowrap; }

/* ================= 9. 工具栏 / 页签 / 分页 ================= */
.toolbar { display: flex; align-items: center; gap: 10px 8px; flex-wrap: wrap; margin-bottom: 12px; }
.toolbar input[type="search"] { flex: 1 1 170px; max-width: 260px; min-height: 34px; }
.toolbar select { max-width: 150px; min-height: 34px; }
.toolbar .btn { min-height: 34px; }
.toolbar .btn.btn-xs { min-height: 30px; }
.toolbar .hint { margin-left: auto; }
.toolbar-spacer { flex: 1 1 auto; }
/* 【评审 P0-6】7~9 个控件挤一行时会被动换行，换完没有分区，读起来像堆在一起。
   这里给一个显式断行：筛选在第一排、批量动作在第二排，换行位置由结构决定而不是宽度决定。 */
.toolbar-break { flex: 0 0 100%; height: 0; margin: 0; }
/* 批量/危险动作贴右：与筛选区分开 */
.toolbar-end { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

.tabs {
  display: inline-flex; gap: 2px; padding: 3px;
  background: var(--surface-3); border: 1px solid var(--border); border-radius: var(--radius);
}
.tabs button {
  border: 0; background: transparent; padding: 6px 14px; border-radius: var(--radius);
  font-size: 12.5px; color: var(--text-2); cursor: pointer; font-weight: 550;
  display: inline-flex; align-items: center; gap: 6px; font-family: inherit;
  transition: background .15s, color .15s, box-shadow .15s;
}
.tabs button:hover { color: var(--text); }
/* 选中项用主色实底，和主按钮同一套：浅色下是墨底米白字，深色下自动翻成琥珀底深字。
   原来用 surface 底 + primary 字，深色下反而比容器更暗，选中项看反。 */
.tabs button.active {
  background: var(--primary); color: var(--surface); font-weight: 650;
  border-color: var(--primary);
}
.tabs i {
  font-style: normal; font-size: 11px; background: var(--surface-3);
  border-radius: var(--radius-sm); padding: 0 6px; color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.tab-pane { display: none; padding: 2px 0 0; }
.tab-pane.active { display: flex; flex-direction: column; gap: 12px; }

.pager { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; padding: 14px 2px 2px; }
.pager-btn {
  min-width: 32px; height: 32px; padding: 0 9px; border-radius: var(--radius);
  border: 1px solid var(--border); background: var(--surface); color: var(--text-2);
  font-size: 12.5px; font-weight: 550; cursor: pointer; font-family: inherit;
  font-variant-numeric: tabular-nums;
  transition: border-color .15s, color .15s, background .15s;
}
.pager-btn:hover:not(:disabled) { border-color: rgba(79, 70, 229, .45); color: var(--primary); background: var(--primary-soft); }
.pager-btn.active { background: var(--primary); border-color: var(--primary); color: #fff; font-weight: 650; }
.pager-btn:disabled { opacity: .4; cursor: default; }
.pager-gap { padding: 0 4px; color: var(--text-3); }
.pager-info { margin-left: auto; font-size: 12.5px; color: var(--text-3); }

/* ================= 10. 进度 / 控制台 / 结果区 ================= */
.action-bar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--border);
}
.action-bar #btnCancel { margin-left: auto; }

.run-card { padding: 18px 20px; }
.progress {
  height: 9px; background: var(--surface-3); border-radius: 1px; overflow: hidden;
  box-shadow: inset 0 1px 2px rgba(15, 23, 42, .05);
}
.progress-bar {
  height: 100%; width: 0%;
  background: linear-gradient(90deg, #c97a0e, #e8a33d);
  border-radius: 1px;
  transition: width .3s var(--ease);
  box-shadow: 0 1px 6px rgba(99, 102, 241, .5);
}
.progress-meta {
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
  margin-top: 10px; font-size: 12.5px; color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.stats-line {
  display: flex; flex-wrap: wrap; gap: 10px 26px;
  margin-top: 14px; padding-top: 13px; border-top: 1px dashed var(--border);
  font-size: 12.5px; color: var(--text-3);
}
.stats-line b {
  font-size: 15px; font-weight: 700; color: var(--text);
  font-variant-numeric: tabular-nums; margin-left: 4px;
}
.stats-line .s-ok b { color: var(--ok); }
.stats-line .s-bad b { color: var(--bad); }
.stats-line .s-warn b { color: var(--warn); }

.result-card { padding: 0; overflow: hidden; }
.result-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  padding: 13px 20px; border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}
.result-actions { display: flex; gap: 8px; }

.console {
  background: #0f1420; border-radius: var(--radius);
  border: 1px solid #1e2637; padding: 14px 16px;
  height: 440px; overflow-y: auto;
  font-family: var(--num); font-size: 12.5px; line-height: 1.7;
  color: #c9d3e4;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .03);
}
.console .line { display: flex; gap: 10px; padding: 1px 0; word-break: break-all; }
.console .ts { color: #5b6579; flex: 0 0 64px; }
.console .lv { flex: 0 0 48px; font-weight: 700; }
.console .lv-info { color: #6ba6ff; }
.console .lv-warn { color: #ffc061; }
.console .lv-error { color: #ff7b72; }
.console .lv-success { color: #5fd68c; }
.console .msg { flex: 1; white-space: pre-wrap; }
.console .line.warn .msg { color: #ffd79a; }
.console .line.error .msg { color: #ffb3ae; }

.result-body {
  margin: 0; padding: 16px; overflow: auto;
  background: #0f1420; color: #c9d3e4;
  border-radius: 0 0 var(--radius) var(--radius);
  font-family: var(--num); font-size: 12.5px; line-height: 1.7;
  max-height: 62vh; white-space: pre-wrap; word-break: break-all;
}

/* ================= 11. 弹窗 / 抽屉 / Toast ================= */
.modal-mask {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(15, 23, 42, .45);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  display: none; align-items: center; justify-content: center; padding: 24px;
}
.modal-mask.open { display: flex; }
.modal {
  background: var(--surface);
  border-radius: var(--radius);
  width: min(480px, 100%); max-height: 90vh;
  display: flex; flex-direction: column;
  box-shadow: var(--shadow-lg);
  animation: pop-in .18s var(--ease);
  overflow: hidden;
}
@keyframes pop-in { from { opacity: 0; transform: translateY(8px) scale(.99); } to { opacity: 1; transform: none; } }
.modal-wide { width: min(800px, 100%); }
.modal-xwide { width: min(940px, 100%); }
.modal-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 16px 20px; border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.modal-head h3 { font-size: 15px; font-weight: 680; }
.modal-head-actions { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.modal-head-actions .hint { font-size: 11.5px; color: var(--text-3); }
.modal-body {
  padding: 18px 20px; display: flex; flex-direction: column; gap: 14px;
  overflow: auto; background: var(--surface);
}
.modal-foot {
  display: flex; align-items: center; justify-content: flex-end; gap: 9px;
  padding: 14px 20px; border-top: 1px solid var(--border);
  background: var(--surface-2);
}

.drawer-mask {
  position: fixed; inset: 0; z-index: 55;
  background: rgba(15, 23, 42, .42);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  display: none;
}
.drawer-mask.open { display: block; }
.drawer {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: min(920px, 94vw);
  background: var(--surface);
  display: flex; flex-direction: column;
  box-shadow: -20px 0 60px rgba(15, 23, 42, .22);
  animation: drawer-in .22s var(--ease);
}
@keyframes drawer-in { from { transform: translateX(28px); opacity: .5; } to { transform: none; opacity: 1; } }
.drawer-wide { width: min(1120px, 96vw); }
.drawer-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 15px 20px; border-bottom: 1px solid var(--border);
}
.drawer-head h3 { font-size: 15px; font-weight: 680; }
.drawer-head-actions { display: flex; gap: 7px; }
.drawer-tip { margin: 0; padding: 10px 20px 0; font-size: 12.5px; color: var(--text-3); }
.drawer-body { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 14px 20px 24px; }
.drawer-close {
  border: 0; background: transparent; cursor: pointer;
  font-size: 18px; line-height: 1; color: var(--text-3);
  width: 30px; height: 30px; border-radius: var(--radius); font-family: inherit;
  display: grid; place-items: center;
  transition: background .15s, color .15s;
}
.drawer-close:hover { background: var(--surface-3); color: var(--text); }

/* 公司到期常驻提示条：走正常流排在顶栏下面（不 fixed，免得起页面滚动时
   挡住顶部那排操作按钮），到期后每个业务请求都 403，有这条客户才知道去哪续期。 */
.tenant-bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: 0 0 14px; padding: 10px 14px;
  background: #7c2d12; color: #fef3c7;
  border: 1px solid rgba(251, 191, 36, .45);
  border-radius: var(--radius);
  font-size: 12.5px; font-weight: 500;
}
.tenant-bar .btn { flex: none; }

/* 免费版是「还没开通」，不是「出故障」：用琥珀提示条，别用报错红。
   红条留给冻结/到期，那才是要客户马上处理的异常。 */
body[data-plan="free"] .tenant-bar {
  background: #fbf3e3;
  color: #7a4a08;
  border-color: rgba(201, 122, 14, .38);
}
body[data-plan="free"] .tenant-bar .btn-primary {
  background: var(--amber);
  border-color: var(--amber);
  color: var(--ink);          /* 铁律：琥珀底上必须配墨字 */
}

/* 免费版：要会员才能用的按钮整体灰掉。
   真正的拦截在后端（403 plan_required），这里只是别让人白点一次再吃个红条。
   标记写在按钮上（data-need-plan），比在 JS 里逐个 id 判断省事，也不会漏。 */
body[data-access="readonly"] [data-need-plan] {
  opacity: .42;
  cursor: not-allowed;
  filter: grayscale(1);
}
body[data-access="readonly"] [data-need-plan]:hover { opacity: .5; }

.toast-wrap {
  position: fixed; right: 22px; bottom: 22px; z-index: 80;
  display: flex; flex-direction: column; gap: 9px; align-items: flex-end;
  /* 提示条只是个通知，不该抢点击：它停在右下角好几秒，
     正好盖住那一带的按钮（「管理模板」「生成」这类），用户点了没反应，
     看起来像按钮坏了。让它穿过去，视觉不变、手能点到。 */
  pointer-events: none;
}
.toast {
  background: #111827; color: #f6f3ec; padding: 11px 15px; border-radius: var(--radius);
  font-size: 12.5px; font-weight: 500;
  box-shadow: 0 16px 40px -14px rgba(15, 23, 42, .6);
  max-width: 400px; animation: toast-in .2s var(--ease);
  border-left: 3px solid rgba(255, 255, 255, .18);
}
.toast.ok { background: #064e3b; border-left-color: #34d399; }
.toast.bad { background: #7f1d1d; border-left-color: #f87171; }
.toast.warn { background: #78350f; border-left-color: #fbbf24; }
@keyframes toast-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* ================= 12. 图片网格 ================= */
.image-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(108px, 1fr));
  gap: 10px; padding: 10px;
  border: 1.5px dashed var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface-2);
  min-height: 68px;
}
.image-grid:empty::before {
  content: '尚未添加图片，可粘贴 URL 后回车';
  color: var(--text-3); font-size: 12.5px; padding: 4px 2px;
}
.image-cell {
  position: relative; background: #fff;
  border: 1px solid var(--border); border-radius: var(--radius);
  overflow: hidden; aspect-ratio: 1 / 1;
  display: flex; align-items: center; justify-content: center;
  cursor: grab;
  transition: border-color .15s, box-shadow .15s, transform .15s;
}
.image-cell:hover { border-color: rgba(79, 70, 229, .5); box-shadow: var(--shadow-xs); }
.image-cell:active { cursor: grabbing; }
.image-cell img { width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
.image-fallback {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-3); color: var(--text-3);
  font-size: 12.5px; text-align: center; padding: 6px;
}
.image-cell-pos {
  position: absolute; top: 5px; left: 5px;
  min-width: 20px; height: 20px; padding: 0 6px;
  background: rgba(15, 23, 42, .68); color: #fff;
  border-radius: var(--radius-sm); font-size: 11px; font-weight: 650;
  display: flex; align-items: center; justify-content: center;
  backdrop-filter: blur(4px);
}
.image-cell-tools {
  position: absolute; right: 5px; bottom: 5px;
  display: flex; gap: 3px; opacity: 0;
  transition: opacity .15s;
}
.image-cell:hover .image-cell-tools { opacity: 1; }
.image-cell-tools .btn {
  min-height: 22px; padding: 0 6px; font-size: 11px;
  border-radius: 6px; line-height: 1.2;
  background: rgba(255, 255, 255, .94);
}
.image-cell.dragging { opacity: .4; }
.image-cell.drop-target {
  border-color: var(--primary);
  box-shadow: 0 0 0 2px rgba(79, 70, 229, .25);
  transform: scale(1.02);
}
.image-grid-toolbar { display: flex; gap: 8px; align-items: center; margin-top: 8px; }
.image-grid-toolbar .btn { min-height: 34px; }
.image-add-input { flex: 1; }
.image-grid-toolbar input { flex: 1; }

/* ================= 13. 类目参数表单 ================= */
/* 类目参数网格：参数名长短差很多（「厂方颜色名称」一行、「Количество упаковок в товаре」
   能折三行），等高标签行 + 顶端对齐的控件，否则同一排的输入框会参差不齐。
   做法：每个 .field 占两格（标签行 + 控件行）并用 subgrid 跟随父网格的行高，
   同一排的标签行自动等高；控件 align-self:start 保持自身高度但顶端对齐。
   不支持 subgrid 的浏览器回落到「标签行预留三行高 + 顶端对齐」。 */
.params-grid {
  /* 自己声明 display:grid，**不挂 .form-grid**：.form-grid 在几个媒体查询里会被改成
     2 列 / 1 列，挂上去就把这里的自适应列数覆盖掉了（窄窗口下只剩 2 列，右边空一大片）。
     auto-fill 本身就随宽度伸缩，不需要额外的媒体查询。 */
  display: grid;
  margin-top: 10px;
  gap: 12px 14px;
  align-items: start;
  grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
}
.params-grid .field {
  position: relative;
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 2;
  gap: 6px;
}
.params-grid .field > span {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  line-height: 1.35;
}
.params-grid .field > select,
.params-grid .field > input,
.params-grid .field > textarea { align-self: start; }
/* 文本框统一高度：rows=2 时宽度不同算出的高度也不同，一排三个框高矮不齐很难看 */
.params-grid .field > textarea { min-height: 56px; }
/* 下拉里的俄语枚举值偏长，列窄时会被截断成「лежан…」；字号收一点能多露几个字，
   完整值用 title 悬停看（JS 侧给 select 补 title）。 */
.params-grid .field > select { font-size: 12.5px; text-overflow: ellipsis; }
@supports not (grid-template-rows: subgrid) {
  .params-grid .field { display: flex; }
  .params-grid .field > span { min-height: 3.4em; align-content: flex-start; }
}
.params-grid .param-type {
  font-size: 11px; padding: 1px 6px; border-radius: 5px;
  background: var(--surface-3); color: var(--text-3);
  font-style: normal; font-weight: 600; letter-spacing: .03em;
}
.params-grid .param-tick { color: var(--ok); font-weight: 700; }
.params-grid .param-miss { color: var(--bad); font-weight: 700; margin-left: auto; }
.params-grid .required-field {
  border-left: 2px solid #f0b429; padding-left: 10px; border-radius: 2px;
}
.params-grid select, .params-grid input, .params-grid textarea { width: 100%; }
/* 同一行里下拉和文本框高度统一，否则视觉上像没对齐 */
.params-grid select, .params-grid input:not([type="checkbox"]):not([type="radio"]) { min-height: 34px; }

.param-label { color: var(--text-1); font-weight: 620; }
/* 参数名后面的俄语原名：中文为主，俄文退成小字灰字，不抢视线但随时对得上后台 */
.param-ru {
  color: var(--text-3); font-size: 11.5px; font-style: normal;
  font-weight: 500; margin-left: 1px; overflow-wrap: anywhere;
}
.param-type { margin-left: 5px; }
.field-gloss { margin-top: 3px; }
.gloss {
  display: block; font-style: normal; font-size: 12.5px;
  color: var(--text-3); line-height: 1.45; margin-top: 2px;
}
.gloss-fix { color: var(--warn); }
.field > span > em.ru {
  font-style: normal; font-size: 11.5px; color: var(--text-3);
  font-weight: 400; margin-left: 4px;
}

/* 勾选列：多个表格共用，统一收窄居中 */
.col-check { width: 34px; text-align: center; }

/* ================= 14. 采集箱详情 ================= */
.box-price-row, .box-stock-row {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  padding: 10px 12px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-2);
}
.box-price-unit { flex: 0 0 auto; width: 132px; }
.box-price-input { flex: 0 1 190px; text-align: right; font-family: var(--num); }
.box-price-calc { flex: 1 1 210px; }
.box-stock-row .hint { color: var(--text-3); }
.box-stock-wh { flex: 1 1 240px; min-width: 200px; }
.box-stock-num { flex: 0 0 120px; width: 120px; text-align: right; font-family: var(--num); }
.field .box-stock-wh,
.field .box-stock-num { flex: none; width: 100%; min-width: 0; }

.box-warn {
  padding: 10px 12px; border-radius: var(--radius);
  background: var(--warn-soft); border: 1px solid #f6ddab;
  color: #92400e; font-size: 12.5px; line-height: 1.6; margin-bottom: 12px;
}
.ai-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-bottom: 14px;
  padding-bottom: 14px; border-bottom: 1px dashed var(--border);
}
.box-section-title {
  display: flex; align-items: center;
  font-size: 11.5px; color: var(--text-3); font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; margin: 4px 0 2px;
}
.box-images { display: flex; flex-wrap: wrap; gap: 8px; }
.box-images img {
  width: 64px; height: 64px; border-radius: var(--radius); object-fit: cover;
  border: 1px solid var(--border); background: var(--surface-2); cursor: zoom-in;
}
.box-images .thumb-lg { width: 64px; height: 64px; font-size: 11.5px; }
.box-link-row { font-size: 12.5px; color: var(--text-2); }
.box-link-row a { color: var(--primary); text-decoration: none; word-break: break-all; }
.box-link-row a:hover { text-decoration: underline; }
/* 采集属性明细：只给「11 项」这个数字等于没给 —— 运营看不到内容，
   就以为没采到（真实反馈）。值单行截断、title 看全文，避免长法务说明撑破弹窗。 */
.box-attr-head { margin: 10px 0 6px; font-size: 12px; color: var(--text-2); }
.box-attr-grid {
  display: grid; gap: 4px 8px;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
}
.box-attr-grid > div {
  display: flex; gap: 6px; min-width: 0;
  padding: 3px 8px; font-size: 12px;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.box-attr-grid .k {
  flex: 0 1 auto; max-width: 46%; color: var(--text-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.box-attr-grid .v {
  flex: 1 1 0; min-width: 0; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kv-key { width: 42%; color: var(--text-2); }
.attr-scroll {
  max-height: 280px; overflow: auto;
  border: 1px solid var(--border); border-radius: var(--radius);
}
.attr-scroll .data-table th { position: sticky; top: 0; }
.attr-editor { display: flex; flex-direction: column; gap: 7px; }
.attr-editor:empty::before,
.attr-editor[data-empty="1"]::before {
  content: '还没采到属性 —— 点上方「+ 添加属性」手工补充（Yandex 只认俄语名/值）';
  color: var(--text-3); font-size: 12.5px; padding: 6px 2px;
}
.attr-row {
  display: grid; grid-template-columns: minmax(140px, 1fr) minmax(180px, 2fr) auto;
  gap: 7px; align-items: center;
}
.attr-row input {
  min-height: 32px; padding: 5px 9px; font-size: 12.5px;
  border: 1px solid var(--border); border-radius: var(--radius);
}
.attr-row .attr-key { font-weight: 600; }
.attr-row .attr-val { color: var(--text-1); }
.attr-row .gloss { grid-column: 1 / -1; }
.translate-row {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 12px; margin-bottom: 12px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-2); font-size: 12.5px; cursor: pointer;
}
.translate-row input { width: 15px; height: 15px; }
.btn-translate { margin-left: 6px; padding: 1px 8px; font-size: 11.5px; line-height: 1.6; }

/* ================= 15. 类目选择器 ================= */
.cat-picker {
  display: grid; grid-template-columns: 244px minmax(0, 1fr);
  gap: 16px; align-items: start;
}
.cat-tree {
  max-height: 480px; overflow-y: auto;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-2); padding: 8px;
}
.cat-node { margin-bottom: 2px; }
.cat-main { min-width: 0; }
.cat-node-head, .cat-leaf {
  display: flex; align-items: center; justify-content: space-between;
  gap: 6px; width: 100%; border: 0; background: transparent;
  text-align: left; padding: 7px 9px; border-radius: var(--radius); cursor: pointer;
  font-size: 12.5px; color: var(--text-1); font-family: inherit;
  transition: background .14s, color .14s;
}
.cat-node-head { font-weight: 620; }
.cat-node-head:hover, .cat-leaf:hover { background: #ede8de; }
.cat-node-head.active { background: var(--primary); color: #fff; }
.cat-node-head.active .cat-count { color: rgba(255, 255, 255, .8); }
.cat-node-body { padding-left: 10px; }
.cat-leaf { font-size: 12.5px; color: var(--text-2); font-weight: 400; }
.cat-count {
  font-style: normal; font-size: 11px; color: var(--text-3);
  flex: 0 0 auto; font-variant-numeric: tabular-nums;
}

/* ================= 16. Yandex 定价 ================= */
.pricing-card { margin-top: 2px; }
.pricing-card .card-head { margin-bottom: 14px; }
.pricing-layout {
  display: grid;
  grid-template-columns: minmax(320px, 1fr) minmax(0, 1.42fr);
  gap: 18px; align-items: start;
}
.pricing-inputs {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
}
.pricing-subtitle {
  margin: 0 0 12px; font-size: 13px; color: var(--text-2); font-weight: 650;
}
.pricing-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 11px; }
.pricing-inputs .btn-primary { width: 100%; margin-top: 12px; }
.pricing-inputs .hint { display: block; margin-top: 9px; font-size: 12.5px; }
.pricing-results { min-width: 0; }
.pricing-results-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px; margin-bottom: 12px; font-weight: 650;
}
.pricing-result-list {
  display: grid; gap: 12px; max-height: 680px; overflow-y: auto; padding-right: 4px;
}
.price-cand {
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 15px; background: var(--surface);
  box-shadow: var(--shadow-xs);
  transition: box-shadow .18s var(--ease), border-color .18s var(--ease), transform .18s var(--ease);
}
.price-cand:hover { box-shadow: var(--shadow); border-color: #dbe2ef; transform: translateY(-1px); }
.price-cand-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px; margin-bottom: 11px;
}
.price-cand-title { font-weight: 700; font-size: 13px; }
.price-cand-kind { font-size: 11.5px; color: var(--text-3); }
.price-cand-main { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; margin-bottom: 11px; }
.price-cand-price { border-radius: var(--radius); padding: 10px 12px; text-align: center; }
.price-cand-price.cny {
  background: linear-gradient(135deg, #12304a, #0b2438); color: #fff;
  box-shadow: 0 8px 18px -12px rgba(11, 36, 56, .85);
}
.price-cand-price.rub { background: var(--primary-soft); color: var(--primary-dark); }
.price-cand-price small { display: block; font-size: 11px; opacity: .88; }
.price-cand-price b { font-size: 20px; font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.price-cand-metrics { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 7px; }
.price-cand-metric {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 6px 8px;
  font-size: 11px; color: var(--text-3);
}
.price-cand-metric b {
  display: block; margin-top: 2px; font-size: 12.5px; color: var(--text);
  font-variant-numeric: tabular-nums;
}

/* ================= 17. 利润核算 ================= */
.profit-up { color: #2f6b4f; font-weight: 680; font-variant-numeric: tabular-nums; }
.profit-down { color: #a62b2b; font-weight: 680; font-variant-numeric: tabular-nums; }
.profit-cost {
  width: 100%; max-width: 82px; min-height: 30px; padding: 3px 6px;
  border: 1px solid var(--border); border-radius: var(--radius);
  font-size: 12.5px; background: var(--surface); color: var(--text);
  font-family: var(--num); text-align: right;
}
.profit-cost:focus { outline: 0; border-color: var(--primary); box-shadow: var(--ring); }
.profit-orders { width: 86px; }

.cat-commission {
  display: inline-flex; align-items: center; gap: 4px;
  margin-left: 8px; padding: 2px 8px 2px 7px;
  border-radius: var(--radius-sm); background: var(--primary-soft);
  color: var(--primary-dark); font-size: 11.5px; font-weight: 620;
  white-space: nowrap;
}
.cat-commission input {
  width: 56px !important; height: 21px; min-height: 0 !important;
  padding: 0 4px !important; text-align: right;
  border: 1px solid rgba(79, 70, 229, .3) !important;
  border-radius: 6px !important;
  background: #fff; color: var(--text); font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}
.cat-commission em { font-style: normal; }
/* 官方三档里的 FBP：跟 FBS 并排的小字旁注，比主值弱一档，不抢视线 */
.cat-commission-fbp {
  margin-left: 2px; padding-left: 6px;
  border-left: 1px solid rgba(79, 70, 229, .22);
  color: var(--text-3); font-size: 11px; font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* 采集箱：店铺筛选下拉
   【评审 P0-2】原来只给 max-width:200px 且参与 flex 收缩，实测被压到 150px，
   店名显示成「Магазин обаков: 2169415」（订单页同款控件是 250px）。
   这里锁住最小宽度并禁止收缩 —— 选错店铺会把商品传到别家店，代价很高。 */
.box-store {
  min-width: 216px; max-width: 260px; min-height: 34px;
  flex: 0 0 auto;
  font-size: 12.5px; padding: 4px 8px;
}
.box-store.need-store {
  border-color: var(--bad); box-shadow: 0 0 0 3px var(--bad-soft);
}

/* 采集箱列表里的佣金：费率 + 扣佣金额。人工核对过 / 表内精确 / 估算，三档颜色区分 */
.comm-rate {
  display: inline-block; padding: 1px 6px; border-radius: var(--radius-sm);
  font-size: 11.5px; font-weight: 640; font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.comm-rate.manual { background: var(--ok-soft, #e6efe8); color: var(--ok-dark, #2f6b4f); }
.comm-rate.table { background: var(--primary-soft); color: var(--primary-dark); }
/* 父类目档：官方公布的费率，但不是这个子类自己的 —— 用警示色，别和精确值同色 */
.comm-rate.parent { background: var(--warn-soft); color: var(--warn-dark, #8a5200); }
.comm-rate.guess { background: var(--warn-soft); color: var(--warn-dark, #8a5200); }
.comm-rate + .cell-gloss { display: block; margin-top: 2px; }

/* 【评审 P0-5】原来是 minmax(190px,.92fr) : 1.5fr —— 实测 234 : 468，
   也就是「这一单赚多少」那个数只占 33%，6 个次要指标占 67%，主次颠倒；
   而且结论块里写着「待核算」三个字还占那么大一块。
   改成上结论 / 下指标：结论整行，指标在下面排 6 列。 */
.settle-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 11px; align-items: stretch;
}
.settle-hero-main {
  position: relative; overflow: hidden;
  border-radius: var(--radius); padding: 16px 18px;
  background: linear-gradient(135deg, #1b3f5c, #0b2438 60%, #0b2438);
  color: #fff; display: flex; flex-direction: column; gap: 3px;
  justify-content: center;
  box-shadow: 0 14px 30px -18px rgba(11, 36, 56, .85);
}
/* 装饰光斑：未核算时也不会是一块死板的纯色 */
.settle-hero-main::after {
  content: ''; position: absolute; right: -40px; bottom: -70px;
  width: 200px; height: 200px; border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 255, 255, .18), transparent 68%);
  pointer-events: none;
}
.settle-hero-main span { font-size: 12.5px; opacity: .9; }
.settle-hero-main b {
  font-size: 34px; line-height: 1.1; letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}
.settle-hero-main em { font-size: 12.5px; font-style: normal; opacity: .9; }
.settle-hero-main.loss {
  background: linear-gradient(135deg, #f87171, #a62b2b 60%, #a62b2b);
  box-shadow: 0 14px 30px -18px rgba(220, 38, 38, .85);
}
/* 结论整行之后，6 个次要指标横向铺开（原来挤在 468px 里的 3 列 × 2 行，每格 156px） */
.settle-hero-metrics { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 9px; }
.settle-hero-metrics > div {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 9px 11px;
  font-size: 11px; color: var(--text-3); min-width: 0;
}
.settle-hero-metrics b {
  display: block; margin-top: 3px; font-size: 13px; color: var(--text-1);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  font-variant-numeric: tabular-nums;
}
.settle-breakdown {
  margin-top: 12px; border: 1px solid var(--border);
  border-radius: var(--radius); overflow: hidden;
}
.settle-line {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding: 8px 13px; font-size: 12.5px; border-bottom: 1px solid var(--border);
}
.settle-line:last-child { border-bottom: 0; }
.settle-line > span { color: var(--text-2); }
.settle-line > b { font-variant-numeric: tabular-nums; }
.settle-line.total { background: var(--surface-2); font-weight: 680; }
.settle-line.deduct > b { color: var(--bad); }
.settle-apply { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin-top: 12px; }
.settle-apply select { max-width: 360px; }

/* ================= 18. 订单管理 ================= */
.order-tabs {
  display: inline-flex; gap: 2px; padding: 3px;
  background: var(--surface-3); border: 1px solid var(--border);
  border-radius: var(--radius); margin: 2px 0 14px;
}
.order-tab {
  padding: 7px 16px; border-radius: var(--radius); border: 0;
  background: transparent; color: var(--text-2);
  font-size: 12.5px; font-weight: 550; cursor: pointer; font-family: inherit;
  transition: background .15s, color .15s, box-shadow .15s;
}
.order-tab:hover { color: var(--text); }
.order-tab.active {
  background: var(--primary); color: var(--surface); font-weight: 650;
}
.order-panel { display: none; }
.order-panel.active { display: block; animation: page-in .18s var(--ease); }

.order-issue-chips { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.issue-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 13px; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: var(--surface);
  font-size: 12.5px; font-weight: 550; cursor: pointer; color: var(--text-2);
  font-family: inherit;
  transition: border-color .15s, color .15s, background .15s;
}
.issue-chip:hover { border-color: rgba(79, 70, 229, .4); color: var(--primary); }
.issue-chip.active {
  border-color: var(--primary); color: var(--primary); background: var(--primary-soft);
}
.issue-chip .n {
  font-weight: 700; margin-left: 1px; font-variant-numeric: tabular-nums;
  background: var(--surface-3); border-radius: var(--radius-sm); padding: 0 6px; font-size: 11.5px;
}
.issue-chip.active .n { background: #fff; }

.order-issue-list { display: grid; gap: 10px; }
.issue-card {
  border: 1px solid var(--border); border-left: 3px solid var(--warn);
  border-radius: var(--radius); padding: 12px 14px; background: var(--surface);
  box-shadow: var(--shadow-xs);
  transition: box-shadow .15s, border-color .15s;
}
.issue-card:hover { box-shadow: var(--shadow); }
.issue-card.error { border-left-color: var(--bad); }
.issue-card.overdue { background: #fffafa; border-color: #f7d4d4; }
.issue-card-head { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.issue-card-head b { font-size: 13px; }
.issue-card-head .hint { margin-left: auto; }
.issue-card p { margin: 6px 0 0; font-size: 12.5px; color: var(--text-2); line-height: 1.6; }
.issue-card-actions { margin-top: 10px; display: flex; gap: 7px; }
.sku-map-form {
  display: grid; grid-template-columns: 1fr 1fr 1.4fr auto;
  gap: 10px; align-items: end; margin-bottom: 16px;
}
.sku-map-form .btn { min-height: 38px; }

/* 折叠容器（采集工作台） */
.collapsible.hidden { display: none; }

/* 定价结果未计算时的空态：把大片空白变成一块「等待输入」的占位区 */
.pricing-result-list:has(> .hint:only-child) {
  min-height: 280px;
  display: grid; place-items: center;
  border: 1.5px dashed var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface-2);
}
.pricing-result-list > .hint:only-child {
  text-align: center; max-width: 320px; line-height: 1.7;
}

/* ================= 19. 自适应 ================= */
@media (max-width: 1440px) {
  .stat-grid-6 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  /* 中等屏幕：表格收紧一点，尽量把「状态 / 操作」留在可视区 */
  .data-table { font-size: 12.5px; }
  .data-table th { padding: 9px 9px; }
  .data-table td { padding: 8px 9px; }
  .box-table-wrap .data-table th,
  .box-table-wrap .data-table td { padding: 6px 7px; }
  .data-table input.box-inline { min-width: 58px; }
  .cell-title, .cell-gloss { max-width: 280px; }
}
@media (max-width: 1180px) {
  /* 窄屏：卡头动作区允许换行，否则下拉和按钮会互相挤压 */
  .card-head-actions { flex-wrap: wrap; }
  .card-head-actions select { max-width: 100%; }
  .pricing-layout { grid-template-columns: 1fr; }
  .settle-hero { grid-template-columns: 1fr; }
  .form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .plan-grid, .dl-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 1024px) {
  :root { --sidebar-w: 204px; }
  .page-host { padding: 18px 20px 44px; }
  .topbar { padding: 12px 20px; }
  .stat-grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* 五格挤到 1024 以下，¥19,140.51 这种数字会被截成省略号 → 换 3 列 */
  .rt-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .price-cand-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 900px) {
  .brand-sub { display: none; }
  .grid-2, .stat-grid, .stat-grid-3 { grid-template-columns: 1fr; }
  .rt-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cat-picker { grid-template-columns: 1fr; }
  .cat-tree { max-height: 190px; }
  .sku-map-form { grid-template-columns: 1fr; }
  .topbar-right .env-dots { display: none; }
}
@media (max-width: 720px) {
  .app-shell { flex-direction: column; }
  .sidebar {
    position: static; height: auto; width: 100%; flex: 0 0 auto;
    flex-direction: row; flex-wrap: wrap; align-items: center;
    border-right: 0; border-bottom: 1px solid var(--border);
    padding: 10px 12px;
  }
  .sidebar-brand { border-bottom: 0; padding-bottom: 8px; margin-bottom: 0; flex: 1 1 100%; }
  .side-nav { flex-direction: row; flex-wrap: wrap; flex: 1 1 100%; gap: 4px; }
  .side-nav button { width: auto; padding: 7px 10px; }
  .side-nav button::before { display: none; }
  .nav-group { flex: 1 1 100%; margin: 6px 0 2px; }
  .sidebar-foot { border-top: 0; margin-top: 0; padding-top: 4px; flex: 1 1 100%; }
  .stat-grid-4, .stat-grid-6, .plan-grid, .dl-grid { grid-template-columns: 1fr; }
  .page-host { padding: 14px 12px 40px; }
  .topbar { padding: 10px 12px; gap: 10px; flex-wrap: wrap; position: static; }
  .topbar-left h2 { font-size: 17px; }
  .form-grid { grid-template-columns: 1fr; }
  .card { padding: 14px; border-radius: var(--radius); }
  .action-bar .btn { flex: 1 1 120px; }
  .action-bar #btnCancel { margin-left: 0; }
  .result-actions { width: 100%; }
  .result-actions .btn { flex: 1 1 auto; }
  .settle-hero-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* ---------------- 订单详情弹窗（明细 / 异常 / 实际成交核算） ---------------- */
.order-detail-top {
  display: flex; flex-direction: column; gap: 5px;
  padding-bottom: 12px; margin-bottom: 14px; border-bottom: 1px solid var(--border);
}
.order-detail-id { display: flex; align-items: center; gap: 10px; }
.order-detail-id b { font-size: 15px; letter-spacing: -.2px; font-family: var(--num); }
.order-detail-sub { font-size: 12.5px; color: var(--text-2); line-height: 1.6; }
.order-detail-cols { display: grid; grid-template-columns: minmax(0, 1fr) 390px; gap: 18px; align-items: start; }
.order-detail-main { min-width: 0; }
.order-detail-side { min-width: 0; }
.order-detail-sec { margin-bottom: 16px; }
.order-detail-sec-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 8px; }
.order-detail-sec-head h4 { margin: 0; font-size: 13px; letter-spacing: -.1px; }
.order-detail-sec-head .hint { margin-left: auto; font-size: 12.5px; }
.order-items-wrap { max-height: 268px; }
/* 商品明细：竖排卡片（左栏 ~530px 放不下 7 列表格） */
.order-item-list { display: flex; flex-direction: column; gap: 8px; }
.order-item-row {
  display: flex; align-items: center; gap: 11px;
  padding: 9px 11px; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); transition: border-color .15s, box-shadow .15s;
}
.order-item-row:hover { border-color: var(--border-strong); box-shadow: var(--shadow-sm); }
.order-item-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.order-item-name {
  font-size: 12.5px; font-weight: 560; line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.order-item-meta { font-size: 11.5px; color: var(--text-3); }
.order-item-side { text-align: right; flex: 0 0 auto; }
.order-item-side b { display: block; font-size: 13px; font-family: var(--num); }
.order-item-side small { font-size: 11.5px; color: var(--text-2); font-family: var(--num); }
.kv-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2px 16px; }
.kv-item {
  display: flex; gap: 8px; align-items: baseline;
  padding: 6px 0; border-bottom: 1px dashed #eef1f7; font-size: 12.5px;
}
.kv-key { flex: 0 0 66px; color: var(--text-3); }
.kv-val { font-weight: 500; word-break: break-word; }
.order-settle-box { display: flex; flex-direction: column; gap: 10px; }
.order-settle-price { font-size: 12.5px; color: var(--text-2); }
/* 算式块：定价 − 扣费 = 到手，一眼能对上账 */
.settle-calc {
  display: flex; flex-direction: column; gap: 2px;
  padding: 9px 11px; border-radius: var(--radius);
  background: var(--surface-2); border: 1px solid var(--border);
}
.settle-calc-head {
  font-size: 11px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--text-3); margin-bottom: 3px;
}
.settle-calc-row {
  display: grid; grid-template-columns: 14px minmax(0, 1fr) auto;
  align-items: start; gap: 7px;
  padding: 3px 0; font-size: 12.5px;
}
.settle-calc-op {
  color: var(--text-3); font-weight: 700; text-align: center;
  line-height: 1.55;
  font-variant-numeric: tabular-nums;
}
.settle-calc-label { color: var(--text-2); min-width: 0; }
.settle-calc-label small {
  display: block; font-size: 11px; color: var(--text-3);
  line-height: 1.5; overflow-wrap: anywhere;
}
.settle-calc-row b {
  font-family: var(--num); font-weight: 650; color: #a62b2b;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.settle-calc-row.base b { color: var(--text-1); }
.settle-calc-row.total {
  margin-top: 4px; padding-top: 7px;
  border-top: 1px dashed rgba(130, 150, 190, .38);
}
.settle-calc-row.total .settle-calc-label { color: var(--text-1); font-weight: 650; }
.settle-calc-row.total b { color: var(--ok); font-size: 13px; }
/* 「平台实收到手」是第二个口径（真实现金流），不抢主结论的风头：不着色、字号回落 */
.settle-calc-row.sub { padding-top: 1px; }
.settle-calc-row.sub .settle-calc-label { color: var(--text-2); }
.settle-calc-row.sub b { color: var(--text-1); font-size: 12.5px; }
.order-settle-lines { display: flex; flex-direction: column; gap: 4px; }
.settle-line {
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
  padding: 7px 10px; border-radius: var(--radius); background: var(--surface-2); font-size: 12.5px;
}
.settle-line-label { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.settle-line-label small { font-size: 11px; color: var(--text-3); }
.settle-line-value { text-align: right; font-family: var(--num); white-space: nowrap; }
.settle-line-value span { font-weight: 650; color: #a62b2b; }
/* 平台抵扣是「加回来的钱」，用绿色和扣费区分，别让人以为又多扣一次 */
.settle-line-value span.credit { color: var(--ok); }
.settle-line-value small { display: block; font-size: 11px; color: var(--text-3); }

/* 净利润：采购成本可手填，填完立刻出数。做成一条横排，跟「怎么算的」不抢视线 */
.settle-profit {
  display: flex; flex-direction: column; gap: 6px;
  margin-top: 8px; padding: 9px 10px;
  border: 1px solid rgba(130, 150, 190, .3); border-radius: var(--radius);
  background: var(--surface-2);
}
.settle-profit-head { display: flex; align-items: baseline; gap: 7px; }
.settle-profit-head b { font-size: 12.5px; color: var(--text-1); }
.settle-profit-head small { font-size: 11px; color: var(--text-3); }
.settle-profit-cost {
  display: flex; align-items: center; gap: 5px; flex-wrap: wrap;
  font-size: 12.5px; color: var(--text-2);
}
.settle-profit-cost em { font-style: normal; color: var(--text-3); }
.settle-profit-cost input {
  width: 92px; height: 26px; padding: 0 7px;
  border: 1px solid var(--border); border-radius: 6px;
  background: var(--surface-1, #fff); color: var(--text-1);
  font-family: var(--num); font-size: 12.5px; text-align: right;
}
.settle-profit-value {
  margin-left: auto; font-family: var(--num); font-size: 14px; font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.settle-profit-value.good { color: var(--ok); }
.settle-profit-value.bad { color: #a62b2b; }
.settle-profit-value.muted { color: var(--text-3); font-weight: 600; }
.settle-profit-ratio { font-size: 11px; color: var(--text-3); }
.order-settle-form {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px 10px;
  padding-top: 11px; border-top: 1px dashed rgba(130, 150, 190, .3);
}
.order-settle-form .switch-line { grid-column: 1 / -1; }
/* 【评审 P2-3】订单行内两个按钮原来靠 4px 外边距挨着，操作列只有 96px，
   两个按钮挤在一起、描边互相压住，看起来像两段裸文字（商品页是描边按钮 → 两种画法）。
   根因是列宽不够，不是类名不统一（两边本来就都是 btn-ghost btn-xs）。
   这里改成 flex 排布 + 表格列加宽，描边就回来了。 */
.order-act { white-space: nowrap; display: flex; gap: 6px; align-items: center; }
.order-act .btn + .btn { margin-left: 0; }
@media (max-width: 1100px) {
  .order-detail-cols { grid-template-columns: 1fr; }
  .kv-grid { grid-template-columns: 1fr; }
}

/* 核算数据来源标注：平台真实报表 vs 预估 */
.settle-source { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.settle-source .hint { font-size: 11.5px; line-height: 1.45; }
.order-settle-form-single { grid-template-columns: 1fr; }

/* ================= 20. AI 作图 ================= */
/* 两栏：左边「选什么、怎么改」，右边「出了什么」。
   左栏固定宽度，右栏自适应 —— 出图区要能铺开看多张，
   左栏变宽只会把表单拉得很空。 */
.ai-layout {
  display: grid; gap: 16px;
  grid-template-columns: minmax(360px, 420px) minmax(0, 1fr);
  align-items: start;
}
.ai-side { display: flex; flex-direction: column; gap: 12px; }
.ai-main { min-width: 0; }

/* 拖拽区：虚线框 + 悬停变色，是「可以拖进来」唯一可靠的视觉提示 */
.ai-drop {
  display: flex; flex-direction: column; gap: 6px; align-items: center;
  justify-content: center; text-align: center;
  padding: 22px 16px; cursor: pointer;
  border: 1.5px dashed var(--border-strong); border-radius: var(--radius-sm);
  background: var(--surface-2); transition: border-color .18s var(--ease), background .18s var(--ease);
}
.ai-drop:hover { border-color: var(--primary); background: var(--primary-soft); }
.ai-drop.active { border-color: var(--primary); background: var(--primary-soft); }
.ai-drop-text { font-size: 13px; font-weight: 600; color: var(--text-1); }

.ai-url-row { display: flex; gap: 8px; align-items: center; }
.ai-url-row input {
  flex: 1 1 auto; min-width: 0;
  padding: 8px 11px; font-size: 12.5px;
  border: 1px solid var(--border); border-radius: var(--radius-xs);
  background: var(--surface); color: var(--text-1);
}
.ai-url-row input:focus { border-color: var(--primary); box-shadow: var(--ring); outline: none; }

/* 原图预览：多张参考图横排缩略图，每张右上角一个 × 单独移除。
   空的时候 `.ai-thumbs` 不占位（:empty），只留一行提示文字。 */
.ai-preview {
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  min-height: 74px; padding: 10px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface-2);
}
.ai-thumbs { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.ai-thumbs:empty { display: none; }
.ai-thumb {
  position: relative; width: 64px; height: 64px; flex: 0 0 auto;
  border: 1px solid var(--border); border-radius: var(--radius-xs);
  background: #fff; overflow: hidden;
}
.ai-thumb img { display: block; width: 100%; height: 100%; object-fit: contain; }
/* 序号是给模型看的顺序：第 1 张是商品外观基准，必须让人一眼看出哪张是第 1 张 */
.ai-thumb-idx {
  position: absolute; left: 3px; top: 3px;
  padding: 0 4px; border-radius: 4px;
  font-size: 11px; font-weight: 700; line-height: 1.6;
  color: #fff; background: rgba(17, 24, 39, .68);
}
/* 单张删除：以前 18px 挤在角上、深灰底，用户根本没看见，
   以为「只能全部移除」（实际能删，只是找不到）。改成 22px 圆形、
   常显白 ×、悬停变红，并给整缩略图一个悬停态提示可删。 */
.ai-thumb-x {
  position: absolute; right: 2px; top: 2px;
  width: 22px; height: 22px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; font-weight: 700; line-height: 1;
  color: #fff; background: rgba(17, 24, 39, .72);
  border: 1px solid rgba(255, 255, 255, .55); border-radius: 50%;
  cursor: pointer; z-index: 2;
  transition: background .15s var(--ease), transform .15s var(--ease);
}
.ai-thumb:hover { border-color: var(--bad); }
.ai-thumb-x:hover { background: var(--bad); transform: scale(1.12); }
.ai-preview-meta {
  flex: 1 1 auto; min-width: 0;
  font-size: 12.5px; color: var(--text-3); line-height: 1.6; overflow-wrap: anywhere;
}

/* 移除按钮：平时低调，悬停才变红 —— 它是「删东西」的动作，不该比「生成」更显眼 */
.ai-preview-remove {
  flex: 0 0 auto;
  padding: 5px 11px;
  font-size: 12.5px; font-weight: 600;
  color: var(--text-2); background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-xs);
  cursor: pointer;
  transition: color .16s var(--ease), border-color .16s var(--ease), background .16s var(--ease);
}
.ai-preview-remove:hover {
  color: var(--bad); border-color: #fecaca; background: var(--bad-soft);
}

/* 场景卡片：一屏看全 7 个，不用滚 */
.ai-scene-grid { display: grid; gap: 8px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.ai-scene {
  display: flex; flex-direction: column; gap: 2px; text-align: left;
  padding: 9px 11px; cursor: pointer;
  border: 1px solid var(--border); border-radius: var(--radius-xs);
  background: var(--surface); color: var(--text-1);
  transition: border-color .16s var(--ease), background .16s var(--ease), box-shadow .16s var(--ease);
}
.ai-scene:hover { border-color: var(--border-strong); background: var(--surface-2); }
.ai-scene.selected {
  border-color: var(--primary); background: var(--primary-soft);
  box-shadow: inset 0 0 0 1px var(--primary);
}
.ai-scene-label { font-size: 12.5px; font-weight: 620; }
.ai-scene-hint { font-size: 11px; color: var(--text-3); line-height: 1.5; }

/* 各场景的俄语文案区：选中场景就出现，字段按该场景用得上的那几项显示 */
.ai-copy {
  display: flex; flex-direction: column; gap: 8px;
  margin-top: 8px; padding: 10px 11px;
  border: 1px solid var(--primary-soft-border, var(--border));
  border-left: 3px solid var(--primary);
  border-radius: var(--radius-xs); background: var(--surface-2);
}
.ai-copy[hidden] { display: none !important; }
/* 「AI 接口地址 / 密钥 / 模型」这一组：平台统一提供时整组收起。
   类本身不带样式，只作分组标记 —— 它们是栅格子项，样式仍靠 .field / .field-wide。 */
.ai-tenant-only { min-width: 0; }
/* 用不上的字段整块拿掉：主图只要标题，把卖点/按钮也摆出来只会让人以为「不填就不出图」 */
.ai-copy [data-copy-field][hidden] { display: none !important; }
.ai-copy-tip {
  font-size: 12.5px; line-height: 1.55; color: var(--text-2);
  padding: 6px 8px; border-radius: 4px;
  background: var(--surface-3, var(--surface)); border: 1px dashed var(--border);
}
.ai-copy-row { display: grid; gap: 8px; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); }
.ai-copy-req {
  font-style: normal; font-weight: 700; font-size: 11px; margin-left: 6px;
  padding: 1px 5px; border-radius: 3px;
  color: #8a5200; background: #fef3c7;
}

/* 状态条：生成中/成功/失败都用同一条，位置固定不抖动 */
.ai-status {
  font-size: 12.5px; line-height: 1.6; color: var(--text-2);
  padding: 9px 11px; border-radius: var(--radius-xs);
  background: var(--surface-2); border: 1px solid var(--border);
  overflow-wrap: anywhere;
  /* 平台审核类报错会给 2~3 行建议，塌成一行就看不清了 */
  white-space: pre-line;
}
.ai-status.running { background: var(--info-soft); border-color: #bae6fd; color: #075985; }
.ai-status.ok { background: var(--ok-soft); border-color: #a7f3d0; color: #065f46; }
.ai-status.error { background: var(--bad-soft); border-color: #fecaca; color: #991b1b; }

/* 接口设置：默认折叠，不配也能先看图 */
.ai-config {
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface-2); padding: 10px 12px;
}
.ai-config > summary {
  cursor: pointer; font-size: 12.5px; font-weight: 620; color: var(--text-1);
  list-style: none;
}
.ai-config > summary::-webkit-details-marker { display: none; }
.ai-config > summary::before { content: '▸ '; color: var(--text-3); }
.ai-config[open] > summary::before { content: '▾ '; }
.ai-config-grid { display: grid; gap: 10px; margin-top: 11px; }
.ai-config-foot { display: flex; gap: 10px; align-items: center; margin-top: 10px; flex-wrap: wrap; }
.ai-check {
  display: flex; gap: 7px; align-items: center;
  margin-top: 10px; font-size: 12.5px; color: var(--text-2);
}
.ai-check input { width: 15px; height: 15px; accent-color: var(--primary); }

/* 失败卡片里的「看提示词」：默认收起，展开才显示整段，卡片不至于被撑爆 */
.ai-card-prompt {
  border-top: 1px dashed var(--border); margin-top: 6px; padding-top: 6px;
}
.ai-card-prompt > summary {
  cursor: pointer; font-size: 11.5px; color: var(--text-3); list-style: none;
}
.ai-card-prompt > summary::-webkit-details-marker { display: none; }
.ai-card-prompt > summary::before { content: '▸ '; }
.ai-card-prompt[open] > summary::before { content: '▾ '; }
.ai-card-prompt-text {
  margin: 6px 0 0; padding: 7px 9px; border-radius: 6px;
  background: var(--surface-2); border: 1px solid var(--border);
  font-size: 11.5px; line-height: 1.6; color: var(--text-2);
  white-space: pre-wrap; word-break: break-word;
  max-height: 150px; overflow: auto;
  font-family: var(--font-mono, ui-monospace, Consolas, monospace);
}

/* 结果网格：auto-fill 铺满，图多也不会一半空着 */
.ai-grid {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
}

/* 商品图片处的快捷作图浮层：左栏操作、右栏结果，两栏各自滚动，
   操作区不会被结果图撑得上下跳。 */
/* 它经常是从「采集箱详情 / 商品编辑」里点开的，必须压在那些弹窗之上
   （所有 .modal-mask 同为 60，DOM 靠后的会盖住靠前的）。 */
#aiQuickModal { z-index: 70; }
.ai-quick {
  display: grid; gap: 14px; min-height: 0;
  grid-template-columns: minmax(300px, 380px) minmax(0, 1fr);
}
.ai-quick-side {
  display: flex; flex-direction: column; gap: 10px; min-width: 0;
  max-height: 66vh; overflow: auto; padding-right: 4px;
}
.ai-quick-main {
  min-width: 0; max-height: 66vh; overflow: auto;
  border-left: 1px solid var(--border); padding-left: 14px;
}
.ai-quick-head {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  font-size: 12.5px; font-weight: 620; color: var(--text-2);
}
.ai-quick-thumbs { min-height: 0; }
.ai-quick-empty {
  margin: 0; font-size: 12.5px; line-height: 1.7; color: var(--text-3);
  padding: 18px; border: 1px dashed var(--border); border-radius: var(--radius-sm);
}
@media (max-width: 900px) {
  .ai-quick { grid-template-columns: minmax(0, 1fr); }
  .ai-quick-main { border-left: 0; padding-left: 0; max-height: none; }
  .ai-quick-side { max-height: none; }
}

.ai-card {
  display: flex; flex-direction: column;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); overflow: hidden;
}
.ai-card-img {
  display: block; width: 100%; aspect-ratio: 1 / 1;
  object-fit: contain; background: var(--surface-3);
}
.ai-card-body { display: flex; flex-direction: column; gap: 5px; padding: 9px 11px; min-width: 0; }
.ai-card-tag {
  align-self: flex-start; font-size: 11px; font-weight: 700;
  padding: 1px 6px; border-radius: 5px;
  background: var(--primary-soft); color: var(--primary-dark);
}
.ai-card-meta { font-size: 11px; color: var(--text-3); line-height: 1.55; overflow-wrap: anywhere; }
.ai-card-actions { display: flex; gap: 7px; align-items: center; flex-wrap: wrap; }
.ai-card-error {
  padding: 13px 12px; font-size: 12.5px; line-height: 1.6;
  color: #991b1b; background: var(--bad-soft);
  border-bottom: 1px solid #fecaca; overflow-wrap: anywhere;
  /* 审核类报错有三行建议，必须保留换行，否则挤成一片看不下去 */
  white-space: pre-line;
}

@media (max-width: 1080px) {
  .ai-layout { grid-template-columns: minmax(0, 1fr); }
  .ai-scene-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* 左栏底部这一行：比例下拉吃掉剩余宽度，「生成图片」保持原尺寸不被压扁。
   不这么写的话下拉会被 flex 挤到只能显示半个选项，看着像界面坏了。 */
.ai-side .toolbar { flex-wrap: nowrap; align-items: flex-end; }
.ai-side .toolbar .field { flex: 1 1 auto; min-width: 0; }
.ai-side .toolbar select { width: 100%; max-width: none; }
.ai-side .toolbar .btn { flex: 0 0 auto; }

/* =============================================================================
   20. 评审改造新增组件（2026-10-25）
   ============================================================================= */

/* 【评审 P0-4】利润页「缺成本」行动条。
   原来 568 个商品都没填成本，表里 5 列全是「—」，整页等于空转，用户会直接放弃这个功能。
   这里在表格上方摆一条带数字的提示，把「先补成本」这件事说清楚；
   列表本身仍按原样渲染（不隐藏、不过滤，交互口径不变）。 */
.callout {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 13px 16px; border-radius: var(--radius); margin: 0 0 12px;
  border: 1px solid var(--border); background: var(--surface-2);
  font-size: 12.5px; line-height: 1.7; color: var(--text-2);
}
.callout .ic {
  flex: none; width: 22px; height: 22px; border-radius: 7px;
  display: grid; place-items: center; font-size: 12.5px; font-weight: 800;
}
.callout .body { flex: 1 1 auto; min-width: 0; }
.callout b { color: var(--text); font-weight: 650; }
.callout.warn { background: var(--warn-soft); border-color: #f2ddb8; }
.callout.warn .ic { background: #fbe7c6; color: var(--warn); }
.callout.warn b { color: #8a4a06; }
.callout[hidden] { display: none; }

/* 待补成本的行：金额列是「—」不是 0，整行压暗一档，扫读时能区分「真的没数据」和「数据是 0」 */
tr.row-uncosted td { color: var(--text-3); }
tr.row-uncosted .cell-title { color: var(--text-2); }

/* 订单详情「怎么算的」分成两段：平台报表口径 / 我按费率预估。
   段头是 .settle-calc-seg —— 刻意不叫 .settle-calc-row，避免被行相关的样式和统计口径算进去。 */
.settle-calc-seg {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 13px 6px; font-size: 11.5px; font-weight: 700;
  letter-spacing: .04em; color: var(--text-3); text-transform: uppercase;
  background: var(--surface-2); border-bottom: 1px solid var(--border);
}
.settle-calc-seg::before {
  content: ''; width: 3px; height: 11px; border-radius: 2px; background: var(--primary); opacity: .55;
}
.settle-calc-seg.calc { background: transparent; }
/* 两套口径的差额：只在一行里说清，不再每行都解释一遍 */
.settle-calc-diff {
  padding: 8px 13px 10px; font-size: 12.5px; line-height: 1.6; color: var(--text-2);
  background: var(--surface-2); border-top: 1px dashed var(--border);
}
.settle-calc-diff b { color: var(--text); font-variant-numeric: tabular-nums; }

/* =============================================================================
   21. 深色模式（评审 P2-2）
   控制台原来没有深色模式，而浏览器扩展的浮窗是跟系统走的 ——
   系统深色下用户在 Ozon 页看到深色浮窗、点进控制台被闪一屏纯白。
   令牌已经集中，这里只覆盖令牌 + 少数几个写死的浅色值（表格行悬停、单元格描边、输入框底色）。
   ============================================================================= */
@media (prefers-color-scheme: dark) {
  :root {
    /* 深色 = 同一套墨蓝，把纸和墨对调：页面是深夜墨，卡片是略亮的墨面。
       侧栏保持 #0b2438，比卡片面更亮一档，层次还在。 */
    --bg: #061420;
    --bg-deep: #04101a;
    --surface: #0e2433;
    --surface-2: #12303f;
    --surface-3: #173a4c;
    --border: #1d3d52;
    --border-strong: #2a5570;
    --rule: #1d3d52;

    /* 单据材料在深夜环境里要重新配：墨线不改亮就会消失在底色里。
       --ink 不动（侧栏底 + 琥珀底上的字，恒为深墨）；--paper* 整组翻暗，当日间的浅底/悬停底用。 */
    --ink-rule: #2a5570;
    --on-ink: #f2efe6;
    --paper-2: #12303f;
    --paper-3: #0d2131;

    --text: #f2efe6;
    --text-1: #e6e1d4;
    --text-2: #b9c7d2;
    --text-3: #8fa3b2;
    --muted: #8fa3b2;
    --text-4: #7e93a3;

    /* 主按钮在深色下换成琥珀底 + 墨字（7.36:1）：墨底墨字在深夜背景上根本看不见 */
    --primary: #e8a33d;
    --primary-dark: #f0b45f;
    --primary-soft: #3a2c12;
    --brand: #e8a33d;
    --brand-2: #f0b45f;
    --amber: #e8a33d;
    --amber-text: #e8a33d;
    --amber-light: #f0b45f;
    --amber-soft: #3a2c12;

    --ok: #5fb98a;
    --ok-soft: #10302a;
    --bad: #e88a86;
    --bad-soft: #33191a;
    --warn: #e8a33d;
    --warn-soft: #33270f;
    --info: #7db3dd;
    --info-soft: #12283a;

    --shadow-xs: none;
    --shadow: none;
    --shadow-md: 0 2px 6px rgba(0, 0, 0, .45), 0 18px 40px -22px rgba(0, 0, 0, .9);
    --shadow-lg: 0 24px 70px -24px rgba(0, 0, 0, .9);
    --ring: 0 0 0 3px rgba(232, 163, 61, .28);
  }
  html, body { background: var(--bg); color: var(--text); }
  ::selection { background: rgba(232, 163, 61, .3); }

  /* 写死浅色的地方逐个补 */
  .data-table tbody tr:hover { background: #12303f; }
  .data-table td { border-bottom-color: #1d3d52; }
  .data-table th { background: var(--surface-2); }
  .data-table .btn-ghost { background: var(--surface); }
  .stat:hover { border-color: var(--border-strong); }
  .btn:hover:not(:disabled) { background: var(--surface-3); border-color: var(--border-strong); }
  input, select, textarea { background: var(--surface); color: var(--text); }
  input::placeholder, textarea::placeholder { color: #6f7d92; }
  .callout.warn { background: #33270f; border-color: #55411a; }
  .callout.warn .ic { background: #40300f; }
  .callout.warn b { color: #f0b45f; }
  .help-dot:hover { background: var(--primary-soft); }
  .settle-hero-metrics > div { background: var(--surface-2); }
  .modal, .drawer, .card { border-color: var(--border); }
  .toast { background: #0b1220; }
  .toast.ok { background: #06301f; }
  .toast.bad { background: #3a1214; }
  .toast.warn { background: #3a2a0c; }
  * { scrollbar-color: #3a4557 transparent; }
  *::-webkit-scrollbar-thumb { background: #3a4557; background-clip: content-box; }
  *::-webkit-scrollbar-thumb:hover { background: #4b5870; background-clip: content-box; }
}

/* 订单行内两个按钮：横向收紧一点，操作列刚好放下「详情 + 标记已处理」不折行。
   单元格左右各 12px 内边距 + 两个按钮 121px = 145px，所以列宽定 148px。 */
.order-act .btn-xs { padding: 0 6px; }

/* 订单表：10 列塞进 1202px，单元格内边距从 12px 收到 10px，换来不出现横向滚动 */
.table-orders td, .table-orders th { padding-left: 10px; padding-right: 10px; }

/* =============================================================================
   账号登录层（2026-10-26）
   -----------------------------------------------------------------------------
   登录之前整屏只有这一张卡片：业务页面的 DOM 虽然存在，但数据一条都不拉
   （见 app.js 的 boot()），所以这里不是「遮罩」，是真正的前置门。
   视觉沿用单证台：纸底 + 墨字 + 琥珀只做点缀，输入框 32px 高好点。
   ============================================================================= */
.auth-gate {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  overflow: auto;
  background:
    radial-gradient(circle at 18% 12%, rgba(201, 122, 14, .07), transparent 46%),
    repeating-linear-gradient(0deg, transparent 0 27px, rgba(11, 36, 56, .035) 27px 28px),
    var(--bg);
}
.auth-gate[hidden] { display: none; }

/* 左品牌 + 右表单。窄屏只留表单（品牌区是装饰，挡路就没意义了）。 */
.auth-stage {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 404px;
  width: min(1060px, 100%);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  box-shadow: 0 24px 62px rgba(11, 36, 56, .15);
  overflow: hidden;
}

.auth-hero {
  display: flex;
  flex-direction: column;
  padding: 32px 36px 28px;
  border-right: 1px solid var(--rule);
  background:
    radial-gradient(circle at 84% 8%, rgba(201, 122, 14, .1), transparent 52%),
    var(--surface-2);
}

.auth-logo { display: flex; align-items: center; gap: 10px; margin-bottom: 26px; }
.auth-logo .brand-mark { width: 36px; height: 36px; font-size: 12px; }
.auth-logo b { display: block; font-size: 13.5px; font-weight: 700; color: var(--text); letter-spacing: .02em; }
.auth-logo small { display: block; margin-top: 1px; font-size: 11px; color: var(--muted); }

.hero-title {
  margin: 0;
  font-size: 29px;
  font-weight: 700;
  line-height: 1.36;
  letter-spacing: -.01em;
  color: var(--text);
}
.hero-title em { font-style: normal; color: var(--amber-text); }
.hero-sub { margin: 10px 0 0; font-size: 13px; line-height: 1.6; color: var(--text-2); }

/* 插画吃掉中间的空白，卖点贴底：
   登录只要 3 个字段、注册要 6 个，两栏高度天然不一样，
   靠 flex 撑开比给每个模式写死高度可靠（写死过一次，换个字段数就露馅）。 */
.hero-art { flex: 1; display: flex; align-items: center; margin: 10px 0; color: var(--ink); }
.hero-art svg { display: block; width: 100%; max-width: 430px; height: auto; }

.hero-points {
  margin: auto 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.hero-points li { position: relative; padding-left: 15px; font-size: 12px; line-height: 1.65; color: var(--text-3); }
.hero-points li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 8px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--amber);
}

.auth-panel { display: flex; flex-direction: column; background: var(--surface); }

/* 页签贴着卡片上沿，代替原来那句「有开通码？点这里」的文案链接 —— 
   注册入口必须一眼看见，藏在正文里没人找得到（上一版就吃过这个亏）。 */
.auth-tabs {
  display: flex;
  justify-content: flex-end;
  gap: 2px;
  padding: 10px 14px 0;
  border-bottom: 1px solid var(--rule);
  background: var(--surface-2);
}
.auth-tabs button {
  padding: 8px 16px 9px;
  font: inherit;
  font-size: 12.5px;
  color: var(--muted);
  cursor: pointer;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
}
.auth-tabs button:hover { color: var(--text); }
.auth-tabs button.active {
  color: var(--ink);
  font-weight: 700;
  border-bottom-color: var(--ink);
}
.auth-tabs[hidden] { display: none; }

.auth-panel-body { display: flex; flex-direction: column; padding: 22px 26px 20px; }
.auth-panel-body h2 { margin: 0; font-size: 18px; font-weight: 700; color: var(--text); }
.auth-panel-body #authSub { margin: 5px 0 18px; font-size: 12px; line-height: 1.6; color: var(--muted); }

.auth-optional {
  margin-left: 4px;
  font-style: normal;
  font-weight: 400;
  font-size: 11px;
  color: var(--text-4);
}

@media (max-width: 880px) {
  .auth-stage { grid-template-columns: 1fr; width: min(430px, 100%); }
  .auth-hero { display: none; }
}

.auth-form { display: flex; flex-direction: column; gap: 12px; }
.auth-field { display: flex; flex-direction: column; gap: 5px; }
.auth-field > span { font-size: 11.5px; font-weight: 600; color: var(--text-2); letter-spacing: .02em; }
.auth-field > input {
  height: 34px;
  padding: 0 10px;
  font-size: 13px;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 3px;
  outline: none;
  transition: border-color .12s, box-shadow .12s;
}
.auth-field > input:focus {
  border-color: var(--ink);
  box-shadow: 0 0 0 2px rgba(11, 36, 56, .1);
}

/* 手机验证码 / 图形码：输入框 + 按钮并排。
   .auth-field 本身是纵向 flex，不套一层横向容器的话按钮会掉到下一行并撑满整宽，
   看着像两个互不相干的字段。 */
.auth-inline {
  display: flex;
  align-items: stretch;
  gap: 8px;
}

.auth-inline > input {
  flex: 1 1 auto;
  /* 少了 min-width:0，长内容会把 flex 项撑到比容器还宽，窄屏整行横向滚动 */
  min-width: 0;
  height: 34px;
  padding: 0 10px;
  font-size: 13px;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
}

.auth-inline > input:focus {
  outline: none;
  border-color: var(--ink);
  box-shadow: 0 0 0 2px rgba(11, 36, 56, .1);
}

/* 倒计时按钮：宽度靠 padding 撑，禁用时保留原位不跳动 */
.auth-mini {
  flex: 0 0 auto;
  height: 34px;
  padding: 0 12px;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  cursor: pointer;
  white-space: nowrap;
  /* 倒计时每秒变一次，比例数字能让按钮宽度不抖 */
  font-variant-numeric: tabular-nums;
}

.auth-mini:hover:not(:disabled) {
  border-color: var(--ink);
  background: var(--surface-2);
}

.auth-mini:disabled {
  color: var(--text-4);
  cursor: default;
}

/* 图形码本身是个按钮（点一下换一张），里面装的是服务端生成的 SVG。
   按 34px 高对齐输入框；SVG 的 viewBox 会等比缩，不变形。 */
.auth-captcha-img {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 34px;
  min-width: 96px;
  padding: 0;
  overflow: hidden;
  font-size: 11px;
  color: var(--text-4);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.auth-captcha-img:hover {
  border-color: var(--ink);
}

.auth-captcha-img svg {
  display: block;
  height: 34px;
  width: auto;
}

.auth-check { display: flex; align-items: flex-start; gap: 7px; font-size: 11.5px; color: var(--text-3); line-height: 1.5; cursor: pointer; }
.auth-check input { margin: 2px 0 0; width: 13px; height: 13px; accent-color: var(--ink); }

.auth-error {
  margin: 0;
  padding: 7px 10px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--bad);
  background: #fdf4f2;
  border-left: 3px solid var(--bad);
  border-radius: 2px;
}
.auth-error[hidden] { display: none; }

.auth-submit {
  height: 36px;
  margin-top: 2px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .04em;
  color: #fdfbf6;
  background: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 3px;
  transition: background .12s;
}
.auth-submit:hover:not(:disabled) { background: var(--primary-dark); }
.auth-submit:disabled { opacity: .6; cursor: not-allowed; }

.auth-foot {
  margin: 16px 0 0;
  padding-top: 12px;
  border-top: 1px dashed var(--rule);
  font-size: 11px;
  line-height: 1.6;
  color: var(--text-4);
}

/* 登录 ⇄ 开通 的切换。做成文字按钮：它是次要动作，
   不该跟主按钮抢注意力，但必须一眼看得见，否则没人知道这里能注册。 */
.auth-switch {
  margin: 14px 0 0;
  text-align: center;
}

.auth-switch button {
  background: none;
  border: 0;
  padding: 4px 6px;
  font: inherit;
  font-size: 12px;
  color: var(--amber);
  cursor: pointer;
  border-bottom: 1px dashed currentColor;
}

.auth-switch button:hover {
  color: var(--ink);
}

/* ---------------------------------------------------------------- 顶栏账号 */
.user-chip { position: relative; }
.user-btn {
  display: flex;
  align-items: center;
  gap: 7px;
  height: 30px;
  padding: 0 8px 0 4px;
  cursor: pointer;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 3px;
  transition: border-color .12s, background .12s;
}
.user-btn:hover { border-color: var(--border-strong); background: var(--surface-2); }
.user-avatar {
  display: grid;
  place-items: center;
  width: 22px; height: 22px;
  font-size: 10.5px; font-weight: 700;
  color: #f6efe0;
  background: var(--ink);
  border-radius: 2px;
  letter-spacing: .02em;
}
.user-meta { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.15; }
.user-meta b { font-size: 11.5px; font-weight: 600; color: var(--text); max-width: 92px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-meta i { font-size: 10px; font-style: normal; color: var(--amber-text); }
.user-caret { font-size: 9px; color: var(--muted); }

.user-pop {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 60;
  width: 172px;
  padding: 6px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 3px;
  box-shadow: 0 12px 26px rgba(11, 36, 56, .16);
}
.user-pop[hidden] { display: none; }
.user-pop-head {
  margin: 2px 4px 6px;
  padding-bottom: 6px;
  border-bottom: 1px dashed var(--rule);
  font-size: 11px;
  color: var(--muted);
  line-height: 1.5;
}
.user-pop-head b { display: block; font-size: 12px; color: var(--text); }
.user-pop-head i { font-style: normal; color: var(--amber-text); }
.user-pop button {
  display: block;
  width: 100%;
  padding: 6px 8px;
  text-align: left;
  font-size: 12px;
  color: var(--text);
  background: none;
  border: 0;
  border-radius: 2px;
  cursor: pointer;
}
.user-pop button:hover { background: var(--surface-3); }
.user-pop button[data-user-act="logout"]:hover { color: var(--bad); }

/* ---------------------------------------------------------------- 成员管理 */
.team-new {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  flex-wrap: wrap;
}
.team-new .field { min-width: 148px; }
.team-new .btn { height: 32px; margin-bottom: 1px; }

/* 运营角色看不到的东西：账号 / 店铺授权 / 成员管理。
   隐藏只是别让人点了才发现 403，真正的拦截在后端中间件。 */
body[data-role="operator"] [data-role="admin"] { display: none !important; }
/* 平台管理比「管理员」还窄：只有服务方那个账号（users.is_platform）看得见。
   用 :not 写而不是给 body 加类名 —— 没登录时 body 上什么都没有，
   这时同样不该露出入口。 */
body:not([data-platform="1"]) [data-platform] { display: none !important; }

/* 成员管理表格：角色下拉、状态胶囊、操作列三个按钮挤一行 */
.pill-off { background: var(--surface-3); border-color: var(--border); color: var(--text-4); }
.team-role { height: 26px; padding: 0 4px; font-size: 12px; }
.team-role:disabled { opacity: .55; }
.team-act { display: flex; gap: 6px; align-items: center; }
.team-self td { background: var(--amber-soft); }
.team-self td:first-child { box-shadow: inset 3px 0 0 var(--amber); }
.muted-cell { color: var(--text-4); }

/* 成员表里「我」这个小标跟用户名贴太紧，加一点间距 */
.data-table td.mono .pill { margin-left: 6px; vertical-align: 1px; }
