/* ========================================================================
   胜琪国际 · 快递客户端样式
   配色全部走 CSS 变量：默认浅色（白底），
   加 <html data-theme="dark"> 就切回原来的深蓝。
   --accent* 一组由 js/theme.js 按用户在「🎨 外观」里选的色写在 <html> 上。
   改色只动变量，不要去改下面的具体规则。
   ======================================================================== */
:root{
  /* ===== 中性色（默认 = 浅色）===== */
  --bg:#eef2f8;                   /* 页面底色 */
  --bg-deep:#e6edf7;              /* 页面底色（渐变深的一头）*/
  --panel:#ffffff;                /* 面板 / 弹窗 / 侧栏 / 顶栏 */
  --panel-2:#f6f9fd;
  --card:#ffffff;                 /* 卡片底 */
  /* 后台叫 --bg2，这里叫 --panel；两个名字都留下，共用组件（js/theme.js 的面板）才能两边通用 */
  --bg2:var(--panel);
  --line:#dbe3ef;                 /* 分隔线 / 描边 */
  --txt:#152a4a;                  /* 正文 */
  --txt-dim:#64748f;              /* 次要文字 */
  --fill:rgba(21,42,74,.045);     /* 输入框底 / 表头 / 极浅填充 */
  --fill-2:rgba(21,42,74,.075);   /* 悬停底 */
  --fill-3:rgba(21,42,74,.13);    /* 强一档（标签底 / 按下）*/
  --scroll:rgba(21,42,74,.22);
  --scroll-h:rgba(21,42,74,.38);
  --scrim:rgba(15,30,60,.45);     /* 弹窗遮罩 */
  --pop:0 12px 32px rgba(18,40,80,.16);
  --pop-2:0 20px 60px rgba(18,40,80,.22);
  --brand-glow:rgba(13,110,253,.10);
  --brand-glow-2:rgba(13,110,253,.08);
  --body-bg:radial-gradient(1200px 600px at 80% -10%,rgba(13,110,253,.07),transparent 60%),linear-gradient(160deg,var(--bg),var(--bg-deep));
  --sidebar-bg:linear-gradient(180deg,#ffffff,#f4f8fe);
  --topbar-bg:rgba(255,255,255,.74);
  --card-grad:linear-gradient(180deg,#ffffff,#f8fbff);
  --card-grad-2:linear-gradient(160deg,#ffffff,#f6faff);
  --panel-grad:linear-gradient(180deg,#ffffff,#f6f9fe);
  /* ===== 主色（由 js/theme.js 覆盖）===== */
  --accent:#0d6efd;
  --accent-text:#0d6efd;          /* 当文字 / 图标色用的主色 */
  --accent-ink:#ffffff;           /* 主色底上的文字色 */
  --accent-2:#0a58ca;             /* 压暗一档，做渐变用 */
  --accent-soft:rgba(13,110,253,.10);
  --accent-strong:rgba(13,110,253,.16);
  --accent-line:rgba(13,110,253,.38);
  /* 兼容旧写法（js 内联样式里用过 --cyan），统一指到主色 */
  --cyan:var(--accent-text);
  --cyan-dim:var(--accent-2);
  /* ===== 状态色 ===== */
  --ok:#16a34a;   --ok-soft:rgba(22,163,74,.10);  --ok-glow:rgba(22,163,74,.45);
  --danger:#dc2626; --danger-soft:rgba(220,38,38,.09); --danger-line:rgba(220,38,38,.38);
  --warn:#d97706; --warn-soft:rgba(217,119,6,.11);
  --radius:12px;
  /* 主内容区四周留白。⭐ 单独抽成变量是因为**吸底操作条要靠它**：
     sticky 的 bottom 是相对滚动容器的 padding box，写 0 会在屏幕底留出这一段缝，
     写 -24px（硬编码）又跟 padding 两处各写一遍 ⇒ 改一处忘一处。
     ⚠️ 两者必须同源：`.content` 的 padding 和 `.form-actions` 的 bottom 偏移。 */
  --content-pad:24px;
}
/* 深色主题 = 原来的样子，一个属性切回去 */
html[data-theme="dark"]{
  --bg:#0A1F44;
  --bg-deep:#061533;
  --panel:#0E2A55;
  --panel-2:#123360;
  --card:#0F2B56;
  --line:rgba(255,255,255,.08);
  --txt:#EAF2FF;
  --txt-dim:#8FA3C8;
  --fill:rgba(255,255,255,.04);
  --fill-2:rgba(255,255,255,.07);
  --fill-3:rgba(255,255,255,.12);
  --scroll:rgba(255,255,255,.15);
  --scroll-h:rgba(255,255,255,.25);
  --scrim:rgba(3,10,25,.7);
  --pop:0 12px 32px rgba(0,0,0,.45);
  --pop-2:0 20px 60px rgba(0,0,0,.5);
  --brand-glow:rgba(0,229,255,.14);
  --brand-glow-2:rgba(0,104,255,.12);
  --body-bg:radial-gradient(1200px 600px at 80% -10%,rgba(0,229,255,.12),transparent 60%),linear-gradient(160deg,var(--bg-deep),var(--bg));
  --sidebar-bg:linear-gradient(180deg,rgba(18,51,96,.6),rgba(6,21,51,.9));
  --topbar-bg:rgba(6,21,51,.4);
  --card-grad:linear-gradient(180deg,var(--card),rgba(15,43,86,.7));
  --card-grad-2:linear-gradient(160deg,var(--card),rgba(15,43,86,.6));
  --panel-grad:linear-gradient(180deg,var(--panel),rgba(18,51,96,.85));
  --ok:#2EE6A8;   --ok-soft:rgba(46,230,168,.12);  --ok-glow:rgba(46,230,168,.6);
  --danger:#FF5D6C; --danger-soft:rgba(255,93,108,.12); --danger-line:rgba(255,93,108,.4);
  --warn:#FFB84D; --warn-soft:rgba(255,184,77,.12);
  color-scheme:dark;
}
*{margin:0;padding:0;box-sizing:border-box}
html{color-scheme:light}
html,body{height:100%}
body{
  font-family:-apple-system,"PingFang SC","Microsoft YaHei","Segoe UI",sans-serif;
  background:var(--body-bg);
  color:var(--txt);
  font-size:14px;
  overflow:hidden;
  transition:background .18s,color .18s;
}
::-webkit-scrollbar{width:8px;height:8px}
::-webkit-scrollbar-thumb{background:var(--scroll);border-radius:4px}
::-webkit-scrollbar-thumb:hover{background:var(--scroll-h)}

/* ===== 布局骨架 ===== */
.app{display:flex;height:100vh}

/* ===== 侧边栏 ===== */
.sidebar{
  width:240px;min-width:240px;
  background:var(--sidebar-bg);
  border-right:1px solid var(--line);
  display:flex;flex-direction:column;
  transition:width .25s,min-width .25s;
  position:relative;z-index:20;
}
.sidebar.collapsed{width:64px;min-width:64px}
.logo{
  height:60px;display:flex;align-items:center;gap:10px;padding:0 18px;
  border-bottom:1px solid var(--line);flex-shrink:0;overflow:hidden;
}
.logo .mark{
  width:32px;height:32px;border-radius:8px;flex-shrink:0;
  background:linear-gradient(135deg,var(--accent),var(--accent-2));
  display:flex;align-items:center;justify-content:center;
  font-weight:800;font-size:15px;color:var(--accent-ink);
}
.logo .name{font-weight:700;font-size:16px;white-space:nowrap}
.logo .name small{display:block;font-size:10px;color:var(--txt-dim);font-weight:400}
.menu{flex:1;overflow-y:auto;padding:10px 0}
.menu-group{padding:4px 0}
.menu-item{
  display:flex;align-items:center;gap:12px;
  padding:0 18px;height:44px;cursor:pointer;position:relative;
  color:var(--txt-dim);transition:.15s;white-space:nowrap;user-select:none;
}
.menu-item .ico{width:20px;height:20px;flex-shrink:0;display:flex;align-items:center;justify-content:center}
.menu-item .ico svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.menu-item:hover{color:var(--txt);background:var(--fill)}
.menu-item.active{color:var(--accent-text);background:linear-gradient(90deg,var(--accent-soft),transparent)}
.menu-item.active::before{content:"";position:absolute;left:0;top:8px;bottom:8px;width:3px;border-radius:0 3px 3px 0;background:var(--accent)}
.menu-item .arrow{margin-left:auto;transition:.2s;width:14px;height:14px;flex-shrink:0}
.menu-item .arrow svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2}
.menu-item.open .arrow{transform:rotate(90deg)}
.menu-item .label{flex:1;overflow:hidden}
.submenu{max-height:0;overflow:hidden;transition:max-height .25s}
.submenu.open{max-height:500px}
.submenu a{
  display:flex;align-items:center;gap:8px;height:38px;padding:0 18px 0 50px;
  color:var(--txt-dim);cursor:pointer;text-decoration:none;white-space:nowrap;
  position:relative;transition:.15s;
}
.submenu a::before{content:"";width:4px;height:4px;border-radius:50%;background:currentColor;opacity:.5;flex-shrink:0}
.submenu a:hover{color:var(--txt)}
.submenu a.active{color:var(--accent-text)}
.collapsed .menu-item .label,.collapsed .menu-item .arrow,.collapsed .logo .name{display:none}
.collapsed .menu-item{padding:0;justify-content:center}
.collapsed .submenu{display:none}
.sidebar .foot{padding:14px;border-top:1px solid var(--line);flex-shrink:0}
.collapse-btn{
  height:40px;border-radius:8px;background:var(--fill);
  display:flex;align-items:center;justify-content:center;gap:8px;cursor:pointer;
  color:var(--txt-dim);transition:.15s;white-space:nowrap;overflow:hidden;
}
.collapse-btn:hover{color:var(--txt);background:var(--fill-3)}
.collapsed .collapse-btn span{display:none}

/* ===== 主区 ===== */
.main{flex:1;display:flex;flex-direction:column;min-width:0}
.topbar{
  height:60px;flex-shrink:0;display:flex;align-items:center;gap:16px;
  padding:0 24px;border-bottom:1px solid var(--line);
  background:var(--topbar-bg);backdrop-filter:blur(8px);
}
.topbar .crumb{font-size:15px;font-weight:600;display:flex;align-items:center;gap:8px}
.topbar .crumb .sub{color:var(--txt-dim);font-weight:400;font-size:13px}
.topbar .spacer{flex:1}
.search-box{
  display:flex;align-items:center;gap:8px;height:36px;padding:0 12px;
  background:var(--fill-2);border:1px solid var(--line);border-radius:8px;
  width:260px;transition:.2s;
}
.search-box:focus-within{border-color:var(--accent)}
.search-box input{background:none;border:none;outline:none;color:var(--txt);flex:1;font-size:13px}
.search-box svg{width:16px;height:16px;stroke:var(--txt-dim);fill:none;stroke-width:2}
.user{
  display:flex;align-items:center;gap:10px;padding:4px 10px 4px 4px;cursor:pointer;
  border-radius:8px;transition:.15s;
}
.user:hover{background:var(--fill-2)}
.user .avatar{
  width:32px;height:32px;border-radius:50%;flex-shrink:0;
  background:linear-gradient(135deg,var(--accent),var(--accent-2));
  display:flex;align-items:center;justify-content:center;font-weight:700;color:var(--accent-ink);
}
.user .info{line-height:1.2}
.user .info b{font-size:13px;display:block}
.user .info span{font-size:11px;color:var(--txt-dim)}

/* 顶栏动作按钮（🎨 外观 / 🚪 退出登录） */
.tb-actions{display:flex;align-items:center;gap:8px}
.tb-btn{
  display:inline-flex;align-items:center;gap:6px;height:34px;padding:0 12px;
  border-radius:8px;border:1px solid var(--line);background:var(--fill);
  color:var(--txt);font-size:13px;cursor:pointer;transition:.15s;white-space:nowrap;
}
.tb-btn:hover{background:var(--fill-3);border-color:var(--accent)}
.tb-btn.danger:hover{border-color:var(--danger);color:var(--danger);background:var(--danger-soft)}

.content{flex:1;overflow-y:auto;padding:var(--content-pad)}
.page{display:none}
.page.active{display:block;animation:fade .25s}
@keyframes fade{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}

/* ===== 通用组件 ===== */
.page-title{font-size:20px;font-weight:700;margin-bottom:4px}
.page-desc{color:var(--txt-dim);font-size:13px;margin-bottom:20px}
.card{
  background:var(--card-grad);
  border:1px solid var(--line);border-radius:var(--radius);padding:20px;
}
.grid{display:grid;gap:16px}
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  height:36px;padding:0 16px;border-radius:8px;border:1px solid var(--line);
  background:var(--fill);color:var(--txt);cursor:pointer;font-size:13px;
  transition:.15s;white-space:nowrap;
}
.btn:hover{background:var(--fill-3)}
.btn.primary{
  background:linear-gradient(135deg,var(--accent),var(--accent-2));border:none;color:var(--accent-ink);font-weight:600;
}
.btn.primary:hover{filter:brightness(1.1)}
.btn.ghost{background:transparent}
.btn.danger{border-color:var(--danger-line);color:var(--danger)}
.btn.danger:hover{background:var(--danger-soft)}
.btn.sm{height:30px;padding:0 12px;font-size:12px}
.btn svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}

.input,select.input,textarea.input{
  height:38px;padding:0 12px;border-radius:8px;border:1px solid var(--line);
  background:var(--fill);color:var(--txt);font-size:13px;outline:none;
  width:100%;transition:.15s;font-family:inherit;
}
textarea.input{height:auto;padding:10px 12px;resize:vertical;line-height:1.6}
.input:focus{border-color:var(--accent)}
.input::placeholder{color:var(--txt-dim)}
select.input{appearance:none;cursor:pointer}
select.input option{background:var(--panel);color:var(--txt)}
.form-label{font-size:13px;color:var(--txt-dim);margin-bottom:6px;display:block}
.form-label .req{color:var(--danger);margin-left:2px}
.form-item{margin-bottom:16px}

/* ===== 下单页「订单信息」：4 列等分、铺两行（2026-10-03 第98批 · 当天第二次改）=====
   上午那版是「24 列栅格、每格按内容跨格 ⇒ 7 个字段一行排完」；用户看完真机对照图（见
   test/_osgrid-proto.py 那四张 A/B/C/D）说：「订单信息一行还是太丑了，还是两行合适？」
   —— 在四个方案里当场选了「两行 · 全部等宽」。
   真机量出来的数字（1600px 宽，网格 1262px）：
     · 一行时每格 199px：「件数」那格里还要塞「输入框 + 录入材积按钮 + 状态小字」
       ⇒ 输入框只剩 **101px**，「是否保价」只剩 92px。
     · 折两行后每格 **305px**，件数框回到 207px（上排 4 格 + 下排 3 格，右下空一格）。
   ⭐ 所以这里是**纯 4 等分**，w-xs / w-sm / w-md 那套跨格分档**已删** ——
      想改回"按内容定宽"要先跟用户确认（他明确否过一次，别自己翻案）。
   ⚠️ 只管这一块（`.os-grid`）；「寄件信息」「收件信息」两块**一个字没动**（仍是 4 等分 + 行内样式）。 */
.os-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px;align-items:start;margin-bottom:8px}
.os-grid>.form-item{margin-bottom:0;min-width:0}
.os-grid>.form-item>.form-label{white-space:nowrap}

/* ===== 单票录入页专属：标签加粗变黑（2026-10-03 第98批 · 用户交办）=====
   用户原话：「还有那个单票录入里面的那个字段的字体啊，你帮我变成加粗黑体，
             更黑更粗一点，更黑一点。」
   改前：.form-label = 13px / font-weight:400 / 颜色 --txt-dim（浅色主题真机实测 rgb(100,116,143)，灰的）。
   改后：**700 加粗 + 颜色换 --txt**（实测 rgb(21,42,74)；深色主题自动跟着变，别写死色值）。
   ⚠️⚠️ 必须挂在 `.os-page` 下面，**不许**去改上面那条 `.form-label`：
      `.form-label` 是全站共用的（客户端「账户管理」「批量下单」、后台不少页都在用它），
      直接改 = 全站标签一起变粗变黑，而用户只要"单票录入这一页"。
      `.os-page` 是 js/order.js 那个页模板外面新包的一层，**只有这一页**有。
   ⚠️ 只管字，不管框：框的样式仍是 .input 那套。 */
.os-page .form-label{font-weight:700;color:var(--txt)}

/* ===== 件数右边那个「录入材积」按钮 + 状态小字（2026-10-03 第97批）=====
   为什么有它：件级尺寸原来在页面上**按件数一行一件铺开**，一票 50 件就铺 25 行、把整屏吃掉
   （用户原话：「我这一票 50 件、100 件，我要写多少个尺寸？这一个界面都看不着了。
             这要在那个件数后面加一个框，录入材积，然后跳出一个框。」）。
   现在页面只剩这一行，逐件那份表在弹窗里（见 js/order.js#osOpenVol）。
   ⚠️ 这一格是 w-md（span 4），件数框 + 按钮要挤着放下 ⇒ 按钮文字再长就会把件数框挤没，
      想改文字先真机量一次像素（span 之和恒等于 24，没有余量可让）。 */
.os-pieces-row{display:flex;align-items:center;gap:8px}
.os-pieces-row>.input{flex:1 1 auto;min-width:0}
.os-vol-btn{flex:0 0 auto;height:38px;padding:0 10px;border:1px solid var(--accent-line);
  border-radius:8px;background:var(--accent-soft);color:var(--accent-text);font-size:12px;
  cursor:pointer;white-space:nowrap}
.os-vol-btn:hover{background:var(--accent-strong)}
/* ⚠️⚠️ 这行小字**必须能折行**，不能 nowrap + 省略号（2026-10-03 真机量出来的）：
   它挤在「件数」那一格里（w-md = span 4，约 190px），而录完之后的内容是
   「✓ 已录 5/5 件 · 10×20×30（每件都一样） · 参考重量合计 4.00 kg」—— 约 330px。
   挂省略号的话**正好把「参考重量合计」那半截吃掉**（真机量到裁掉 156px），
   客户就永远看不到自己报的货大概多重 —— 那正是这一列存在的意义。
   折成两行只是这一格高一点，没有任何副作用。 */
.os-vol-state{margin-top:4px;font-size:12px;color:var(--txt-dim);line-height:1.4;
  overflow-wrap:anywhere}
.os-vol-state.on{color:var(--ok)}
.os-vol-state.warn{color:var(--warn)}
/* ⭐ 2026-10-10 第133批：产品没勾「支持多件」时，「件数」下面那行说明（见 js/order.js#osApplyPiecesLock）。
   ⚠️ 必须能**折行**（同 .os-vol-state 那条教训）—— 它挤在 w-md（span 4）那一格里，写 nowrap 会被省略号吞掉后半句。
   ⚠️ 颜色全走变量 ⇒ 暗色主题自动跟着变，别在这儿写死色值。 */
.os-lock-hint{margin-top:4px;font-size:12px;color:var(--warn);line-height:1.4;overflow-wrap:anywhere}

/* ===== 材积弹窗（第97批）=====
   挂在公共弹窗里（js/core.js#openDialog → #mask / .dialog）——**不另造遮罩**：
   自造的遮罩跳页时不会被收走（core.js#goto 只 closeDialog 关 #mask），会糊在屏幕上。
   ⚠️ 所有颜色都走变量 ⇒ 暗色主题自动跟着变，别在这儿写死色值。 */
.osvd .osvd-tools{display:flex;flex-wrap:wrap;gap:10px 16px;align-items:center;
  font-size:12px;color:var(--txt-dim);padding-bottom:12px;border-bottom:1px solid var(--line)}
.osvd .osvd-grp{display:flex;align-items:center;gap:6px}
/* ⚠️ 密集工具条里的控件一律**显式定尺寸**（项目铁律：.field 里放控件不写死宽高就会撑满/被裁） */
/* ⚠️ 密度 62px 是按「长 / 宽 / 高」这种两个字定的；「参考重量」是四个字（4×12 + 内边距 16 + 边框 2 ≈ 66px）
   ⇒ 62px 会把占位文字裁成「参考重」（2026-10-03 真机截图里一眼看见）。
   这一个给宽一点，别动其它三个（工具条本来就折两行，多 16px 不影响）。 */
.osvd .osvd-num{width:62px;height:30px;padding:0 8px;border:1px solid var(--line);border-radius:7px;
  background:var(--fill);color:var(--txt);font-size:12px;box-sizing:border-box}
.osvd .osvd-num.kg{width:78px}
.osvd .osvd-btn{height:30px;padding:0 10px;border:1px solid var(--line);border-radius:7px;
  background:var(--panel);color:var(--txt);font-size:12px;cursor:pointer;white-space:nowrap}
.osvd .osvd-btn:hover{background:var(--fill-2)}
.osvd .osvd-btn.pri{border-color:var(--accent-line);background:var(--accent-soft);color:var(--accent-text)}
.osvd .osvd-sep{width:1px;height:20px;background:var(--line)}
.osvd .osvd-paste{padding:12px 0;border-bottom:1px solid var(--line)}
.osvd .osvd-paste textarea{width:100%;height:84px;padding:9px 11px;border:1px solid var(--line);
  border-radius:8px;background:var(--fill);color:var(--txt);font-size:12px;box-sizing:border-box;
  resize:vertical;font-family:ui-monospace,Consolas,monospace}
.osvd .osvd-ph{font-size:12px;color:var(--txt-dim);line-height:1.7;margin-bottom:8px}
/* ⭐ 表格那块**自己滚**（不靠整个弹窗滚）⇒ 上面那排工具条一直看得见，改件数不用先滚回顶部。
   表头 sticky 一起跟上。 */
.osvd .osvd-body{max-height:46vh;overflow:auto;margin-top:12px}
.osvd .osvd-table{width:100%;border-collapse:collapse;font-size:13px}
.osvd .osvd-table th{position:sticky;top:0;background:var(--panel);text-align:left;font-weight:500;
  color:var(--txt-dim);font-size:12px;padding:8px 6px;border-bottom:1px solid var(--line);z-index:1}
.osvd .osvd-table td{padding:5px 6px;border-bottom:1px solid var(--line)}
.osvd .osvd-table .osvd-no{width:66px;color:var(--txt-dim);font-size:12px}
.osvd .osvd-table .osvd-op{width:132px;text-align:right;white-space:nowrap}
.osvd .osvd-table input{width:100%;height:32px;padding:0 9px;border:1px solid var(--line);
  border-radius:7px;background:var(--fill);color:var(--txt);font-size:13px;box-sizing:border-box}
.osvd .osvd-table input:focus{outline:none;border-color:var(--accent-line);background:var(--panel)}
.osvd .osvd-mini{border:0;background:transparent;color:var(--accent-text);font-size:12px;
  cursor:pointer;padding:2px 4px}
.osvd .osvd-mini:hover{text-decoration:underline}
/* 三边没填全的行描个淡黄底 —— 只是提示，**不拦提交**（箱规本来就是选填） */
.osvd tr.osvd-miss td{background:var(--warn-soft)}
.osvd .osvd-note{padding:10px 0 2px;font-size:12px;color:var(--txt-dim);line-height:1.75}
.osvd .osvd-note b{color:var(--txt)}
/* 底部合计靠左、两个按钮靠右（.d-foot 本来就是 flex-end） */
.osvd .osvd-sum{font-size:12px;color:var(--txt-dim);margin-right:auto}
.osvd .osvd-sum b{color:var(--ok)}

/* ===== 可搜索选择框（全项目唯一一份组件：admin/js/searchPick.js）=====
   下单页的「目的国家」「省 / 州」用它 —— 原生 <select> 在 264 个国家里只能一行行翻。
   类名 `.fpk*` 与后台 admin.css 里那份**同一套**，CSS 变量也同名，所以同一份 JS 两边都跑得起来。
   ⚠️ 大小按**客户端**的 .input 对齐（38px / 13px）；后台那套是表单网格里的 27px / 12px。 */
.fpk{position:relative;min-width:0}
.fpk-box{display:flex;align-items:center;gap:4px;flex-wrap:wrap;min-height:38px;padding:4px 12px;
  background:var(--fill);border:1px solid var(--line);border-radius:8px;cursor:text}
.fpk-box.open{border-color:var(--accent);background:var(--accent-soft)}
/* 校验没过时打的 .field-missing 落在**容器**上，而真正有边框的是里面那层 .fpk-box ⇒ 补这条 */
.fpk.field-missing .fpk-box{border-color:var(--danger) !important;background:var(--danger-soft) !important}
.fpk-tag{display:inline-flex;align-items:center;gap:4px;max-width:170px;padding:2px 8px;border-radius:999px;
  background:var(--accent-strong);color:var(--accent-text);font-size:12px;white-space:nowrap;overflow:hidden}
.fpk-tag>b{cursor:pointer;font-weight:400;opacity:.7;flex:0 0 auto}
.fpk-tag>b:hover{opacity:1}
.fpk-q{flex:1 1 60px;min-width:50px;width:auto;padding:2px 0;border:0;background:none;
  color:var(--txt);font-size:13px;line-height:20px;outline:none;font-family:inherit}
.fpk-q::placeholder{color:var(--txt-dim)}
.fpk-menu{position:absolute;left:0;right:0;top:calc(100% + 4px);z-index:80;max-height:250px;overflow:auto;
  padding:4px;background:var(--panel);border:1px solid var(--line);border-radius:8px;
  box-shadow:var(--pop)}
.fpk-item{display:flex;align-items:center;gap:6px;padding:6px 8px;border-radius:4px;font-size:13px;
  color:var(--txt);cursor:pointer;white-space:nowrap}
.fpk-item:hover{background:var(--fill-2)}
.fpk-item.on{color:var(--accent-text);background:var(--accent-soft)}
.fpk-name{overflow:hidden;text-overflow:ellipsis}
.fpk-desc{margin-left:auto;padding-left:10px;color:var(--txt-dim);font-size:12px;white-space:nowrap}
.fpk-empty{padding:10px;text-align:center;color:var(--txt-dim);font-size:12px}
.fpk-foot{padding:6px 8px;margin-top:2px;border-top:1px solid var(--line);color:var(--txt-dim);font-size:12px}
/* 分类标签条（2026-10-05 第99批 · 运输方式面板）：渲染在 .fpk-menu **顶部**，
   且 position:sticky —— menu 本身 max-height:250px + overflow:auto，候选一多标签就滚走了，
   用户会找不到分类（"热门"必须始终看得见）。
   ⚠️ 只有 mount 时传了 tabs 的选择框才渲染这块；国家 / 省州 / 后台那几个框**一个字不变**。 */
.fpk-tabs{display:flex;flex-wrap:wrap;gap:6px;padding:6px 8px;position:sticky;top:0;z-index:1;
  background:var(--panel);border-bottom:1px solid var(--line)}
.fpk-tab{cursor:pointer;padding:3px 10px;border-radius:999px;font-size:12px;line-height:16px;
  color:var(--txt-dim);background:var(--fill-2);white-space:nowrap}
.fpk-tab:hover{color:var(--txt)}
.fpk-tab.on{color:var(--accent-text);background:var(--accent-soft);font-weight:600}

/* 统计卡片 */
.stat-cards{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:20px}
.stat-card{
  background:var(--card-grad-2);
  border:1px solid var(--line);border-radius:var(--radius);padding:18px;
  position:relative;overflow:hidden;
}
.stat-card::after{
  content:"";position:absolute;right:-20px;top:-20px;width:90px;height:90px;border-radius:50%;
  background:radial-gradient(circle,var(--brand-glow),transparent 70%);
}
.stat-card .label{font-size:13px;color:var(--txt-dim);margin-bottom:8px}
.stat-card .value{font-size:28px;font-weight:800;letter-spacing:.5px}
.stat-card .value .unit{font-size:13px;font-weight:400;color:var(--txt-dim);margin-left:4px}
.stat-card .trend{font-size:12px;margin-top:8px}
.stat-card .trend.up{color:var(--ok)}
.stat-card .trend.down{color:var(--danger)}
.stat-card .ico{
  position:absolute;right:16px;top:16px;width:34px;height:34px;border-radius:8px;
  display:flex;align-items:center;justify-content:center;
}
.stat-card .ico svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}

/* 表格 */
.table-wrap{overflow-x:auto}
table{width:100%;border-collapse:collapse;font-size:13px}
th,td{text-align:left;padding:12px 14px;border-bottom:1px solid var(--line);white-space:nowrap}
th{color:var(--txt-dim);font-weight:500;background:var(--fill)}
tbody tr{transition:.15s}
tbody tr:hover{background:var(--fill)}
td .num{font-variant-numeric:tabular-nums}

/* 标签 */
.tag{display:inline-flex;align-items:center;gap:4px;height:22px;padding:0 8px;border-radius:11px;font-size:12px}
.tag::before{content:"";width:5px;height:5px;border-radius:50%;background:currentColor}
.tag.cyan{color:var(--accent-text);background:var(--accent-soft)}
.tag.ok{color:var(--ok);background:var(--ok-soft)}
.tag.warn{color:var(--warn);background:var(--warn-soft)}
.tag.danger{color:var(--danger);background:var(--danger-soft)}
.tag.gray{color:var(--txt-dim);background:var(--fill-2)}

/* 快捷入口 */
.quick-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-top:20px}
.quick-item{
  background:var(--card-grad-2);
  border:1px solid var(--line);border-radius:var(--radius);padding:18px;cursor:pointer;
  transition:.15s;display:flex;align-items:center;gap:14px;
}
.quick-item:hover{border-color:var(--accent);transform:translateY(-2px)}
.quick-item .q-ico{
  width:42px;height:42px;border-radius:10px;flex-shrink:0;
  background:var(--accent-soft);color:var(--accent-text);
  display:flex;align-items:center;justify-content:center;
}
.quick-item .q-ico svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.quick-item b{display:block;font-size:14px;margin-bottom:3px}
.quick-item span{font-size:12px;color:var(--txt-dim)}

/* 图表占位 */
.chart-box{height:260px;border-radius:var(--radius);position:relative}
.bars{display:flex;align-items:flex-end;gap:12px;height:200px;padding:0 8px}
.bar-col{flex:1;display:flex;flex-direction:column;align-items:center;gap:8px;height:100%;justify-content:flex-end}
.bar{width:100%;max-width:40px;border-radius:6px 6px 0 0;background:linear-gradient(180deg,var(--accent),var(--accent-2));transition:.3s;position:relative}
.bar:hover{filter:brightness(1.2)}
.bar .val{position:absolute;top:-20px;left:50%;transform:translateX(-50%);font-size:11px;color:var(--accent-text)}
.bar-col .x{font-size:11px;color:var(--txt-dim)}

/* 弹窗 */
.mask{position:fixed;inset:0;background:var(--scrim);backdrop-filter:blur(3px);z-index:100;display:none;align-items:center;justify-content:center}
.mask.show{display:flex}

/* ====== 报关信息表：**一条明细一行** + 横向拖动（用户 2026-09-18）======
   ⚠️ `table-layout:fixed` 是必须的：列宽认 <th> 上写死的 width，长内容不会把列撑开。
      少了它 ⇒ 横滚宽度失控、列头与数据错位（本项目"宽表"踩过的老坑）。 */
.cargo-table{table-layout:fixed;width:100%}
.cargo-table th{padding:8px;font-size:12px;font-weight:500;color:var(--txt-dim);background:var(--fill);white-space:nowrap}
.cargo-table td{padding:6px 8px;vertical-align:middle;white-space:nowrap}
.cargo-table tbody tr{border-bottom:1px solid var(--line)}
.cargo-table tbody tr:last-child{border-bottom:0}
/* 表格里的输入框/下拉要**显式写全** —— 少写一项就落回浏览器默认样式（2px inset 的立体感） */
.cargo-table .input,
.cargo-table select.input{
  height:34px;padding:0 8px;font-size:12px;border-radius:6px;width:100%;
  border:1px solid var(--line);box-shadow:none;appearance:none;
  background:var(--fill);color:var(--txt);
}
.cargo-table .input:focus{border-color:var(--accent)}
.cargo-table .ci-no{text-align:center;color:var(--txt-dim);font-size:12px;font-variant-numeric:tabular-nums}
.cargo-table .ci-price-box{display:flex;gap:6px}
.cargo-table .ci-price-box .ci-price{flex:1;min-width:0}
/* 申报币种（2026-10-10 第130批）：单价框缩窄、右边接一个币种下拉
   （用户原话「那个单价框也大，把单价的框缩小一点，然后后面再加一个币种」）。
   宽度**写死**给下拉、`flex:1` 留给单价 ⇒ 单价自然变窄（不用改列宽，表宽一点没变）。
   ⚠️ 这里必须补一个箭头图标：`.cargo-table .input` 上有 `appearance:none`，原生箭头被去掉了
      （现有 `.ci-template` 那个下拉也这样）—— 不补的话它长得像个文本框，客户不点不知道能选。 */
.cargo-table .ci-price-box .ci-currency{
  flex:none;width:88px;padding-right:20px;
  background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'%3E%3Cpath d='M2 3.5L5 6.5L8 3.5' fill='none' stroke='%23888' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 6px center;text-overflow:ellipsis;
}
/* 总价：表里只留文字 —— 原来那颗 accent 胶囊在表格里会把整行撑肿 */
.cargo-table .cargo-total{
  display:block;height:auto;padding:0;background:transparent;border:0;
  font-size:13px;font-weight:700;color:var(--accent-text);
  line-height:34px;font-variant-numeric:tabular-nums;
}
.cargo-table .ci-ops{text-align:center}
.cargo-table .ci-del{
  display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;
  border-radius:6px;border:1px solid var(--danger-line);color:var(--danger);
  background:transparent;cursor:pointer;transition:.15s;
}
.cargo-table .ci-del:hover{background:var(--danger-soft)}
.cargo-table .ci-del svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
/* 横向滚动条做得明显一点（用户 2026-09-18：「带进度条一样的，我可以往后拉」） */
#cargoList .table-wrap{padding-bottom:2px}
#cargoList .table-wrap::-webkit-scrollbar{height:10px}
#cargoList .table-wrap::-webkit-scrollbar-track{background:var(--fill);border-radius:5px}
#cargoList .table-wrap::-webkit-scrollbar-thumb{background:var(--scroll);border-radius:5px}
#cargoList .table-wrap::-webkit-scrollbar-thumb:hover{background:var(--scroll-h)}

/* ====== 可收起区块（寄件信息默认收起，用户 2026-09-18）======
   ⭐ "默认收起"就写在这里：`.sec-body` 不带 `.open` 就是隐藏的。
      不靠"渲染完再跑一段 JS 设一次" —— 那样页面会先展开再收起来（闪一下）。 */
.sec-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:18px 0 12px;cursor:pointer;user-select:none}
.sec-head .sec-arrow{font-size:11px;color:var(--txt-dim);transition:transform .18s;display:inline-block}
.sec-head.open .sec-arrow{transform:rotate(90deg)}
.sec-head .sec-title{font-size:15px;font-weight:700;color:var(--accent-text)}
.sec-head .sec-sub{font-size:12px;color:var(--txt-dim)}
.sec-head .sec-spacer{flex:1}
.sec-head:hover .sec-title{text-decoration:underline;text-underline-offset:3px}
.sec-body{display:none}
.sec-body.open{display:block}
/* 不需要收起的区块标题（报关信息） */
.sec-row{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;margin:18px 0 10px}
.sec-row .sec-title{font-size:15px;font-weight:700;color:var(--accent-text)}
.sec-row .sec-sub{font-size:12px;color:var(--txt-dim)}

/* ====== 操作条吸底：页面再长也不用滚到底才能保存（用户 2026-09-18）======
   负 margin 抵消 `.card` 的 20px 内边距 ⇒ 操作条横贯整张卡片、贴住卡片底边。
   ⚠️ bottom 用 `calc(-1 * var(--content-pad))` 而不是 0：sticky 的 bottom 相对滚动容器的
      padding box，写 0 会在屏幕最底下留出 24px 的缝（实测 faBottom=876 / viewH=900），
      看着像"按钮浮在半空"；负偏移才真正贴到屏幕底边。**与 .content 的 padding 同源。** */
.form-actions{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  position:sticky;bottom:calc(-1 * var(--content-pad));z-index:6;
  margin:20px -20px -20px;padding:14px 20px;
  background:var(--panel);border-top:1px solid var(--line);
  border-radius:0 0 var(--radius) var(--radius);
  /* 向上投一点阴影：让它明显是"浮在内容之上的一条工具条"，
     而不是"插在表单中间的按钮"（内容长于视口时它必然盖住后面一段，滚一下就能看到） */
  box-shadow:0 -6px 18px rgba(18,40,80,.10);
}
.form-actions .fa-hint{font-size:12px;color:var(--txt-dim);margin-left:auto}
/* 校验没过时被点名的框：标红，用户一动手就由 JS 摘掉 */
.field-missing, .field-missing:focus{border-color:var(--danger) !important;background:var(--danger-soft) !important}
.add-cargo-btn{
  display:flex;align-items:center;justify-content:center;gap:6px;width:100%;height:42px;
  border-radius:8px;border:1px dashed var(--accent-line);color:var(--accent-text);background:transparent;
  cursor:pointer;font-size:13px;transition:.15s;margin-top:4px;
}
.add-cargo-btn:hover{background:var(--accent-soft)}
.add-cargo-btn svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}

/* 订单管理：状态筛选标签 */
.status-tabs{display:flex;flex-wrap:wrap;gap:8px;margin:16px 0}
.status-tab{
  padding:6px 14px;border-radius:6px;font-size:13px;cursor:pointer;
  background:var(--fill);border:1px solid var(--line);color:var(--txt-dim);
  transition:.15s;display:flex;align-items:center;gap:6px;
}
.status-tab:hover{color:var(--txt);background:var(--fill-3)}
.status-tab.active{background:var(--accent-soft);border-color:var(--accent-line);color:var(--accent-text)}
.status-tab .badge{font-size:11px;padding:1px 6px;border-radius:10px;background:var(--fill-3);color:var(--txt)}
.status-tab.active .badge{background:var(--accent-strong);color:var(--accent-text)}
.dialog{
  width:520px;max-width:92vw;max-height:88vh;overflow-y:auto;
  background:var(--panel);border:1px solid var(--line);border-radius:14px;
  box-shadow:var(--pop-2);animation:pop .2s;
}
.dialog.lg{width:760px}
@keyframes pop{from{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}
.dialog .d-head{display:flex;align-items:center;justify-content:space-between;padding:18px 22px;border-bottom:1px solid var(--line)}
.dialog .d-head h3{font-size:16px}
.dialog .d-close{cursor:pointer;color:var(--txt-dim);transition:.15s;display:flex}
.dialog .d-close:hover{color:var(--txt)}
.dialog .d-close svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:2}
.dialog .d-body{padding:22px}
.dialog .d-foot{display:flex;justify-content:flex-end;gap:10px;padding:16px 22px;border-top:1px solid var(--line)}

/* 轨迹时间线 */
.timeline{position:relative;padding-left:24px}
.timeline::before{content:"";position:absolute;left:7px;top:6px;bottom:6px;width:2px;background:var(--line)}
.tl-item{position:relative;padding-bottom:22px}
.tl-item:last-child{padding-bottom:0}
.tl-item .dot{position:absolute;left:-22px;top:4px;width:14px;height:14px;border-radius:50%;background:var(--panel);border:3px solid var(--accent)}
.tl-item.latest .dot{border-color:var(--ok);box-shadow:0 0 8px var(--ok-glow)}
.tl-item .tl-time{font-size:12px;color:var(--txt-dim);margin-bottom:3px}
.tl-item .tl-title{font-size:14px;font-weight:600;margin-bottom:2px}
.tl-item .tl-desc{font-size:12px;color:var(--txt-dim)}

/* 响应式 */
@media(max-width:900px){
  .stat-cards,.quick-grid{grid-template-columns:repeat(2,1fr)}
}
@media(max-width:768px){
  .sidebar{position:fixed;left:0;top:0;bottom:0;transform:translateX(-100%);transition:transform .25s}
  .sidebar.mobile-show{transform:translateX(0)}
  .search-box{display:none}
  .stat-cards,.quick-grid{grid-template-columns:1fr}
  .topbar{padding:0 14px;gap:10px}
  .tb-btn span{display:none}      /* 窄屏只留图标，别把顶栏挤爆 */
  .tb-btn{padding:0 10px}
  .user .info{display:none}
}
.hamburger{display:none;cursor:pointer;color:var(--txt)}
.hamburger svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:2}
@media(max-width:768px){.hamburger{display:flex}}

/* ===== 登录页 ===== */
.login-page{display:none;height:100vh;align-items:center;justify-content:center;position:relative}
.login-page.show{display:flex}
.login-bg{position:absolute;inset:0;overflow:hidden;pointer-events:none}
.login-bg::before{content:"";position:absolute;width:600px;height:600px;border-radius:50%;background:radial-gradient(circle,var(--brand-glow),transparent 70%);top:-200px;right:-100px}
.login-bg::after{content:"";position:absolute;width:500px;height:500px;border-radius:50%;background:radial-gradient(circle,var(--brand-glow-2),transparent 70%);bottom:-150px;left:-120px}
.login-box{
  position:relative;z-index:2;width:400px;max-width:92vw;
  background:var(--panel-grad);
  border:1px solid var(--line);border-radius:16px;padding:40px 36px;
  box-shadow:var(--pop-2);animation:pop .3s;
}
.login-box .lb-mark{
  width:56px;height:56px;border-radius:14px;margin:0 auto 18px;
  background:linear-gradient(135deg,var(--accent),var(--accent-2));
  display:flex;align-items:center;justify-content:center;
  font-size:26px;font-weight:800;color:var(--accent-ink);
}
.login-box h1{font-size:20px;text-align:center;margin-bottom:6px}
.login-box .sub{font-size:13px;color:var(--txt-dim);text-align:center;margin-bottom:28px}
.login-box .form-item{margin-bottom:18px}
.login-box .btn{width:100%;height:42px;margin-top:6px}
.login-hint{margin-top:18px;text-align:center;font-size:12px;color:var(--txt-dim);line-height:1.8}
.login-error{background:var(--danger-soft);color:var(--danger);font-size:12.5px;padding:10px 12px;border-radius:8px;margin-bottom:16px;display:none}

/* ====== 订单管理：上钉住 / 中滚动 / 下钉住（2026-09-26 第72批 · 用户交办）======
   用户原话：「往下拉的时候，上面那个筛选部分都被拉得看不到了……能不能把这些上面这些东西
   放固定，我拉的时候只拉下面那个表格的界面，他们在滚动，上面的也不滚动。还有在最下面
   显示条数那个共多少条记录……就是表头和表尾就相当于这个意思，都是固定的，里面的条数在滚动。」

   做法：这一页**不再让 .content 整页滚** —— 页面自己是一根撑满可见区的 flex 竖列，
   头(.ol-head)、尾(.ol-foot) 都是 flex:none，只有中间 (.ol-body) flex:1 + overflow:auto。
   ⚠️ 为什么不用 position:sticky 去钉头部：这一页 17 列要**横向**滚，sticky 表头的 top 得等于
      "上方那块的实际高度"，而它会随窗口宽度换行而变 ⇒ 列头会飘、会叠字。
      改成"内部滚动容器"后，列头的 sticky top:0 是相对**这一块**的，永远准。
   ⚠️ 表头背景必须是**不透明**的 var(--card)：全局 --fill 是半透明的
      （浅色 rgba(21,42,74,.045) / 深色 rgba(255,255,255,.04)），行会从表头底下透出来。
   ⚠️ .card.ol-body 用双类名：`.card` 给的是 --card-grad 渐变，这里要纯色底板
      （表头要和卡片底色**一模一样**才看不出接缝），双类名才稳。 */
.ol-page{height:100%;display:flex;flex-direction:column;min-height:0}
.ol-head{flex:none}
.card.ol-body{
  flex:1 1 auto;min-height:200px;min-width:0;
  padding:0;overflow:hidden;display:flex;flex-direction:column;background:var(--card);
}
.ol-body .table-wrap{flex:1 1 auto;min-height:0;overflow:auto}
.ol-body thead th{position:sticky;top:0;z-index:2;background:var(--card);box-shadow:inset 0 -1px 0 var(--line)}
.ol-foot{
  flex:none;display:flex;justify-content:space-between;align-items:center;
  gap:12px;flex-wrap:wrap;padding:12px 2px 0;color:var(--txt-dim);font-size:12px;
}
.ol-foot .ol-pager{display:flex;align-items:center;gap:8px}
.ol-foot select.input{width:auto;height:30px;padding:0 8px;font-size:12px}
.ol-sel-hint{font-size:12px;color:var(--txt-dim);white-space:nowrap}
.ol-sel-hint b{color:var(--accent-text)}
/* 按钮禁用态：以前全站没写，靠浏览器默认（很淡、几乎看不出"这是不能用"）——
   底栏的「上一页/下一页」和工具栏的「清空勾选」都要靠它说清"现在点了没用"。 */
.btn:disabled{opacity:.45;cursor:not-allowed}
