/* ============ 线路智能调度系统 样式 ============ */
* { margin:0; padding:0; box-sizing:border-box; }
:root{
  --pri:#1a66ff; --pri-d:#0f4fd0; --bg:#f2f4f8; --card:#fff; --line:#e2e6ee;
  --txt:#222b3a; --sub:#6b7590; --ok:#16a34a; --warn:#d97706; --err:#dc2626;
}
/* v1.0.313:设计令牌(皮肤系统)—— 语义色集中在此,各皮肤只需覆盖这些变量 */
:root{
  /* 表面与底色 */
  --bg-soft:#f7f9fc;      /* 表头/浅底 */
  --bg-hover:#f7faff;     /* 行/项悬停 */
  --bg-sel:#e8f0ff;       /* 选中行/选中项 */
  --bg-tint:#eef4ff;      /* 淡蓝点缀(按钮悬停/浅色块) */
  --bg-elev:#fafcff;      /* 略高于底色的面板 */
  --bg-mute:#f6f7f9;      /* 灰度行(未解析经纬度) */
  --bg-mute-hover:#eef1f6;
  --line-strong:#c9d6f2;  /* 描边加强 */
  --track:#e3e9f4;        /* 进度条轨道 */
  --focus-ring:#c9dcff;   /* 输入聚焦光圈 */
  --overlay:rgba(255,255,255,.96);   /* 地图全屏浮层底 */
  --toast-bg:#222b3a;
  /* 文字层级 */
  --ink-2:#334;           /* 次级正文 */
  --sub-2:#9aa8c4;        /* 弱提示/拖柄 */
  --sub-3:#c3cbd9;        /* 更弱(排序灰箭头) */
  --on-accent:#fff;       /* 主色/深底上的文字 */
  /* 语义色扩展 */
  --pri-2:#0a66c2;        /* 主色深阶(链接/图标描边) */
  --pri-lite:#7aa7ff;     /* 主色浅阶(头像渐变) */
  --ok-bg:#e6f7ec; --warn-bg:#fef3e2; --err-bg:#fee8e8;
  --ok-ink:#0d6e3f;        /* v1.0.415:成功/已指定·最优 的文字色(原先在 JS 里写死,已收敛为令牌) */
  --warn-ink:#b45309; --warn-line:#f0c36d;
  --accent2:#e07c00; --accent2-ink:#b36a00; --accent2-bg:#fff6e8;
  --mark:#f0b429; --mark-ink:#5b3a00; --mark-bg:#fffbea;   /* 选中线路高亮 */
  --pin-off:#b9c6dd;
  /* 形状与阴影(皮肤可改) */
  --r-sm:8px; --r-md:10px; --r-lg:12px; --r-xl:14px; --r-pill:20px;
  --shadow-1:0 1px 4px rgba(0,0,0,.18);
  --shadow-2:0 4px 14px rgba(0,0,0,.18);
}
html,body{ height:100%; }
body{ font-family:"Microsoft YaHei","PingFang SC",system-ui,sans-serif; background:var(--bg); color:var(--txt); font-size:14px; }
#topbar{ display:flex; align-items:center; gap:18px; background:var(--card); padding:8px 16px; border-bottom:1px solid var(--line); position:sticky; top:0; z-index:1000; }
.brand{ display:flex; align-items:center; gap:10px; }
.brand .logo{ font-size:26px; }
.brand h1{ font-size:17px; }
.brand .sub{ font-size:11px; color:var(--sub); }
#nav{ display:flex; gap:4px; flex:1; justify-content:center; flex-wrap:wrap; }
#nav button{ border:0; background:transparent; padding:8px 14px; border-radius:8px; cursor:pointer; font-size:14px; color:var(--txt); }
#nav button:hover{ background:var(--bg-tint); }
#nav button.active{ background:var(--pri); color:var(--on-accent); }
#authBox{ display:flex; align-items:center; gap:8px; }
.badge{ background:var(--bg-tint); color:var(--pri); padding:4px 10px; border-radius:20px; font-size:12px; }
.badge.soon{ background:var(--warn-bg); color:var(--warn); }
.badge.pro{ background:var(--ok-bg); color:var(--ok); }
.badge.expired{ background:var(--err-bg); color:var(--err); }

#main{ padding:16px; max-width:1400px; margin:0 auto; }
/* v1.0.379:身份提示条(游客 / 微信 / 注册登记 / 公司账号)—— 可见但不挡路:
 * 一条细横条,不 fixed、不覆盖任何内容、不遮按钮,只把「当前身份 + 能用什么 + 还剩多少天 + 到期怎么办」讲清楚。
 * 颜色只用设计令牌(--info/--warn/--err 与各自的 *-bg),5 套皮肤(含深色)自动适配。 */
.access-notice{
  display:flex; align-items:flex-start; gap:10px; flex-wrap:wrap;
  border:1px solid var(--line); border-left:4px solid var(--pri);
  background:var(--card); border-radius:10px; padding:8px 10px; margin-bottom:12px;
  font-size:12.5px; line-height:1.6;
  min-width:0; max-width:100%; overflow-wrap:anywhere; word-break:break-word;   /* v1.0.383:额度/限制说明是必须读的,长无空格串也不许顶出右边界 */
}
.access-notice .an-badge{ flex:0 0 auto; font-weight:700; padding:2px 8px; border-radius:20px; background:var(--bg-tint); color:var(--pri); white-space:nowrap; }.access-notice .an-body{ flex:1 1 320px; min-width:0; color:var(--txt); overflow-wrap:anywhere; word-break:break-word; }
.access-notice .an-limit{ color:var(--sub); }
/* v1.0.381:额度那一行(「任务单 N/M 条 · 今天智能调度 N/M 次」)—— **要高亮、要可扫读**:
 * 单独一段、加内边距与圆角、数字加粗,默认用中性高亮(--bg-tint + --pri);
 * 接近上限时整行转 warn 配色、已满转 err 配色(与提示条左边框同色系,一眼分得清"预警"和"已满")。
 * 只改外观:额度拦不拦、怎么算都由 js/auth.js 的 quotaState()/quotaPlanGate() 决定(行为可断言)。 */
.access-notice .an-quota{
  display:inline-block; margin-top:3px; padding:1px 8px; border-radius:8px;
  background:var(--bg-tint); color:var(--pri); font-weight:700; border:1px solid var(--line);
  max-width:100%; overflow-wrap:anywhere; word-break:break-word;   /* v1.0.383:额度说明是必须读的,不许被裁 */
}
.access-notice.an-warn .an-quota{ background:var(--warn-bg); color:var(--warn); border-color:var(--warn); }
.access-notice.an-err .an-quota{ background:var(--err-bg); color:var(--err); border-color:var(--err); }
.access-notice .an-how{ color:var(--pri); font-weight:700; }
.access-notice .an-hide{ flex:0 0 auto; border:1px solid var(--line-strong); background:transparent; color:var(--sub); border-radius:6px; padding:1px 8px; font-size:11.5px; cursor:pointer; }
.access-notice .an-hide:hover{ color:var(--txt); }
/* ★ v1.0.421:车型库「温度能力自动补全」的告知条。
 * 为什么要单独一个类而不是内联样式:项目有 5 套皮肤(含深色),写死色值会串味
 *   (`test_node` 的「颜色棘轮」断言把写死十六进制色钉成只减不增) ⇒ 一律走设计令牌。
 * 视觉与 .access-notice 同族:左侧 4px 提示色竖条 + 淡底,不遮挡任何按钮。 */
.veh-temp-notice{
  display:flex; align-items:flex-start; gap:8px; flex-wrap:wrap;
  border:1px solid var(--line); border-left:4px solid var(--warn);
  background:var(--warn-bg); color:var(--warn-ink);
  border-radius:8px; padding:7px 10px; margin-top:6px;
  font-size:12.5px; line-height:1.7;
  min-width:0; max-width:100%; overflow-wrap:anywhere; word-break:break-word;
}
.veh-temp-notice b{ color:var(--warn-ink); }
/* v1.0.676:页面版本与服务器不一致时的顶部提示条(颜色只用设计令牌) */
.ver-mismatch-bar{ position:fixed; left:0; right:0; top:0; z-index:9999; text-align:center;
  padding:8px 12px; font-size:13px; line-height:1.5;
  background:var(--warn-bg); color:var(--warn-ink); border-bottom:1px solid var(--warn-line); }
.ver-mismatch-bar b{ color:var(--warn-ink); }
.ver-mismatch-bar a{ margin-left:10px; color:var(--warn-ink); text-decoration:underline; }
.veh-temp-notice .vtn-name{ font-weight:400; }
/* ★ v1.0.421:「温度类型」「双温组合」的**多选复选框组**(车型库表单、车辆档案、任务单表单共用)。
 * 为什么单独一类而不是内联样式:项目有 5 套皮肤(含深色),写死色值会串味,
 * test_node 的「颜色棘轮」把写死十六进制色钉成只减不增 ⇒ 一律走设计令牌。
 * 布局:自动换行、每项不折行(label 内 checkbox+文字一体),窄屏也能一排两三个。 */
.multi-box{
  display:flex; flex-wrap:wrap; gap:4px 14px; align-items:center;
  border:1px solid var(--line); border-radius:6px; background:var(--card);
  padding:5px 8px; min-width:0; max-width:100%;
}
.multi-item{
  display:inline-flex; align-items:center; gap:4px; white-space:nowrap;
  font-size:12.5px; color:var(--txt); cursor:pointer; user-select:none;
}
.multi-item input[type="checkbox"]{ margin:0; flex:0 0 auto; }
/* ★ v1.0.425(用户要求):车型库数据表下面的「温度类型能力清单」—— **可展开/可收起**的独立面板。
 * 为什么单独一类而不是内联样式:项目有 5 套皮肤(含深色),写死色值会串味,
 *   `test_node` 的「颜色棘轮」把写死十六进制色钉成只减不增 ⇒ 一律走设计令牌。
 * 结构:.cap-panel > .cap-head(可点) + .cap-body(展开时显示);收起状态存在本机设置里(刷新仍在)。 */
.cap-panel{
  border:1px solid var(--line); border-radius:8px; background:var(--card);
  margin-top:6px; min-width:0; max-width:100%; overflow:hidden;
}
.cap-head{
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  padding:8px 10px; cursor:pointer; user-select:none;
  background:var(--bg-elev); border-bottom:1px solid var(--line);
  font-size:13px; color:var(--txt);
}
.cap-panel.cap-collapsed .cap-head{ border-bottom:0; }
.cap-head:hover{ background:var(--bg-hover); }
.cap-head:focus-visible{ outline:2px solid var(--focus-ring); outline-offset:-2px; }
.cap-chev{ flex:0 0 auto; color:var(--sub); font-size:12px; width:12px; text-align:center; }
.cap-title{ font-weight:600; color:var(--txt); }
.cap-sub{ color:var(--sub-2); font-size:12px; }
.cap-cur{ margin-left:auto; color:var(--sub-2); font-size:12px; white-space:nowrap; }
.cap-body{ padding:8px 10px 10px; min-width:0; max-width:100%; overflow-x:auto; }
.cap-panel.cap-collapsed .cap-body{ display:none; }
.cap-body .cap-note{ margin:6px 0 0; color:var(--sub-2); font-size:12px; line-height:1.7; }
.cap-body .cap-note b{ color:var(--txt); }
/* ★ v1.0.427:能力清单渲染失败时**必须看得见**(铁律 7 绝不静默)。
 *   起因:v1.0.426 上线后用户反馈"内容没展示、也没有展开收起按键",而控制台干净 ——
 *   由于渲染函数若没被调用/中途抛错被 `catch{}` 吞掉,界面上与"功能根本没做"完全一样,无从排查。
 *   现在任何失败都往面板里写一条红字(含错误信息 + 一行自查提示)。 */
.cap-panel .cap-err{
  margin:8px 10px; padding:7px 10px; border-radius:8px;
  border:1px solid var(--line); border-left:4px solid var(--err);
  background:var(--err-bg); color:var(--err);
  font-size:12.5px; line-height:1.7; overflow-wrap:anywhere; word-break:break-word;
}
.cap-panel .cap-err b{ color:var(--err); }
/* ★ v1.0.430(用户要求):大批量询问卡从「调度方案」区顶部挪到**任务单卡片下方**。
 *   它不是报错、也不是普通提示,而是"**需要你做一个选择**"的等待态 ⇒ 左边一条强调竖条 + 稍亮的底,
 *   在任务单卡片与排车控件之间一眼能看到、又不至于像告警那样刺眼。
 *   全部走设计令牌(5 套皮肤含深色自适应;写死色值会撞"颜色棘轮"断言)。 */
.md-accel-ask{
  margin:8px 0 2px; border:1px solid var(--line); border-left:4px solid var(--pri);
  background:var(--bg-tint); border-radius:8px; padding:8px 10px;
  min-width:0; max-width:100%; overflow-wrap:anywhere;
}
.md-accel-ask .card-head{ background:transparent; border:0; padding:0 0 2px; }
/* ══════════════════════════════════════════════════════════════════════════════════════
 * ★ v1.0.432(P1):「平台对接」—— 调度单推送到运满满 / 货拉拉。
 * 设计口径(用户明确要求):P1 阶段**功能未开通**,界面上必须让用户一眼看出"即将推出",
 *   并且**绝不允许**出现"看起来能用、点了没反应"的按钮(那正是 v1.0.426 踩过的坑:静默失败最难查)。
 *   所以:① 页签标题旁挂一个醒目的 `即将推出` 徽标;② 页内首屏给诚实的进度说明;
 *   ③ "确认推送"置灰并写明原因;④ 每处都附一句"已经做好了什么",给用户期待感。
 * 全部走设计令牌(5 套皮肤含深色自适应;写死色值会撞"颜色棘轮"断言)。
 * ══════════════════════════════════════════════════════════════════════════════════════ */
/* 页签上的「即将推出」徽标(比普通文字醒目,但不抢主色) */
.tab-soon{
  display:inline-block; margin-left:4px; padding:0 5px;
  font-size:10.5px; line-height:16px; font-weight:700; vertical-align:1px;
  border-radius:var(--r-pill); background:var(--warn-bg); color:var(--warn-ink);
  border:1px solid var(--warn-line); white-space:nowrap;
}
/* 首屏的"建设中"说明块 */
.carrier-soon{
  border:1px solid var(--line); border-left:4px solid var(--warn);
  background:var(--warn-bg); color:var(--warn-ink);
  border-radius:8px; padding:9px 11px; margin:6px 0 10px;
  font-size:13px; line-height:1.8; min-width:0; max-width:100%; overflow-wrap:anywhere;
}
.carrier-soon b{ color:var(--warn-ink); }
.carrier-soon .cs-title{ font-weight:700; display:block; margin-bottom:3px; }
/* "已经做好了什么" —— 给期待感的那一段 */
.carrier-done{
  border:1px solid var(--line); border-left:4px solid var(--ok);
  background:var(--ok-bg); border-radius:8px; padding:9px 11px; margin:8px 0;
  font-size:12.5px; line-height:1.8; color:var(--txt);
  min-width:0; max-width:100%; overflow-wrap:anywhere;
}
.carrier-done b{ color:var(--ok); }
/* 平台卡片(货拉拉 / 运满满 / Lalamove 各一张) */
.carrier-card{
  border:1px solid var(--line); border-radius:8px; background:var(--card);
  padding:9px 11px; margin:8px 0; min-width:0; max-width:100%;
}
.carrier-card .cc-head{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.carrier-card .cc-name{ font-weight:700; color:var(--txt); }
.carrier-card .cc-state{ font-size:12.5px; color:var(--sub-2); }
.carrier-card .cc-ops{ margin-left:auto; display:flex; gap:6px; flex-wrap:wrap; }
.carrier-card .cc-note{ margin:6px 0 0; font-size:12px; line-height:1.75; color:var(--sub-2); }
/* 状态点:未配置 / 已配置 */
.cc-dot{ display:inline-block; width:8px; height:8px; border-radius:50%; background:var(--sub-3); vertical-align:1px; }
.cc-dot.on{ background:var(--ok); }
/* 平台交互时间轴(调度单详情用) */
.carrier-tl{ margin:6px 0 0; padding:0; list-style:none; }
.carrier-tl li{
  position:relative; padding:2px 0 8px 16px; font-size:12.5px; line-height:1.7;
  border-left:2px solid var(--line); margin-left:5px; color:var(--txt);
}
.carrier-tl li:last-child{ border-left-color:transparent; padding-bottom:0; }
.carrier-tl li::before{
  content:''; position:absolute; left:-6px; top:7px; width:9px; height:9px;
  border-radius:50%; background:var(--pri); border:2px solid var(--card);
}
.carrier-tl .tl-at{ color:var(--sub-2); margin-right:6px; }
.carrier-tl .tl-pf{ color:var(--sub-2); margin-left:6px; }
.md-accel-ask .toolbar{ gap:8px; }
/* ★ v1.0.428(用户要求):能力清单表格 —— **能装的打勾、不能装的用横线 `-`**。
 *   为什么单独立类而不是沿用当时那个空的 `ts-table` + 内联样式:
 *   ① `ts-table` **从来没有样式定义**(只借了全局 table 规则),勾用的是彩色 emoji `✅`、
 *      不能装用的是长破折号 `—` —— emoji 在 5 套皮肤/不同字体下字形不一致,长破折号也不像"横线";
 *   ② 用户要的是"**一眼能分辨**",所以符号用纯文本 `✓` / `-`(不依赖 emoji 字体、不依赖颜色也能分辨),
 *      颜色只做辅助(能=绿、不能=灰);③ 走设计令牌,深色皮肤自动适配。 */
.tcap-table{
  width:auto; min-width:560px; border-collapse:separate; border-spacing:0;
  font-size:12.5px; background:var(--card);
}
.tcap-table th, .tcap-table td{
  border:1px solid var(--line); padding:5px 8px;
  white-space:nowrap; min-width:0;
}
.tcap-table thead th{
  background:var(--bg-elev); color:var(--txt); font-weight:600;
  position:sticky; top:0;
}
.tcap-table tbody th{ background:var(--bg-soft); color:var(--txt); font-weight:600; text-align:left; }
.tcap-table td{ text-align:center; }
/* 能装:绿勾 */
.tcap-table .tcap-yes{ color:var(--ok); font-weight:700; font-size:14px; }
/* 不能装:明确的**横线**(用户口径) + 收敛的灰,和绿勾拉开对比 */
.tcap-table .tcap-no{ color:var(--sub-3); font-weight:600; }
.tcap-table .tcap-zones{ color:var(--sub-2); font-weight:400; font-size:11.5px; }
/* 行内小结:这台车"能装的货物清单",收起/扫描时不必逐列数格子 */
.tcap-table .tcap-sum{ color:var(--sub-2); font-size:11.5px; white-space:normal; min-width:150px; }
.access-notice.an-info{ border-left-color:var(--pri); }
.access-notice.an-ok{ border-left-color:var(--ok); }
.access-notice.an-ok .an-badge{ background:var(--ok-bg); color:var(--ok); }
.access-notice.an-warn{ border-left-color:var(--warn); }
.access-notice.an-warn .an-badge{ background:var(--warn-bg); color:var(--warn); }
.access-notice.an-err{ border-left-color:var(--err); }
.access-notice.an-err .an-badge{ background:var(--err-bg); color:var(--err); }
/* v1.0.379:授权 / 版权页脚(**左下角**那条,内容由 js/auth.js 的 renderLicenseWatermark() 写)
 * 分工:位置(left:10px / bottom:4px)、position/z-index、pointer-events 由 JS 内联给定
 *   (位置属于"行为",所以放在 JS 里可被断言;配色/字体/窄屏行为属于"外观",统一放这里按皮肤走)。
 * 不挡路:pointer-events:none 不可点击拦截(双保险,JS 也设了一遍);user-select:none 不干扰选中正文。
 * 5 套皮肤:颜色用设计令牌 --sub(各皮肤自己的次要文字色)+ 低透明度,深色皮肤(科技感)下也不会消失/刺眼。
 * 窄屏:nowrap + overflow:hidden + text-overflow:ellipsis ⇒ **永远单行**,最窄也不会挤成三行;全文在 title 里悬停可看。
 * 打印:@media print 里整条隐藏 —— 打印件(作业单/方案)不出现这条页脚文字。 */
#licenseWatermark{
  color:var(--sub); opacity:.62;
  font-size:11px; letter-spacing:.3px; line-height:1.4;
  max-width:calc(100vw - 24px);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  pointer-events:none; user-select:none;
}
/* 窄屏再收一点(手机/微信内打开):字号更小,仍保持单行省略 */
@media (max-width:560px){ #licenseWatermark{ font-size:10px; opacity:.55; } }
/* 打印:不出现这条页脚(避免把"版权所有/授权使用"打到客户的作业单上) */
@media print{ #licenseWatermark{ display:none !important; } }
.view{ display:none; }
.view.active{ display:block; }
.panel{ background:var(--card); border:1px solid var(--line); border-radius:12px; padding:16px 18px; margin-bottom:16px; }
.panel h2{ font-size:18px; margin-bottom:6px; }
/* v1.0.383(全局排查):`.hint`/`.msg` 承载"操作指引 / 失败原因 / 下一步怎么办 / 额度与金额说明",
 * 长**无空格**串(URL、单号串、英文报错、掩码密钥)以前会整段横向顶出容器 ⇒ 一律允许任意断行,绝不裁掉。 */
.hint{ color:var(--sub); font-size:12.5px; margin-bottom:12px; overflow-wrap:anywhere; word-break:break-word; }

/* 按钮/输入 —— v1.0.324:全部按键统一为「简洁高级 3D 立体按键」
 * 立体感只由三样东西构成,且**全部走设计令牌**(5 套皮肤自动适配,深色皮肤不刺白):
 *   ① 面:--card → --bg-elev → --bg-soft 竖向渐变(上亮下暗 = 受光面)
 *   ② 边:1px --line-strong 描边 + 底部硬边 `0 2px 0 var(--bg)`(页面底色,做出键帽厚度)
 *   ③ 影:inset 顶面高光(--card)+ inset 底面内暗 + 少量 rgba(0,0,0,α) 环境投影
 * 交互:悬停上浮 1px、底边换主色浅阶(--pri-lite);按下下压 1px、底边收起、内影加深(真"按下去"的手感)。
 * 说明:以上只用令牌,故不写死任何颜色;深色皮肤下高光取 --card(本身就是该皮肤最亮面),不会出现白块。 */
.btn{
  border:1px solid var(--line-strong);
  background:linear-gradient(180deg, var(--card) 0%, var(--bg-elev) 46%, var(--bg-soft) 100%);
  color:var(--txt);
  padding:7px 14px;
  border-radius:var(--r-sm);
  cursor:pointer;
  font-size:13.5px;
  font-weight:500;
  line-height:1.35;
  letter-spacing:.2px;
  box-shadow:inset 0 1px 0 var(--card), inset 0 -2px 0 rgba(0,0,0,.055), 0 2px 0 var(--bg), 0 4px 7px rgba(0,0,0,.10);
  transform:translateY(0);
  transition:transform .12s ease, box-shadow .12s ease, border-color .12s ease, color .12s ease;
}
/* 主键(确定/生成/保存):主色立体面,底边用深一阶主色做出厚度 */
.btn.primary{
  border-color:var(--pri-d);
  background:linear-gradient(180deg, var(--pri) 0%, var(--pri-2) 100%);
  color:var(--on-accent);
  font-weight:600;
  box-shadow:inset 0 1px 0 var(--pri-lite), inset 0 -2px 0 rgba(0,0,0,.16), 0 2px 0 var(--pri-d), 0 4px 9px rgba(0,0,0,.18);
}
/* 危险键(取消全部调度/删除):红色立体面,文字仍用警示红,悬停才实心填充 */
.btn.danger{
  border-color:var(--err);
  color:var(--err);
  background:linear-gradient(180deg, var(--err-bg) 0%, var(--card) 100%);
  box-shadow:inset 0 1px 0 var(--card), inset 0 -2px 0 rgba(0,0,0,.05), 0 2px 0 var(--err), 0 4px 8px rgba(0,0,0,.12);
}
/* 紧凑尺寸(表格行内/工具条):按键更小,底边与内影同比例收窄,避免"厚边"显笨 */
.btn.sm, .btn-sm{ padding:5px 11px; font-size:12.5px; }
.btn-sm, .btn.sm, .btn-xs{ box-shadow:inset 0 1px 0 var(--card), inset 0 -1px 0 rgba(0,0,0,.045), 0 1px 0 var(--bg), 0 2px 4px rgba(0,0,0,.09); }
.btn-xs{ padding:2px 8px; font-size:12px; }
.btn.primary.btn-sm, .btn.primary.btn-xs, .btn.primary.sm{ box-shadow:inset 0 1px 0 var(--pri-lite), inset 0 -1px 0 rgba(0,0,0,.12), 0 1px 0 var(--pri-d), 0 3px 6px rgba(0,0,0,.16); }
.btn.danger.btn-sm, .btn.danger.btn-xs{ box-shadow:inset 0 1px 0 var(--card), inset 0 -1px 0 rgba(0,0,0,.04), 0 1px 0 var(--err), 0 3px 5px rgba(0,0,0,.10); }
/* 悬停:上浮 1px + 底边换主色浅阶 + 环境影拉长 */
.btn:hover{
  border-color:var(--pri);
  color:var(--pri);
  background:linear-gradient(180deg, var(--card) 0%, var(--bg-tint) 100%);
  box-shadow:inset 0 1px 0 var(--card), inset 0 -2px 0 rgba(0,0,0,.05), 0 3px 0 var(--pri-lite), 0 6px 11px rgba(0,0,0,.13);
  transform:translateY(-1px);
}
.btn.primary:hover{
  background:linear-gradient(180deg, var(--pri-lite) 0%, var(--pri) 42%, var(--pri-2) 100%);
  color:var(--on-accent);
  box-shadow:inset 0 1px 0 var(--pri-lite), inset 0 -2px 0 rgba(0,0,0,.14), 0 3px 0 var(--pri-d), 0 7px 14px rgba(0,0,0,.20);
  transform:translateY(-1px);
}
.btn.danger:hover{
  background:var(--err);
  border-color:var(--err);
  color:var(--on-accent);
  box-shadow:inset 0 1px 0 var(--err-bg), inset 0 -2px 0 rgba(0,0,0,.20), 0 3px 0 var(--err), 0 7px 14px rgba(0,0,0,.20);
  transform:translateY(-1px);
}
/* 按下:下压 1px + 底边收起 + 内影加深(键帽被按进去) */
.btn:active{
  border-color:var(--pri);
  background:linear-gradient(180deg, var(--bg-soft) 0%, var(--bg-mute) 100%);
  box-shadow:inset 0 2px 5px rgba(0,0,0,.18), inset 0 -1px 0 rgba(0,0,0,.04), 0 1px 0 var(--bg), 0 1px 2px rgba(0,0,0,.08);
  transform:translateY(1px);
}
.btn.primary:active{
  transform:translateY(1px);
  box-shadow:inset 0 3px 6px rgba(0,0,0,.26), inset 0 -1px 0 rgba(0,0,0,.10), 0 1px 0 var(--pri-d);
}
.btn.danger:active{ transform:translateY(1px); box-shadow:inset 0 3px 6px rgba(0,0,0,.26), 0 1px 0 var(--err); }
.btn:focus-visible{ outline:2px solid var(--focus-ring); outline-offset:2px; }
/* v1.0.255:生成方案按钮运算中禁用态(防误按)—— 压平:无厚度、无投影、去饱和 */
.btn[disabled], .btn:disabled{
  opacity:.6; cursor:not-allowed; pointer-events:none;
  background:linear-gradient(180deg, var(--bg-soft) 0%, var(--bg-mute) 100%);
  box-shadow:none; transform:none; filter:saturate(.65);
}
.btn.primary[disabled]:hover, .btn.primary:disabled:hover{ background:var(--pri); color:var(--on-accent); border-color:var(--pri); }
.inp, select.inp{ border:1px solid var(--line); padding:7px 10px; border-radius:8px; font-size:13.5px; width:100%; }
.inp:focus{ outline:2px solid var(--focus-ring); border-color:var(--pri); }
.toolbar{ display:flex; gap:8px; align-items:center; flex-wrap:wrap; margin:10px 0; }
/* v1.0.326/328:换行占位(flex 容器内 flex-basis:100% + 高度 0 ⇒ 强制其后内容另起一行,不占垂直空间)
 * v1.0.326:用于任务单卡片工具条 —— 让「机理 + ▶ 生成调度方案」成对折到下一行;
 * v1.0.328:同一占位也用于任务单卡片筛选行 —— 让「查询/清空查询/全选/反选/退回任务单」成组折到下一行 */
.toolbar .tb-break, .filter-row .tb-break{ flex-basis:100%; height:0; margin:0; padding:0; }
/* ============================================================================
 * v1.0.421:智能调度中心「排车控件」改为**每项独占一行**
 * 用户要求:「到达装货点、车型安排、线路优先、温度约束、机理、加速模式、生成调度方案,调整为各占独立一行」。
 * 布局口径(两处共用同一套变量,面板与全屏看起来才是一体):
 *   · 一行 = 一个控件;窄屏也不会把两个控件挤在一起看错;
 *   · 标签固定 [--md-ctrl-label] 宽且右对齐 ⇒ 七行标签成一条竖线,控件起点自动对齐;
 *   · 控件列缩进到标签右侧 ⇒ 视觉上"标签 | 控件"两列,长下拉框换行时也与上一行控件左边缘对齐。
 * 保留 .toolbar 类:一是沿用它的 margin/gap,二是既有断言按 .toolbar 定位本行(唯一定位锚,不另造)。
 * ========================================================================== */
.md-ctrl-list{ display:grid; grid-template-columns:1fr; gap:6px; align-items:start; }
.md-ctrl-row{ display:grid; grid-template-columns:5em minmax(0,1fr); gap:8px; align-items:center; min-width:0; }
.md-ctrl-label{ text-align:right; color:var(--sub); font-size:12.5px; line-height:1.6; white-space:nowrap; }
.md-ctrl-ops{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; min-width:0; }
/* 行内说明(温度/线路优先/加速模式的动态提示):缩进到**控件列**并在其下换行 ⇒ 紧挨它所说明的那一项,
 * 不会漂到别的行去;文字右到卡片边,长句自然折行。 */
.md-ctrl-note{ grid-column:2; color:var(--sub); font-size:11.5px; line-height:1.45; white-space:normal; overflow-wrap:anywhere; min-width:0; }
/* 面板上「加速模式」的说明沿用同一个类,但它在控件列里,宽度无需再限(靠 .md-ctrl-note 折行) */
.md-ctrl-list .md-accel-note{ max-width:none; }
/* ★ v1.0.421(用户要求):三个开关的**勾选框放到名称右边**(名字在前、方框在后)。
 *   名字用 span 包一层、input 跟在后面;label 仍是 inline-flex 且不改对齐方式 ⇒ 竖排时方框自然落在同一列。 */
.md-chk-right .md-chk-name{ white-space:nowrap; }
.md-chk-right input[type="checkbox"]{ margin:0; flex:0 0 auto; }
.md-ctrl-list #mdDispatch{ justify-self:start; }
/* 窄屏(手机/分栏很窄):标签不再占固定列,改成"标签一行 + 控件一行",仍然每项独占自己的行 */
@media (max-width:560px){
  .md-ctrl-row{ grid-template-columns:1fr; gap:2px; }
  .md-ctrl-label{ text-align:left; }
  .md-ctrl-note{ grid-column:1; }
}
/* ★ 智能调度中心这一栏是**固定 400px**(.dispatch-layout 第一列),扣掉卡片内边距只剩 ~370px:
 *   5em 标签(约 65px)+ 一整行控件(如「车型安排不考虑交通管制」或"下拉 + 日期时间"两个控件)
 *   在 400px 里会被挤到频繁折行、反而更难看。故 561~1180px 这段(**400px 主用区间就在这里**)
 *   改回「标签一行 + 控件缩进一列」(与全屏分组内那些行同一观感):控件不必再和标签抢宽度,
 *   每行仍是**一个控件**;长文字提示仍在该控件下方、紧挨它所说明的那一项。
 *   >1180px(如 rpin/pin/col3 下这一栏变得很宽)才回到"标签 | 控件"两列,进一步压缩整段高度。 */
@media (min-width:561px) and (max-width:1180px){
  .md-ctrl-row{ grid-template-columns:1fr; gap:2px; }
  .md-ctrl-label{ text-align:left; }
  .md-ctrl-ops{ padding-left:1.25em; }
  .md-ctrl-note{ grid-column:1; padding-left:1.25em; }
}
/* ★ v1.0.456:加 `white-space:pre-line` —— 44 个确认弹框调用点大量用 `\n\n` 分段
 *   (如「确定删除勾选的 N 条规则?\n\n其中 N 条是已生效规则 —— 删除后立即不再参与排车…」),
 *   原来会被压成一整行,「说明」与「注意」分不开。项目在 js/lines.js / js/parties.js 已对
 *   错误容器单独加过这条,这里是补上公共类。 */
.msg{ color:var(--sub); font-size:12.5px; overflow-wrap:anywhere; word-break:break-word; white-space:pre-line; }
.msg.ok{ color:var(--ok); }
.msg.err{ color:var(--err); }
/* v1.0.740:补齐「提醒 / 次要」两态,让颜色三态不必再写内联色 */
.msg.warn{ color:var(--warn-ink); }
.msg.mut{ color:var(--sub); }

/* 表格 */
.table-wrap{ overflow:auto; border:1px solid var(--line); border-radius:10px; }
table{ width:100%; border-collapse:collapse; font-size:13px; min-width:900px; }
th,td{ padding:8px 10px; border-bottom:1px solid var(--line); text-align:left; vertical-align:middle; }
/* v1.0.383(全局排查):单元格里的长**无空格**串(服务端报错/单号串/无空格地址)不许把整列撑到天边 ——
 * 列宽由表头 min-width 决定,内容一律允许任意断行(表格容器仍是横向可滚动,列不会错位)。 */
th,td{ overflow-wrap:anywhere; word-break:break-word; }
th{ background:var(--bg-soft); color:var(--sub); font-weight:600; white-space:nowrap; }
tr:hover td{ background:var(--bg-hover); }
tr.sel td{ background:var(--bg-sel); }
.empty{ color:var(--sub-2); padding:26px; text-align:center; }

/* v1.0.236:表格列管理(排序/拖列序/拖列宽)通用样式 */
th.th-sortable{ cursor:pointer; user-select:none; }
th.th-sortable:hover{ background:var(--bg-tint); color:var(--pri); }
.th-sort{ color:var(--pri); font-size:11px; }
.th-sort-dim{ color:var(--sub-3); font-size:11px; font-weight:400; }
th.th-draggable{ cursor:grab; }
th.th-draggable:active{ cursor:grabbing; }
th.th-drag-src{ opacity:.45; }
.col-resize{ position:absolute; top:0; right:0; width:6px; height:100%; cursor:col-resize; background:transparent; z-index:3; }
.col-resize:hover{ background:var(--line-strong); }
th{ position:relative; }
table.cols-managed{ table-layout:auto; }

/* v1.0.234:任务单表格「操作」列冻结在最右(类似冻结最右列)——
 * 横向滚动时 📝/编辑/删除 始终贴在可视区右侧可见可点 */
#orderTable th:last-child,
#orderTable td:last-child{
  position:sticky; right:0; z-index:4;
  background:var(--card); box-shadow:-1px 0 0 var(--line);
  white-space:nowrap;
}
#orderTable th:last-child{ background:var(--bg-soft); z-index:5; }
#orderTable tbody tr:hover td:last-child{ background:var(--bg-hover); }
#orderTable tbody tr.sel td:last-child{ background:var(--bg-sel); }
/* v1.0.235:任务单 18 列较宽,数据卡片内允许横向滚动;表头行与操作列同屏冻结 */
#orderTable{ min-width:1580px; }

/* v1.0.242:车型库卡片内操作列冻结最右(与任务单同款) */
#vehicleTable{ min-width:1240px; }
#vehicleTable th:last-child,
#vehicleTable td:last-child{
  position:sticky; right:0; z-index:4;
  background:var(--card); box-shadow:-1px 0 0 var(--line);
  white-space:nowrap;
}
#vehicleTable th:last-child{ background:var(--bg-soft); z-index:5; }
#vehicleTable tbody tr:hover td:last-child{ background:var(--bg-hover); }
#vehicleTable tbody tr:hover td{ background:var(--bg-hover); }

/* v1.0.243:任务单行拖排序 —— 行首拖柄列(⠿ 与表头提示)与拖拽状态 */
#orderTable th.rd-th{ width:34px; min-width:34px; text-align:center; color:var(--sub-2); font-weight:400; cursor:default; }
#orderTable td.rd-td{ width:34px; min-width:34px; text-align:center; padding:2px 0; }
#orderTable .row-drag-h{ cursor:grab; user-select:none; color:var(--sub-2); font-size:15px; line-height:1; padding:4px 6px; border-radius:4px; display:inline-block; }
#orderTable .row-drag-h:hover{ color:var(--pri); background:var(--bg-tint); }
#orderTable .row-drag-h:active{ cursor:grabbing; }
#orderTable tr.rd-src td{ opacity:.4; }
#orderTable tr.rd-over td{ background:var(--bg-tint) !important; box-shadow:inset 0 2px 0 var(--pri); }

/* v1.0.228:后台管理·司机车辆档案数据卡片 —— 表头上方操作栏;表格区内部滚动(数据量大右侧出现滚动条),表头随滚动冻结(类冻结首行);卡片高度可上下拖动并记忆 */
.fleet-card{ border:1px solid var(--line); border-radius:12px; background:var(--card); overflow:hidden; }
.fleet-card .toolbar{ margin-top:0; }
.fleet-table-zone{ overflow:auto; height:460px; min-height:140px; }
.fleet-table-zone table{ min-width:900px; border-collapse:separate; border-spacing:0; }
.fleet-table-zone thead th{ position:sticky; top:0; z-index:3; background:var(--bg-soft); box-shadow:0 1px 0 var(--line); }
.fleet-batch-bar{ border-top:1px solid var(--line); padding:8px 12px; background:var(--bg-elev); }
.fleet-resize{ height:14px; cursor:ns-resize; text-align:center; color:var(--sub-2); font-size:11px; line-height:14px; user-select:none; background:var(--bg-elev); border-top:1px solid var(--line); }
.fleet-resize:hover{ color:var(--pri); background:var(--bg-tint); }

/* v1.0.292/299:调度单页表格(标准数据卡:表区内部滚动 + 表头 sticky + 首列冻结 + 操作列冻结最右 + ⠿ 行拖柄) */
#doTable{ min-width:1860px; }
#doTable th:last-child, #doTable td:last-child{
  position:sticky; right:0; z-index:4; background:var(--card); box-shadow:-1px 0 0 var(--line); white-space:nowrap;
}
#doTable th:last-child{ background:var(--bg-soft); z-index:5; }
#doTable tbody tr:hover td:last-child{ background:var(--bg-hover); }
#doTable tbody tr.sel td:last-child{ background:var(--bg-sel); }
#doTable tbody tr.do-row.sel td{ background:var(--bg-sel); }
#doTable tbody tr.do-row:hover td{ background:var(--bg-hover); }
#doTable th.rd-th{ width:34px; min-width:34px; text-align:center; color:var(--sub-2); font-weight:400; cursor:default; }
#doTable td.rd-td{ width:34px; min-width:34px; text-align:center; padding:2px 0; }
#doTable .row-drag-h{ cursor:grab; user-select:none; color:var(--sub-2); font-size:15px; line-height:1; padding:4px 6px; border-radius:4px; display:inline-block; }
#doTable .row-drag-h:hover{ color:var(--pri); background:var(--bg-tint); }
#doTable .row-drag-h:active{ cursor:grabbing; }
#doTable tr.rd-src td{ opacity:.4; }
#doTable tr.rd-over td{ background:var(--bg-tint) !important; box-shadow:inset 0 2px 0 var(--pri); }
.do-no-badge{ display:inline-block; width:15px; height:15px; line-height:15px; text-align:center; border:1.5px solid var(--pri-2); border-radius:50%; color:var(--pri-2); font-size:10px; font-weight:700; margin-right:4px; vertical-align:1px; }
.do-sub-row td{ background:var(--bg-hover) !important; padding:6px 10px; }
.do-sub-row .route-table{ min-width:1560px; }/* v1.0.292:任务单「拆单」列与查询条件的高亮展示 */
.split-tag{ display:inline-block; padding:1px 6px; border-radius:9px; background:var(--warn-bg); color:var(--warn-ink); border:1px solid var(--warn-line); font-weight:700; font-size:11.5px; white-space:nowrap; }
.split-part{ color:var(--warn-ink); font-weight:700; }
/* v1.0.293:经纬度未解析的任务单整行灰度显示(有坐标的正常显示) */
#orderTable tbody tr.order-nogeo td{ background:var(--bg-mute); color:var(--sub-2); }
#orderTable tbody tr.order-nogeo td a,
#orderTable tbody tr.order-nogeo td button{ opacity:.75; }
#orderTable tbody tr.order-nogeo:hover td{ background:var(--bg-mute-hover); }

/* 调度布局 */
/* v1.0.113/116/118:地图调度三面板布局 —— **v1.0.422 起只保留「品字(上1下2)」与「上中下」两种**(用户要求删除
 * 倒品字/左中右/自适应三个按钮);由 #mdLayout data-layout 驱动;面板槽位 A/B/C 由 JS 按顺序分配) */
.dispatch-layout{ display:grid; gap:14px; align-items:start; grid-template-columns:400px 1fr; }
.dispatch-layout[data-layout="pin"]{ grid-template-columns:minmax(0,1fr) minmax(0,1fr); grid-template-areas:"A A" "B C"; }
.dispatch-layout[data-layout="col3"]{ grid-template-columns:minmax(0,1fr); grid-template-areas:"A" "B" "C"; }
.dispatch-layout .md-pane{ min-width:0; min-height:0; }
.dispatch-layout .md-pane > .card{ height:100%; }
/* v1.0.422:品字(上1下2)—— 上排卡片拉伸填满行高(沿用 v1.0.176/181/184 为「上2下1」写的那套等高规则,
 * 按新布局语义迁到品字上;删掉倒品字/左中右后,这套规则只服务品字) */
.dispatch-layout[data-layout="pin"]{ align-items:stretch; }
.dispatch-layout[data-layout="pin"] .md-pane > .card{ display:flex; flex-direction:column; }
.dispatch-layout[data-layout="pin"] .md-pane > .card > .toolbar,
.dispatch-layout[data-layout="pin"] .md-pane > .card > .legend{ flex:0 0 auto; }
.dispatch-layout[data-layout="pin"] .md-pane .map-fs{ flex:1 1 auto; min-height:0; }
.dispatch-layout[data-layout="pin"] .md-pane .mapbox{ height:100% !important; width:100% !important; min-height:120px; }
@media(max-width:1000px){ .dispatch-layout{ grid-template-columns:1fr; } }
/* v1.0.422:窗口变窄时只有品字需要回退单列(上中下本来就是单列) */
@media(max-width:680px){
  .dispatch-layout[data-layout="pin"]{ grid-template-columns:minmax(0,1fr); grid-template-areas:"A" "B" "C"; }
}
/* 面板标题栏把手(HTML5 拖拽换位)与布局切换按钮 */
.md-titlebar{ display:flex; justify-content:space-between; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:6px; }
.md-titlebar h2{ margin:0; }
.md-layoutbar{ display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
.md-layoutbar .layout-btn.active{ background:var(--pri); color:var(--on-accent); border-color:var(--pri); }
.ch-t{ display:flex; align-items:center; gap:6px; min-width:0; }
.md-grip{ cursor:grab; color:var(--sub-2); font-size:14px; padding:0 4px; user-select:none; line-height:1; }
.md-grip:hover{ color:var(--pri); }
.md-grip:active{ cursor:grabbing; }
/* v1.0.211:收货点地图「⛶ 全屏」按钮加大突出,下方提示“全屏操作体验最佳!” */
.md-fs-cta{ display:inline-flex; flex-direction:column; align-items:center; gap:2px; }
.md-fs-cta .btn{ font-size:15px; font-weight:600; padding:9px 20px; border-radius:10px;
  box-shadow:0 2px 8px rgba(10,102,194,.35); line-height:1.2; }
.md-fs-cta .btn:hover{ box-shadow:0 3px 12px rgba(10,102,194,.5); transform:translateY(-1px); }
.md-fs-cta .fs-tip{ font-size:12px; color:var(--ok); font-weight:600; white-space:nowrap; }
.md-pane.drag-over > .card{ outline:2px dashed var(--pri); outline-offset:2px; }
/* v1.0.160:布局像素分界拖动 —— 相邻面板边界出现拖把,左右拖宽/上下拖高 */
.md-split-handles{ position:absolute; inset:0; pointer-events:none; z-index:1500; }
.md-split-h{ position:absolute; pointer-events:auto; border-radius:3px; }
.md-split-h.v{ width:9px; margin-left:-4.5px; cursor:col-resize; }
.md-split-h.r{ height:9px; margin-top:-4.5px; cursor:row-resize; }
.md-split-h:hover{ background:rgba(37,99,235,.4); }
/* v1.0.121:调度方案面板「⇔ 拖宽」把手(左右拖动调整方案列宽;仅 row3/pin 且方案在第3槽时显示) */
.md-rx{ cursor:col-resize; user-select:none; white-space:nowrap; font-size:12px; color:var(--ink-2);
  border:1px solid var(--line); border-radius:8px; padding:4px 10px; background:var(--bg-elev); touch-action:none; }
.md-rx:hover{ color:var(--pri); border-color:var(--pri); background:var(--bg-tint); }
.md-rx.drag{ background:var(--pri); color:var(--on-accent); }
/* v1.0.122:方案明细操作表与方案汇总表同宽(560),不再窄于上方汇总/合计框 */
.plan-body .rt-op{ min-width:560px; }
/* v1.0.119:地图调度任务单面板 —— 控件字号/宽高统一;行内容放不下自动换行 */
.md-pane[data-pane="list"] .filter-row .btn,
.md-pane[data-pane="list"] .toolbar .btn{ height:30px; padding:0 12px; font-size:13px; display:inline-flex; align-items:center; white-space:nowrap; }
.md-pane[data-pane="list"] .filter-row .btn.btn-xs,
.md-pane[data-pane="list"] .toolbar .btn.btn-xs{ padding:0 8px; }
.md-pane[data-pane="list"] .filter-row .inp,
.md-pane[data-pane="list"] .toolbar .inp{ height:30px; padding:0 8px; font-size:13px; }
.md-pane[data-pane="list"] .flt-panel .btn{ height:auto; padding:3px 8px; font-size:12.5px; display:inline-block; }
/* 统计行:机理 + 已选/货物/重量/体积 并排,放不下自动换行 */
.stat-line{ display:flex; flex-wrap:wrap; align-items:center; gap:6px 16px; margin:6px 0 0; font-size:13px; color:var(--ink-2); }
.stat-line .st-item{ display:inline-flex; align-items:center; gap:4px; white-space:nowrap; }
/* v1.0.383(用户实测:进度说明文字较长时顶出右边界,后半句「怎么办」看不到):
 * `#mdSummary` 这个格子平时是短的「📦 已选 N 个收货地址」,但**服务端等待期间**会被 mdPlanWaitBarShow
 * 写成整句进度文案 + 【⏹ 停止等待】按钮(见 js/mapdispatch.js 的 mdPlanWaitBarShow)—— 它以前继承
 * 上面 .st-item 的 nowrap,于是整句**无法折行**,一路顶出本栏(被右栏卡片盖住 ⇒ 用户就"看不到了")。
 * 处理:只给这一个格子允许折行(其余短项继续 nowrap,不会把统计行拆得七零八落),按钮本身仍不折行。 */
.stat-line .st-item#mdSummary{ white-space:normal; overflow-wrap:anywhere; word-break:break-word; min-width:0; max-width:100%; }
.stat-line .st-item#mdSummary > button{ white-space:nowrap; flex:0 0 auto; }
.stat-line select.inp{ width:auto; height:30px; padding:0 8px; font-size:13px; }
.stat-line .st-sep{ color:var(--sub-3); margin:0 1px; }
/* v1.0.255/259:调度方案运算进度条(stat-line 内;bar 行 + 阶段子项行;running=亮带流动,完成后满格自动退出)
 * v1.0.383:进度文案越界的根治 —— ① 盒子允许收缩(flex 子项必须 min-width:0,否则 min-content=整句宽度会把
 *   整行顶出去);② 文本**允许折行**(以前 white-space:nowrap ⇒ 长句只能顶出右边界被裁掉);
 *   ③ 上限改成 min(560px,100%):宁可窄一点折成两行,也不越过右边界(短信息留在第一行,长句自然折到下一行)。 */
.md-progress{ display:inline-flex; flex-direction:column; align-items:stretch; gap:3px; max-width:min(560px,100%); min-width:0; flex:0 1 auto; }
.md-progress-bar-row{ display:inline-flex; align-items:center; gap:7px; flex-wrap:wrap; min-width:0; max-width:100%; }
.md-progress-track{ position:relative; width:150px; height:7px; border-radius:4px; background:var(--track); overflow:hidden; flex:0 0 auto; }
.md-progress-fill{ position:absolute; left:0; top:0; height:100%; width:0; border-radius:4px; background:linear-gradient(90deg,var(--pri),var(--pri-2)); transition:width .25s ease; }
.md-progress.running .md-progress-fill::after{ content:''; position:absolute; left:0; top:0; height:100%; width:40%; background:linear-gradient(90deg,rgba(255,255,255,0),rgba(255,255,255,.65),rgba(255,255,255,0)); animation:mdProgFlow 1s linear infinite; }
@keyframes mdProgFlow{ from{ transform:translateX(-60%);} to{ transform:translateX(400%);} }
/* ============================================================================
 * ★★★ v1.0.477(用户要求)任务单 / 调度单**分页条**样式
 * ----------------------------------------------------------------------------
 * 结构:共 N 条 · 第 x/y 页 · 显示 a–b | « 首页 ‹‹ 上一页 1 2 … 9 下一页 ›› 末页 » | 每页条数下拉
 * 说明:页码按钮沿用既有 .btn.btn-xs 外观(与全站一致),仅补当前页高亮与省略号间距;
 *       整条允许换行,窄屏或页数很多时不会撑破卡片。
 * ========================================================================== */
.page-bar{ display:flex; flex-wrap:wrap; align-items:center; gap:6px 10px; padding:6px 2px; font-size:12px; color:var(--ink-2); }
.page-bar .page-info{ white-space:nowrap; }
.page-bar .page-info b{ color:var(--pri-2); }
.page-bar .page-ctrl{ display:inline-flex; flex-wrap:wrap; align-items:center; gap:3px; }
.page-bar .page-btn{ min-width:26px; padding:1px 6px; line-height:1.5; }
.page-bar .page-btn.page-cur{ background:var(--pri); border-color:var(--pri); color:#fff; font-weight:700; }
.page-bar .page-btn:disabled{ opacity:.45; cursor:not-allowed; }
.page-bar .page-gap{ padding:0 2px; opacity:.55; }
.page-bar .page-size{ margin-left:auto; }
.page-bar .page-size-sel{ width:auto; height:26px; padding:0 6px; font-size:12px; }
.md-progress-txt{ font-size:12px; color:var(--ink-2); white-space:normal; overflow-wrap:anywhere; word-break:break-word; min-width:0; flex:1 1 auto; max-width:100%; }
/* ============================================================================
 * ★★★ v1.0.476 重新设计:**计时器改由浏览器(CSS 动画)驱动,不再靠 JS 每秒重写**
 * ----------------------------------------------------------------------------
 * 【为什么必须这样改】用户连续报障「进度文字停在某一句话不动 / 看着像卡死」。
 *   旧实现靠 `setInterval` 每秒改文本 ⇒ ① 主线程一忙就不跳;② 定时器漏停就常驻(实测泄漏过一次)。
 *   现在改成:进入等待时只写**一个** CSS 变量 `--elapsed-s`(秒),由 `@keyframes` 每 1 秒
 *   把计数器 +1,并用 `counter()` 显示 —— 动画跑在**合成线程**上,主线程再忙也照跳,
 *   而且**没有任何 JS 定时器需要停**(从结构上消除泄漏)。
 * 【兼容】`counter()` 需要较新内核;老内核不认就静默不显示秒数(仍显示文字),
 *   由 JS 端的兜底写法负责给出「已 N 秒」——两条路互不干扰。
 * ========================================================================== */
.md-elapsed{ font-weight:600; color:var(--pri-2); }
.md-elapsed::after{
  counter-reset:mdsec var(--md-elapsed-0, 0);
  content:counter(mdsec) ' 秒';
  animation:mdSecCount 3600s steps(3600, end) 1 forwards;
}
@keyframes mdSecCount{ from{ counter-reset:mdsec var(--md-elapsed-0, 0); } to{ counter-reset:mdsec calc(var(--md-elapsed-0, 0) + 3600); } }
/* v1.0.259:阶段子项行(① 定位坐标 / ② 引擎运算 / ③ 生成展示;运行中蓝、完成绿、待办灰)
 * v1.0.383:同样允许折行(阶段说明里也会带「未配 Key,城市级估算」「分批并行:第 3/8 批完成,共 2085 单」这类长句) */
.md-progress-steps{ display:flex; flex-wrap:wrap; gap:2px 12px; font-size:11.5px; line-height:1.5; color:var(--sub-2); max-width:min(560px,100%); min-width:0; }
.md-progress-steps .md-step{ white-space:normal; overflow-wrap:anywhere; word-break:break-word; }
.md-progress-steps .md-step.run{ color:var(--pri-2); font-weight:600; }
.md-progress-steps .md-step.done{ color:var(--ok); }
.md-progress-steps .md-step.wait{ color:var(--sub-2); }
.md-progress-steps .md-step.skip{ color:var(--sub-3); text-decoration:line-through; }
/* v1.0.258:全屏进度条(地图容器顶部居中悬浮;仅全屏时由 JS 显示,普通视图隐藏)
 * v1.0.383:绝对居中 + 长文案 ⇒ 以前两侧一起被裁(实测 1366×768 下末尾字符落在视口外);这里给盒子加上宽度上限,
 * 配合 .md-progress-txt 的折行,任何分辨率都不会越出屏幕(顶部单行居中的"在做的事"始终看得见)。 */
.map-fs .md-progress-fs{ position:absolute; top:10px; left:50%; transform:translateX(-50%); z-index:2100; background:rgba(255,255,255,.96); border:1px solid var(--line-strong); border-radius:14px; padding:6px 14px; box-shadow:0 2px 10px rgba(0,0,0,.28); pointer-events:none; max-width:min(92vw,720px); }
.map-fs .md-progress-fs .md-progress{ max-width:100%; }
.map-fs .md-progress-fs .md-progress-txt{ text-align:center; }
.map-fs .md-progress-fs .md-progress-track{ width:180px; }
/* v1.0.126:调度中心「地图轨迹」面板控件统一;modeTag 描述行 */
.md-pane[data-pane="map"] .toolbar select,
.md-pane[data-pane="map"] .toolbar .btn{ height:30px; font-size:13px; }
.md-pane[data-pane="map"] .toolbar select{ padding:0 8px; border:1px solid var(--line); border-radius:8px; background:var(--card); color:var(--txt); }
.md-pane[data-pane="map"] .legend{ margin-top:6px; }
#modeTag{ color:var(--sub); font-size:12.5px; }
.card{ border:1px solid var(--line); border-radius:10px; padding:12px; background:var(--card); }
.card-head{ display:flex; justify-content:space-between; align-items:center; margin-bottom:8px; }
.pick-list{ max-height:380px; overflow:auto; border:1px solid var(--line); border-radius:8px; }
.pick-item{ display:flex; gap:8px; padding:8px 10px; border-bottom:1px solid var(--line); cursor:pointer; }
.pick-item:hover{ background:var(--bg-hover); }
.pick-item.sel{ background:var(--bg-sel); }
.pick-item .t{ font-weight:600; }
.pick-item .s{ font-size:11.5px; color:var(--sub); }
/* ★ v1.0.421(用户要求):区划行与时间行都**放不下时自动换行**;
 *   每一段(label:值)带 nowrap(内联写的),所以换行只发生在分隔符处,不会把一段拆两半。 */
.pick-item .s, .pick-item .zone-line{ white-space:normal; overflow-wrap:anywhere; word-break:break-word; line-height:1.6; }
/* 分隔符(→ 与 /):左右留一点空,既不粘连也不占太宽 */
.pick-item .md-sep{ color:var(--sub-2); padding:0 5px; }
.pick-item .w{ font-size:11.5px; color:var(--pri); white-space:nowrap; }

.plan-tabs{ display:flex; gap:6px; margin-bottom:10px; flex-wrap:wrap; }
.plan-tabs button{ border:1px solid var(--line); background:var(--card); padding:6px 12px; border-radius:8px; cursor:pointer; font-size:13px; }
.plan-tabs button.active{ background:var(--pri); color:var(--on-accent); border-color:var(--pri); }
.plan-body .empty{ padding:40px; }
.route-block{ border:1px solid var(--line); border-radius:10px; margin-bottom:10px; overflow:hidden; }
.route-head{ background:var(--bg-tint); padding:8px 12px; font-weight:600; display:flex; justify-content:space-between; }
.route-head .m{ color:var(--pri); }
.route-table td,.route-table th{ font-size:12.5px; padding:6px 8px; }
/* v1.0.120:方案明细窄容器适配 —— 表格最小宽降至560(不再按全局900撑破面板),操作列(调整↑↓/移除任务)sticky 常驻右侧可见 */
.route-table{ min-width:560px; }
.rt-op th:last-child, .rt-op td:last-child{ position:sticky; right:0; background:var(--card); z-index:2; box-shadow:-2px 0 5px rgba(31,45,91,.07); }
.rt-op th:last-child{ background:var(--bg-soft); }
.summary-bar{ display:flex; flex-wrap:wrap; gap:4px 18px; padding:10px 12px; background:var(--bg-elev); border-bottom:1px solid var(--line); font-size:13px; align-items:center; min-width:0; }
/* v1.0.383:摘要行里的说明句(如"⚡ 智能优化…"、服务端口径说明)也可能很长 ⇒ 允许换行,不再顶出右边界 */
.summary-bar span{ white-space:normal; overflow-wrap:anywhere; word-break:break-word; min-width:0; }
.summary-bar b{ color:var(--pri); }
/* v1.0.383:警告行(服务端原文 / 预算说明 / 「怎么办」长句)一律允许折行 —— 这些句子正是"被裁掉就看不到下一步"的地方 */
.warn-line{ color:var(--warn); font-size:12.5px; padding:4px 12px; overflow-wrap:anywhere; word-break:break-word; }
.route-stops{ font-size:12.5px; padding:8px 12px; color:var(--ink-2); line-height:1.9; }
.stop-no{ display:inline-block; background:var(--pri); color:var(--on-accent); border-radius:50%; width:20px; height:20px; line-height:20px; text-align:center; font-size:11px; margin-right:4px; }
.stop-no.unload{ background:var(--accent2); }

/* 地图 */
.mapbox{ height:520px; border:1px solid var(--line); border-radius:10px; }
/* v1.0.83/84:地图全屏
 * 全屏对象为包裹层 .map-fs(内置「退出全屏」按钮,全屏时才显示,便于无键盘用户恢复) */
.map-fs{ position:relative; }
.map-fs .fs-exit{
  position:absolute; top:12px; right:12px; z-index:2000;
  display:none; cursor:pointer;
  border:1px solid var(--line-strong); background:rgba(255,255,255,.96); color:var(--pri);
  border-radius:8px; padding:4px 12px; font-size:13px; box-shadow:0 1px 5px rgba(0,0,0,.2);
}
.map-fs .fs-exit:hover{ background:var(--bg-tint); }
/* v1.0.127:全屏浮层「选择要展示的调度路线」下拉(仅全屏显示,位于左上角)
 * v1.0.195:右移避开左上角 Leaflet 的 -/+ 缩放控件(原来 left:12px 与之重叠) */
.map-fs .fs-route{
  position:absolute; top:12px; left:60px; z-index:2000; display:none;
  border:1px solid var(--line-strong); background:rgba(255,255,255,.97); color:var(--txt);
  border-radius:8px; padding:4px 10px; font-size:13px; max-width:60%;
  box-shadow:0 1px 5px rgba(0,0,0,.2); cursor:pointer;
}
.map-fs .fs-route:hover{ border-color:var(--pri); }
/* v1.0.135:地图全屏底部工具条(到达装货点/点选顺序/框选/缩放/机理/生成方案,仅全屏显示) */
.map-fs .fs-tools{
  position:absolute; bottom:16px; left:50%; transform:translateX(-50%);
  z-index:2100; display:none; align-items:center; flex-wrap:wrap; gap:6px 8px; justify-content:center;
  max-width:94%; background:rgba(255,255,255,.98); border:1px solid var(--line-strong); border-radius:12px;
  padding:8px 12px; font-size:12.5px; color:var(--ink-2);
  box-shadow:0 4px 14px rgba(0,0,0,.28);
}
.map-fs:fullscreen .fs-tools{ display:flex; }
/* ★★★ v1.0.550(**最终口径:把手只留左上角那一个 + 右下角仍可拖大小**)=====================
 *   用户三次澄清,最终定稿:
 *     ①「三项卡片上的【按住拖动位置,拖右下角改大小】取消按键及文件。」
 *     ②「右下角保持能拖大小;按住拖动位置消失,但左上角的把手保留。」
 *     ③「把手有两个,我说的是保留左上角的把手,而【按住拖动位置,拖右下角改大小】左边的把手取消。」
 *   ⇒ **结构结论**:
 *     · **左上角 `.fs-lc-grip`(⣿)= 唯一把手**,拖动整张浮卡从它发起;
 *     · **工具条顶部那根 `.fs-grip`(带提示文字的那根)已取消** ——
 *       HTML 里的 `#mdFsGrip` 与其 CSS 规则(v1.0.550 起)都已删除;
 *     · **右下角仍可拖大小**(`resize:both` 保留,浮卡与工具条都保留);
 *     · `.fs-tools-pinned` 与"显式 left/top"口径必须留着 —— 否则拖动会被居中定位弹回原处。 */
.map-fs .fs-tools{ resize:both; overflow:auto; min-width:320px; min-height:120px; max-width:96vw; max-height:88vh; }
.map-fs .fs-tools.fs-tools-pinned{ left:auto; right:auto; bottom:auto; transform:none; }
/* v1.0.550:`.map-fs .fs-tools .fs-grip` 的规则已删除(连同 `:hover` 与 `::before` 提示文字)——
 *   那根把手(`#mdFsGrip`)按用户要求取消;拖动改由左上角 `.fs-lc-grip` 承担。 */
.map-fs .fs-tools .btn{ height:26px; padding:0 9px; font-size:12.5px; display:inline-flex; align-items:center; white-space:nowrap; }
.map-fs .fs-tools .btn.md-box-on{ background:var(--pri); color:var(--on-accent); border-color:var(--pri); }
.map-fs .fs-tools .fs-tool-inp{ height:26px; padding:0 6px; font-size:12.5px; border:1px solid var(--line); border-radius:8px; }
.map-fs .fs-tools .fs-tool-sel{ height:26px; padding:0 6px; font-size:12.5px; border:1px solid var(--line); border-radius:8px; background:var(--card); color:var(--txt); }
/* v1.0.411:全屏工具条上的「⚡ 加速模式(分批并行)」开关(与面板上的同一持久化字段,双向同步) */
.map-fs .fs-tools .fs-tool-chk{ display:inline-flex; align-items:center; gap:4px; height:26px; font-size:12.5px; white-space:nowrap; }
.map-fs .fs-tools .fs-tool-chk input{ margin:0; }
.map-fs .fs-tools .md-accel-note{ color:var(--sub); max-width:300px; white-space:normal; line-height:1.35; }
/* ============================================================================
 * v1.0.421:全屏地图工具条**按类归组**(用户要求「全屏地图也更新并优化一下位置,方便操作、归好类、美观一体,
 * 考虑好文字提示的位置」)。三个分组各是一张浅底小卡(靠背景色 + 圆角分区,不额外画竖线 ⇒ 简洁一体):
 *   ① 行车与车型  ② 排车开关  ③ 地图操作与生成
 * 每组内是"行":标签固定宽度 + 控件列 ⇒ 组内上下对齐;开关的说明文字固定在**它的右侧、同一行内**,
 * 不再被长串控件挤到看不见的地方。窄屏(或分栏很窄)自动改成单列,仍然每项独占一行。
 * ========================================================================== */
.map-fs .fs-tools .fs-groups{ display:flex; flex-wrap:wrap; align-items:flex-start; justify-content:center; gap:8px 10px; }
.map-fs .fs-tools .fs-group{
  display:flex; flex-direction:column; gap:3px; padding:5px 9px 6px;
  border-radius:10px; background:rgba(15,23,42,.045);
}
:root[data-theme]:not([data-theme="classic"]) .map-fs .fs-tools .fs-group{ background:rgba(255,255,255,.06); }
.map-fs .fs-tools .fs-group-h{
  font-size:11px; color:var(--sub); letter-spacing:.5px; line-height:1.5;
  padding-bottom:3px; border-bottom:1px solid var(--line); margin-bottom:1px; white-space:nowrap;
}
.map-fs .fs-tools .fs-rows{ display:flex; flex-direction:column; gap:3px; }
.map-fs .fs-tools .fs-row{ display:flex; align-items:center; gap:7px; min-width:0; }
.map-fs .fs-tools .fs-row-label{ flex:0 0 5.5em; text-align:right; color:var(--sub); font-size:11.5px; white-space:nowrap; }
.map-fs .fs-tools .fs-row-ops{ display:flex; align-items:center; gap:6px; flex-wrap:wrap; min-width:0; }
/* 开关说明:同一行右侧,过长自动折行并限宽(避免把整条工具条拉得过宽盖住地图) */
.map-fs .fs-tools .fs-row-note{ color:var(--sub); font-size:11.5px; line-height:1.35; max-width:320px; white-space:normal; overflow-wrap:anywhere; }
.map-fs .fs-tools .fs-noengine{ flex-basis:100%; text-align:center; }
/* 「▶ 生成调度方案」:整条工具条的收尾按钮,给自己一条底线,和上面的分组分开 */
.map-fs .fs-tools .fs-launch{ flex-basis:100%; justify-content:center; height:32px; font-size:13.5px; margin-top:2px; }
/* ★★★ v1.0.555(**用户要求:三颗主按钮的文字统一为深金黄色**)=============================
 *   用户原话(逐条累积):
 *     · v1.0.550:「生成调度方案文字由白色改为深金黄色。」(全屏浮卡那颗 `#fsMdDispatch`)
 *     · v1.0.555:「任务单:将文字『加载到智能调度中心』的改为深金黄色。
 *                  智能调度中心:将文字『生成调度方案』的改为深金黄色。」
 *   ⇒ 现在这三颗**同一家族的主按钮**统一用**深金黄色** `#a9761b`:
 *       ① `#btnLoadMd`     —— 任务单页「📋 加载到智能调度中心」
 *       ② `#mdDispatch`    —— 智能调度中心面板「▶ 生成调度方案」
 *       ③ `#fsMdDispatch`  —— 全屏浮卡「▶ 生成调度方案」(+ 收起态回显 `.fs-lc-mini`)
 *   选深金而非亮金的理由:亮金在 --pri 蓝底上对比不足、易发灰;
 *   深金 #a9761b 在蓝底上对比 ≥4.5:1,可读。
 *   ⚠ 必须把 :hover / :active / [disabled] 三态**一并覆盖** —— 否则悬停/按下会退回白色
 *     (`.btn.primary:hover` 也是 (0,2,0)~(0,3,0),而 `#id` 选择器是 (1,x,0) ⇒ ID 必定胜出;
 *      `.fs-launch` 那条靠"写在文件更后"胜出)。
 *   ⚠ 皮肤纪律:本规则**不含 opacity/filter**,颜色按需求写定值(与 v1.0.550 同类先例一致)。 */
#btnLoadMd,
#btnLoadMd:hover,
#btnLoadMd:active,
#btnLoadMd[disabled],
#btnLoadMd:disabled,
#mdDispatch,
#mdDispatch:hover,
#mdDispatch:active,
#mdDispatch[disabled],
#mdDispatch:disabled,
.map-fs .fs-tools .fs-launch,
.map-fs .fs-tools .fs-launch:hover,
.map-fs .fs-tools .fs-launch:active,
.map-fs .fs-tools .fs-launch[disabled],
.map-fs .fs-tools .fs-launch:disabled{
  color:#a9761b;
  font-weight:700;                 /* 深色文字在蓝底上稍显细 ⇒ 加粗,与原来白字观感相当 */
}
/* 收起态那颗「回显按钮」与之一致(用户看到的是同一个"生成调度方案"字样) */
.fs-launch-card .fs-lc-mini{ color:#a9761b; font-weight:700; }
/* 全屏工具条整体:分组多了会高,给个上限并可滚动(小屏全屏时不会顶出屏幕外) */
.map-fs .fs-tools{ max-height:74vh; overflow:auto; }
/* v1.0.197:地图全屏左下「任务单卡」/右下「调度方案卡」—— 缩成一条悬停向上展开,高度可拖并记忆 */
.map-fs .fs-panel{
  position:absolute; bottom:0; z-index:2060; display:none; flex-direction:column; height:30px;
  font-size:12.5px; color:var(--txt);
}
.map-fs:fullscreen .fs-panel{ display:flex; }
.map-fs .fs-panel[data-dock='left']{ left:10px; width:min(440px, 42vw); }
.map-fs .fs-panel[data-dock='right']{ right:10px; width:min(720px, 60vw); }
.map-fs .fs-panel-tab{
  flex:0 0 30px; display:flex; align-items:center; gap:8px; padding:0 14px;
  background:rgba(255,255,255,.97); border:1px solid var(--line-strong); border-bottom:none;
  border-radius:10px 10px 0 0; box-shadow:0 -2px 10px rgba(0,0,0,.14); color:var(--pri); font-weight:600;
}
.map-fs .fs-panel-tab .fs-panel-hint{ margin-left:auto; color:var(--sub-2); font-weight:400; font-size:11px; }
.map-fs .fs-panel-zone{ display:none; flex-direction:column; min-height:0; flex:1; }
.map-fs .fs-panel.open{ height:calc(var(--fs-h, 320px) + 40px); }
.map-fs .fs-panel.open .fs-panel-zone{ display:flex; }
.map-fs .fs-panel-resize{
  flex:0 0 10px; cursor:ns-resize; text-align:center; line-height:9px; color:var(--sub-2); user-select:none;
  font-size:9px; letter-spacing:3px; background:var(--bg-tint); border:1px solid var(--line-strong); border-bottom:none;
}
.map-fs .fs-panel-resize:hover{ background:var(--bg-sel); color:var(--pri-2); }
/* v1.0.200:卡片左右拖宽手柄 —— 任务单卡右缘(wr)/调度方案卡左缘(wl),展开时显示;内容随宽度自适应 */
.map-fs .fs-panel-wresize{
  position:absolute; top:0; bottom:0; width:14px; z-index:2070; display:none;
  cursor:ew-resize; align-items:center; justify-content:center;
  color:var(--sub-2); font-size:10px; user-select:none; background:transparent;
}
.map-fs .fs-panel.open .fs-panel-wresize{ display:flex; }
.map-fs .fs-panel-wresize:hover{ background:rgba(10,102,194,.18); color:var(--pri-2); }
.map-fs .fs-panel-wresize.wr{ right:-8px; }
.map-fs .fs-panel-wresize.wl{ left:-8px; }
.map-fs .fs-panel-body{
  flex:1; min-height:0; overflow:auto; background:rgba(255,255,255,.98);
  border:1px solid var(--line-strong); border-bottom:none; border-top:none; padding:8px 10px 12px;
}
.map-fs .fs-panel-body .card{ border:none; box-shadow:none; padding:0; height:auto; background:transparent; }
.map-fs .fs-panel-body .card-head{ display:none !important; }
/* v1.0.198:任务单卡拖高/拖低时,列表区随卡片高度自适应伸缩(去掉 .pick-list 的 380px 封顶,
 * 卡片内部改为弹性列:筛选行/底部工具行固定,列表 flex 填充剩余高度,内部自行滚动) */
.map-fs .fs-panel[data-dock='left'] .fs-panel-body{ display:flex; padding:6px 10px 10px; }
.map-fs .fs-panel[data-dock='left'] .fs-panel-body .card{ flex:1 1 auto; display:flex; flex-direction:column; min-height:0; height:auto; margin:0; }
.map-fs .fs-panel[data-dock='left'] .fs-panel-body .filter-row{ flex:0 0 auto; }
.map-fs .fs-panel[data-dock='left'] .fs-panel-body .pick-list{ flex:1 1 auto; min-height:40px; max-height:none !important; margin:4px 0 6px; }
.map-fs .fs-panel[data-dock='left'] .fs-panel-body .route-stops{ flex:0 0 auto; max-height:84px; overflow:auto; }
.map-fs .fs-panel[data-dock='left'] .fs-panel-body .toolbar{ flex:0 0 auto; }
.map-fs .fs-panel[data-dock='left'] .fs-panel-body .stat-line{ flex:0 0 auto; }
/* v1.0.200:卡片变宽/变窄时内部内容自适应(表格/方案块随宽度铺满,过长内部滚动) */
.map-fs .fs-panel-body .route-table{ width:100%; }
.map-fs .fs-panel-body .plan-box{ min-width:0; }
.map-fs .fs-panel-body .plan-tabs{ flex-wrap:wrap; }
/* v1.0.136:地图全屏内「继续框选?」询问浮层(全屏时弹窗在 fullscreen 元素外不可见,改用地图内卡片) */
.map-fs .fs-ask{ position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); z-index:2300; width:min(92%,640px); }
.map-fs .fs-ask-card{ background:rgba(255,255,255,.99); border:1px solid var(--line-strong); border-radius:12px; padding:14px 18px; box-shadow:0 4px 16px rgba(0,0,0,.3); }
.map-fs .fs-ask-card .msg{ color:var(--ink-2); }
/* v1.0.137:「点击设顺序」实时汇总 HUD(地图最左边中间;非全屏/全屏均显示;pointer-events:none 不挡地图操作) */
.map-fs .md-seq-hud{
  position:absolute; left:8px; top:50%; transform:translateY(-50%); z-index:1900;
  width:196px; background:rgba(255,255,255,.97); border:1px solid var(--line-strong); border-radius:10px;
  padding:8px 11px; font-size:12.5px; color:var(--ink-2); line-height:1.75;
  box-shadow:0 2px 10px rgba(0,0,0,.22); pointer-events:none;
}
.map-fs .md-seq-hud b{ color:var(--pri); }
.map-fs .md-seq-hud .hud-ok{ color:var(--ok); }
.map-fs .md-seq-hud .hud-over{ color:var(--err); font-weight:600; }
.map-fs .md-seq-hud .hud-warn{ color:var(--warn); }
.map-fs .md-seq-hud select{ pointer-events:auto; }
/* v1.0.139/141:分配车辆 —— 输入模糊过滤选择器(输车牌/车型/司机即过滤;▾ 手动开合) */
.map-fs .md-seq-hud .md-veh-inp{ pointer-events:auto; flex:1; min-width:0; box-sizing:border-box; height:24px; font-size:12px;
  border:1px solid var(--line); border-radius:6px; padding:0 6px; }
.map-fs .md-seq-hud .md-veh-toggle{ pointer-events:auto; width:24px; height:24px; flex:0 0 auto; cursor:pointer;
  border:1px solid var(--line); border-radius:6px; background:var(--card); color:var(--pri); font-size:12px; line-height:1; }
.map-fs .md-seq-hud .md-veh-toggle:hover{ background:var(--bg-tint); }
.map-fs .md-seq-hud .md-veh-sug{ pointer-events:auto; position:absolute; left:0; right:0; top:100%; z-index:2400;
  background:var(--card); border:1px solid var(--line-strong); border-radius:8px; margin-top:2px; max-height:168px; overflow:auto;
  box-shadow:0 4px 12px rgba(0,0,0,.25); }
.md-veh-sug-i{ padding:5px 8px; font-size:12px; cursor:pointer; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.md-veh-sug-i:hover{ background:var(--bg-tint); }
.md-veh-sug-i.auto{ color:var(--ink-2); }
.md-veh-sug-empty{ padding:5px 8px; font-size:12px; color:var(--warn); }
.map-fs:fullscreen{ width:100vw !important; height:100vh !important; }
.map-fs:fullscreen .fs-exit{ display:block; }
.map-fs:fullscreen .fs-route{ display:block; }
.map-fs:fullscreen .mapbox{ width:100% !important; height:100% !important; border:none; border-radius:0; }
/* v1.0.278:弹窗遮罩/toast 全屏时搬入 .map-fs 内,改用 absolute 相对全屏容器定位(避免 fixed 在全屏下的兼容差异) */
.map-fs:fullscreen .mask{ position:absolute; }
.map-fs:fullscreen .toast{ position:absolute; }
.legend{ margin-top:8px; font-size:12.5px; color:var(--sub); display:flex; gap:16px; flex-wrap:wrap; }
.legend .dot{ display:inline-block; width:10px; height:10px; border-radius:50%; margin-right:4px; }

/* 标签页 */
.tabs{ display:flex; gap:4px; flex-wrap:wrap; margin-bottom:12px; }
.tabs .tab{ border:1px solid var(--line); background:var(--card); padding:7px 14px; border-radius:8px; cursor:pointer; }
.tabs .tab.active{ background:var(--pri); color:var(--on-accent); border-color:var(--pri); }
.atab{ display:none; }
.atab.active{ display:block; }
/* v1.0.251:后台管理分组 —— 「用户后台管理」/「开发后台管理」两组页签 */
.admin-tab-group{ margin-bottom:10px; }
.admin-tab-group:last-child{ margin-bottom:0; }
.admin-tab-label{ display:block; font-size:12px; font-weight:600; color:var(--sub); margin:0 0 4px 2px; letter-spacing:.4px; }
.admin-tab-group .tabs{ margin-bottom:0; }
/* ★ v1.0.631「公司与平台」可收起卡片:收起时那条始终显示状态与两个操作,展开后 6 秒无光标自动收起(锁定除外) */
.adm-headcard{ border:1px solid var(--line); border-radius:10px; background:var(--panel,#fff); padding:6px 8px; margin-bottom:8px; }
.adm-headbar{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.adm-headbar-btns{ margin-left:auto; display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
.adm-chip{ font-size:12px; font-weight:600; padding:2px 8px; border-radius:999px; border:1px solid var(--line); white-space:nowrap; }
.adm-chip.on{ color:#065f46; background:#ecfdf5; border-color:#a7f3d0; }   /* 已登录 */
.adm-chip.off{ color:#92400e; background:#fffbeb; border-color:#fde68a; }  /* 未登录 */
.adm-headcard.expanded{ box-shadow:0 2px 10px rgba(0,0,0,.06); }
#admHeadLockWrap{ user-select:none; }
/* ★ v1.0.638:退出后台后**硬隐藏**面板。用 !important 是因为现场存在"退出后又被某处把
 *   #adminPanel 的 display 设回 block"的情况(用户实测:登录门上方还留着「托运客户档案」半页内容)。
 *   只要这个类还在,任何内联 display 都盖不掉它 ⇒ 残留内容不可能被看见。 */
#adminPanel.adm-hard-hidden{ display:none !important; visibility:hidden !important; }
/* ★★ v1.0.641(用户连报两次"退出后残留"):把"是否已登录后台"变成**CSS 可判定**的状态类,
 *   放在 `#view-admin` 上:
 *     · 没有 .adm-in ⇒ #adminPanel **一律不显示**(!important,任何内联 display 都盖不掉),
 *       同时保证登录卡片可见;
 *     · 有 .adm-in ⇒ 面板显示、登录卡片隐藏。
 *   这样即使某处漏调清理、或有迟到的异步渲染,退出后也**不可能**看到后台内容 —— 由 CSS 兜底,而不是靠每次记得清。 */
#view-admin:not(.adm-in) #adminPanel{ display:none !important; visibility:hidden !important; }
#view-admin.adm-in #adminGate{ display:none !important; }
/* v1.0.660:开后台密码、但公司与平台都没登录 ⇒ 只显示登录卡片;主功能区与各页内容一律隐藏(!important 兜底) */
#adminPanel.adm-no-main #adminMainArea{ display:none !important; }
#adminPanel.adm-no-main .atab{ display:none !important; }
.form-grid{ display:grid; grid-template-columns:1fr 1fr; gap:12px; }
@media(max-width:800px){ .form-grid{ grid-template-columns:1fr; } }
.field label{ display:block; font-size:12.5px; color:var(--sub); margin-bottom:4px; }
.field .inp{ }
.qr-box{ display:flex; gap:20px; flex-wrap:wrap; }
.qr-item{ text-align:center; }
.qr-item img{ width:220px; height:220px; border:1px solid var(--line); border-radius:10px; object-fit:contain; background:var(--card); }
.center-card{ max-width:420px; margin:40px auto; padding:26px; text-align:center; }
.center-card .inp{ margin-bottom:10px; }

/* 弹窗
 * v1.0.370:自适应口径(用户报「任务单/智能调度中心的地址解析弹框看不到下方按键,要把浏览器调到 135% 才看得到」)。
 * 旧口径 `.modal{max-height:90vh; overflow:auto}` + `.modal.resizable{overflow:hidden}`:
 *   openModal 写死 `height:560px` → 超高内容(含底部 .modal-actions)直接落到弹框盒子外面,
 *   resizable 的 overflow:hidden 又把它裁掉且不可滚动 ⇒ 按键「在视口里但点不到」。
 * 新口径 = 纵向 flex 容器:正文(.modal-body)可滚动、动作区(.modal-actions)固定在最下方、
 *   整体尺寸一律「上限」语义并夹在视口内(见 js/core.js openModal)。任何分辨率/缩放下按键都在。 */
.mask{ position:fixed; inset:0; background:rgba(20,26,40,.55); z-index:2000; display:flex; align-items:center; justify-content:center; padding:12px; }
.modal{
  background:var(--card); border-radius:14px; padding:20px 22px;
  width:100%;
  max-width:min(760px, calc(100vw - 24px));      /* 窄屏/手机竖屏:先给 vw 回退(绝不横向溢出) */
  max-width:min(760px, calc(100dvw - 24px));     /* 支持 dvw 时按动态视口再收一次(写在后面即覆盖上一行) */
  max-height:calc(100vh - 24px);
  max-height:calc(100dvh - 24px);
  display:flex; flex-direction:column;           /* 纵向 flex:子项高度可分配,正文才能「伸缩 + 自己滚」 */
  overflow:hidden;                               /* 溢出由容器自己收住(不再靠横向滚动,也不再裁掉按键) */
  /* v1.0.383(全局排查):长**无空格**串(服务端报错原文/URL/单号串)以前会横向撑出弹窗被 overflow:hidden 裁掉 ——
   * 用户最需要读的"失败原因/怎么办"正好是这类,故统一允许任意断行。 */
  overflow-wrap:anywhere; word-break:break-word; min-width:0;
}
.modal h3{ margin-bottom:12px; flex:0 0 auto; }
.modal .close-x{ float:right; cursor:pointer; color:var(--sub); font-size:20px; }
/* 正文滚动态:openModal 统一把「动作区之前的全部内容」收进 .modal-body(见 js/core.js);
 * 长内容弹框也可自己把列表容器标成 .modal-body-scroll(等价口径,便于在 HTML 里单点声明)。
 * v1.0.383:正文同样允许任意断行 —— 服务端报错原文/长地址/无空格串都不许横向撑出弹窗。 */
.modal-body, .modal-body-scroll{ flex:1 1 auto; min-height:80px; overflow:auto; min-width:0; overflow-wrap:anywhere; word-break:break-word; }
/* 动作区:flex:0 0 auto ⇒ 永不被压缩;margin-top:auto ⇒ 内容不足时也贴在弹框最下方 */
.modal-actions{ display:flex; gap:10px; justify-content:flex-end; flex-wrap:wrap; flex:0 0 auto; margin-top:16px; }
.modal > .modal-actions{ margin-top:auto; padding-top:16px; }

/* 支付 */
.plan-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(150px,1fr)); gap:10px; margin:12px 0; }
.plan-item{ border:1px solid var(--line); border-radius:10px; padding:12px; text-align:center; cursor:pointer; }
.plan-item.sel{ border-color:var(--pri); background:var(--bg-tint); }
.plan-item .p{ font-size:20px; color:var(--err); font-weight:700; }
.pay-qr-tabs{ display:flex; gap:8px; margin:10px 0; }
.pay-qr-tabs button{ border:1px solid var(--line); padding:6px 16px; border-radius:8px; cursor:pointer; background:var(--card); }
.pay-qr-tabs button.active{ background:var(--pri); color:var(--on-accent); }

/* 头像 */
.avatar{ width:20px; height:20px; border-radius:50%; object-fit:cover; vertical-align:middle; display:inline-block; flex:none; }
.avatar-fb{ background:linear-gradient(135deg,var(--pri),var(--pri-lite)); color:var(--on-accent); text-align:center; line-height:20px; font-size:11px; font-weight:700; }
.avatar-lg{ width:44px; height:44px; line-height:44px; font-size:20px; }
#btnLogin{ display:inline-flex; align-items:center; gap:6px; padding:6px 12px; }
#btnLogin .avatar{ width:20px; height:20px; }
#planBadge .avatar{ width:16px; height:16px; line-height:16px; font-size:10px; margin-right:4px; }

/* 地图调度 */
.md-pin{ background:var(--pri); color:var(--on-accent); border-radius:50%; width:26px; height:26px; line-height:26px; text-align:center; font-size:12px; font-weight:700; border:2px solid #fff; box-shadow:0 1px 4px rgba(0,0,0,.4); }
.md-pin-off{ background:var(--pin-off); }
.md-pin-seq{ background:var(--accent2); }
.md-pin-cus{ background:var(--ok); font-size:10px; }
.md-pin-load{ background:var(--ok); font-size:11px; }
/* v1.0.156/157:选中线路 —— 该线收货点顺序号改为黄色(高亮放大描边),取消选中恢复原色 */
.md-pin.sel{ background:var(--mark); color:var(--mark-ink); font-weight:800; border:2px solid #fff; box-shadow:0 0 8px rgba(240,180,41,.85); transform:scale(1.22); transform-origin:center; z-index:3; }
.md-tip-sel{ border:1px solid var(--accent2) !important; font-weight:700 !important; color:var(--accent2-ink) !important; }
/* v1.0.156:选中线路信息卡(第一层,地图顶部居中,普通与全屏一致) */
.map-fs .md-line-info{
  position:absolute; top:8px; left:50%; transform:translateX(-50%); z-index:2150;
  background:rgba(255,255,255,.98); border:1px solid var(--mark); border-radius:12px;
  padding:6px 12px; font-size:12.5px; color:var(--ink-2); box-shadow:0 3px 12px rgba(0,0,0,.25);
  max-width:96%; pointer-events:none; white-space:nowrap;
}
.map-fs .md-line-info .mli-wrap{ display:flex; flex-wrap:wrap; gap:6px 16px; align-items:center; justify-content:center; }
.map-fs .md-line-info .mli-it{ white-space:normal; overflow-wrap:anywhere; }   /* v1.0.383:超长车型名/说明折行,不顶出地图 */
.md-tip{ background:rgba(255,255,255,.94); border:1px solid var(--line-strong); border-radius:6px; padding:2px 6px; font-size:11px; color:var(--txt); box-shadow:0 1px 3px rgba(0,0,0,.15); line-height:1.4; }
.md-tip small{ color:var(--sub); }
.md-box-on{ border-color:var(--accent2) !important; background:var(--accent2-bg) !important; color:var(--accent2) !important; }
.seq-chip{ display:inline-block; background:var(--accent2-bg); border:1px solid var(--warn-line); color:var(--accent2-ink); border-radius:12px; padding:2px 10px; font-size:12px; margin:2px 4px 2px 0; }
.seq-x{ cursor:pointer; color:var(--err); margin-left:4px; font-weight:700; }

/* 任务列表多选过滤 */
.filter-row{ display:flex; gap:8px; margin:8px 0; flex-wrap:wrap; }
/* v1.0.335:区划组不再是独立一行 —— display:contents 让它不生成自己的盒子,8 个下拉直接参与父级 #fltMRow 的
   flex 换行布局(⇒ 托运客户/收货人/线路/区划/五个按键同排,窄屏自动换行);用 id 选择器确保盖过 .filter-row 的 flex。 */
#fltMZoneRow{ display:contents; }
.flt{ position:relative; }
.flt-panel{ position:absolute; z-index:1200; top:36px; left:0; background:var(--card); border:1px solid var(--line); border-radius:10px; box-shadow:0 6px 18px rgba(0,0,0,.12); padding:8px; min-width:190px; max-width:calc(100vw - 24px); max-height:260px; overflow:auto; }
.flt-ops{ display:flex; gap:6px; margin-bottom:6px; }
/* v1.0.383:筛选项里的**客户名/线路名/地址**可能很长(且可能是无空格串)——
 * 以前 nowrap 只能横向撑出去(要拖横向滚动条才看得到,等于看不到)⇒ 允许折行,标签可收缩。 */
.flt-item{ display:flex; gap:6px; align-items:center; padding:3px 4px; font-size:13px; cursor:pointer; white-space:normal; overflow-wrap:anywhere; word-break:break-word; }
.flt-item > span, .flt-item > label, .flt-item > b{ min-width:0; }
.flt-item:hover{ background:var(--bg-hover); }
/* v1.0.307:多选查询条件 —— 面板内关键字模糊过滤 + 已选计数 + 反选 */
.flt-search{ width:100%; margin-bottom:6px; }
.flt-list{ max-height:210px; overflow:auto; border-top:1px solid var(--line); margin-top:2px; }
.flt-cnt{ margin-left:auto; font-size:11.5px; color:var(--sub); white-space:nowrap; }
.flt-item.flt-hide{ display:none; }
.flt-btn.flt-on{ border-color:var(--pri); color:var(--pri); box-shadow:0 0 0 2px rgba(26,102,255,.12) inset; }
.zone-line{ font-size:11.5px; color:var(--ink-2); }
.zone-line b{ color:var(--ink-2); }

.route-block.route-sel{ outline:2px solid var(--mark); background:var(--mark-bg); }

/* toast */
.toast{ position:fixed; bottom:26px; left:50%; transform:translateX(-50%); background:var(--toast-bg); color:var(--on-accent); padding:10px 20px; border-radius:10px; z-index:3000; font-size:13.5px; opacity:0; pointer-events:none; transition:.3s; }
.toast.show{ opacity:1; }
/* v1.0.405:错误提示条样式 —— 补这一条之前,「保存成功」与「保存失败」外观完全一样
 * 【为什么必须补】js/core.js 的 toast 一直给错误提示加 .err 类(`el.className='toast show'+(isErr?' err':'')`),
 *   但全项目**没有任何一条 .toast.err 规则**(本文件只有 .toast / .toast.show,皮肤文件只改 .toast 的
 *   background/color)⇒ 267 处 toast 里显式传 true 的 142 处"报错"与成功提示一个样子,用户无法从外观分辨。
 * 【取值】用 --err 令牌(五套皮肤各自定义,暗色/亮色都取到合适值)+ 白字保证对比度;左侧再加一条实色色条,
 *   即便将来有人用别的规则盖掉背景色,错误提示也还能一眼认出来(不靠单一点位)。
 * 【注意】皮肤文件的 `:root[data-theme="…"] .toast{background:…}` 优先级高于这里的 `.toast.err`
 *   ⇒ themes.css 里每个皮肤都补了一条同款 `.toast.err`;全屏那条 `!important` 也在本文件下方重申。 */
.toast.err{
  background:var(--err); color:#fff; font-weight:600;
  box-shadow:0 6px 18px rgba(0,0,0,.22), inset 6px 0 0 0 rgba(255,255,255,.55);
  padding-left:24px;
}

/* AI 面板 */
.ai-chat{ border:1px solid var(--line); border-radius:10px; max-height:320px; overflow:auto; padding:10px; margin-bottom:10px; background:var(--bg-elev); }
.ai-msg{ margin-bottom:8px; font-size:13px; }
.ai-msg .who{ font-weight:600; color:var(--pri); }
.ai-msg.user .who{ color:var(--ok); }
.kv{ display:grid; grid-template-columns:160px 1fr; gap:6px 12px; font-size:13px; }
.kv b{ color:var(--sub); font-weight:600; }
/* ---- v1.0.29:调度结果可调展示框 ---- */
.plan-box{ position:relative; border:1px solid var(--line); border-radius:10px; height:430px; min-height:140px; background:var(--card); overflow:hidden; }
.plan-box .plan-body{ height:calc(100% - 14px); overflow:auto; border-radius:10px; }
.plan-box .pb-nav{ position:absolute; right:8px; width:28px; height:28px; border:1px solid var(--line-strong); background:var(--card); color:var(--pri); border-radius:8px; cursor:pointer; z-index:5; display:none; align-items:center; justify-content:center; font-size:14px; box-shadow:0 1px 5px rgba(0,0,0,.18); line-height:1; }
.plan-box .pb-nav:hover{ background:var(--bg-tint); }
.plan-box .pb-prev{ top:40px; }
.plan-box .pb-next{ top:74px; }
.plan-box .pb-resize{ height:14px; cursor:ns-resize; text-align:center; color:var(--sub-2); font-size:11px; line-height:14px; user-select:none; background:var(--bg-elev); border-top:1px solid var(--line); }
.plan-box .pb-resize:hover{ color:var(--pri); background:var(--bg-tint); }

/* ---- v1.0.29:AI 助手可调窗口(地址解析弹框同样用 resizable+size) ----
 * v1.0.370:① 可拖大小必须**同时**设 max-width/max-height 上限,拖动不能超出视口;
 *   ② 开出来的尺寸记在 --modal-w/--modal-h(openModal 写入),CSS 用 min() 夹在视口内 —— 既保留
 *      「拖动改大小 + 尺寸记忆」,又保证宽/高是**确定值**(.ai-win 内部的聊天区/录入区比例联动依赖它);
 *   ③ 内联 max-* 只夹视口、不夹请求值,否则用户把窗口拖大也长不高/变不宽(与旧行为不一致)。 */
.modal.resizable{
  resize:both; overflow:hidden;
  min-width:300px; min-height:220px;
  width:min(var(--modal-w, 760px), calc(100vw - 24px));      /* 不支持 dvw 时的回退 */
  width:min(var(--modal-w, 760px), calc(100dvw - 24px));
  height:min(var(--modal-h, 660px), calc(100vh - 24px));
  height:min(var(--modal-h, 660px), calc(100dvh - 24px));
  max-width:calc(100vw - 24px);
  max-width:calc(100dvw - 24px);
  max-height:calc(100vh - 24px);
  max-height:calc(100dvh - 24px);
}
.modal.resizable::-webkit-resizer{ display:block; }
.ai-win{ display:flex; flex-direction:column; height:100%; min-height:320px; }
/* AI 助手窗自带纵向 flex 布局:整块撑满弹框(它的动作区嵌在录入区里,故不套通用 .modal-body) */
.modal > .ai-win{ flex:1 1 auto; min-height:0; height:auto; }
.ai-win .ai-chat{ flex:0 1 auto; min-height:140px; overflow:auto; border:1px solid var(--line); border-radius:10px; padding:10px; background:var(--bg-elev); }
.ai-win .ai-split{ flex:0 0 auto; cursor:ns-resize; text-align:center; color:var(--sub-2); font-size:11.5px; padding:3px 0; user-select:none; line-height:1; }
.ai-win .ai-split:hover{ color:var(--pri); background:var(--bg-tint); }
.ai-win .ai-input-zone{ flex:1 1 auto; display:flex; flex-direction:column; justify-content:flex-end; min-height:0; }
.ai-win .ai-input-zone .inp{ flex:1; }
.ai-win .ai-resize-note{ font-size:11px; color:var(--sub); white-space:nowrap; }

/* v1.0.62:轨迹段里程标签 */
.rt-mile-tag{ pointer-events:none; }
.rt-mile{ display:inline-block; background:var(--card); border:1.5px solid var(--pri); border-radius:10px; padding:1px 7px; font-size:11px; color:var(--ink-2); font-weight:600; white-space:nowrap; transform:translate(-50%, -50%); box-shadow:0 1px 4px rgba(0,0,0,.18); }
.rt-mile small{ display:block; font-size:9.5px; color:var(--ok); font-weight:600; text-align:center; }

/* ---- v1.0.314:地址解析(未定位)弹窗 —— 参考值下拉 + 人工录入(颜色走皮肤令牌) ---- */
.urow{ display:flex; gap:10px; align-items:flex-start; padding:9px 4px; border-bottom:1px dashed var(--line); flex-wrap:wrap; }
.urow:last-child{ border-bottom:0; }
.uaddr{ flex:1 1 240px; min-width:200px; font-size:12.5px; color:var(--ink-2); line-height:1.65; word-break:break-all; }
.uref{ flex:1 1 360px; min-width:260px; display:flex; flex-direction:column; gap:5px; }
.uref .inp{ font-size:12.5px; }
.uref .urefsel{ height:auto; padding:5px 8px; }
.uhint{ font-size:11.5px; color:var(--sub); line-height:1.7; }
.uchip{ display:inline-block; background:var(--bg-tint); border:1px solid var(--line-strong); color:var(--pri); border-radius:var(--r-pill); padding:0 7px; margin-right:4px; }
.uok{ color:var(--ok); }
.uwarn{ color:var(--warn); }
.umsg{ color:var(--sub-2); }
.ubtns{ flex:0 0 auto; display:flex; flex-direction:column; gap:6px; }
.urow.dropped{ opacity:.45; }
.urow.picked .uinput{ border-color:var(--ok); box-shadow:0 0 0 2px var(--ok-bg); }
@media(max-width:900px){ .ubtns{ flex-direction:row; width:100%; justify-content:flex-end; } }

/* ---- v1.0.318:调度方案标题行内的操作按钮(导出/打印/显示路线/添加任务) ---- */
.md-plan-head{ flex-wrap:wrap; gap:6px 10px; align-items:center; }
.md-plan-tools{ display:flex; flex-wrap:wrap; gap:6px; align-items:center; min-width:0; flex:0 1 auto; }
.md-plan-tools .btn{ flex:0 0 auto; white-space:nowrap; }
/* 「＋ 添加任务」与其选择下拉框为**同一组**:要么同行显示,要么整组换行,不会被拆到两行 */
.md-plan-tools .md-add-group{ display:inline-flex; flex-wrap:nowrap; gap:6px; align-items:center; flex:0 0 auto; }
.md-plan-tools .md-add-group > select.inp{ max-width:320px; min-width:120px; flex:0 1 auto; }
.md-plan-head .md-rx{ margin-left:auto; }

/* ---- v1.0.321:全屏地图的方案面板 —— 标题行(含 导出/打印/显示路线/添加任务/保存/取消)+ 方案汇总卡片头 显示为首行 ----
 * 背景:上一版把操作按钮移进了「调度方案」标题行;而下面那条「全屏面板内隐藏所有卡片头」是为省空间写的,
 * 会把整行按钮与「方案汇总」的展开/收起按钮一起藏掉 → 这里对方案面板单独放开,其余面板的卡片头保持隐藏。 */
/* v1.0.322 修正:选择器必须挂在「被搬动的卡片」上(#mdPlanCard) —— 全屏搬运后 #mdPanePlan 已不是祖先,旧选择器永不匹配 */
.map-fs .fs-panel-body #mdPlanCard > .card-head{ display:flex !important; flex-wrap:wrap; gap:6px 10px; align-items:center; padding:2px 2px 6px; }
.map-fs .fs-panel-body #mdPlanCard > .card-head .md-grip,
.map-fs .fs-panel-body #mdPlanCard > .card-head .md-rx{ display:none !important; }   /* 全屏内不需要拖面板/拖宽把手(全屏有自己的拖柄) */
.map-fs .fs-panel-body #mdPlanBody .card-head{ display:flex !important; flex-wrap:wrap; gap:6px 10px; align-items:center; }   /* 方案汇总/自选方案卡片头(含「▼ 展开/▲ 收起」) */
/* 全屏面板较窄(默认 720px 上限):按钮更紧凑,宽度不够时按整行自动换行;「＋添加任务」与其下拉框仍整组不拆 */
.map-fs .fs-panel-body .md-plan-tools .btn{ padding:3px 9px; font-size:12px; }
.map-fs .fs-panel-body .md-plan-tools .md-add-group > select.inp{ max-width:240px; }
/* v1.0.322 双保险:凡被搬进全屏面板的卡片,其标题行都放开显示(不依赖卡片原来挂在哪个父节点下) */
.map-fs .fs-panel-body > .md-card-in-fspanel > .card-head{ display:flex !important; flex-wrap:wrap; gap:6px 10px; align-items:center; padding:2px 2px 6px; }

/* ---- v1.0.323:任务说明(警告/提示)卡片与逐条列表(默认展开,每条一行) ---- */
.md-warn-card{ border-left:3px solid var(--warn); }
.md-warn-list{ margin:2px 0 0; padding-left:20px; max-height:280px; overflow:auto; font-size:12.5px; line-height:1.8; color:var(--warn); }
.md-warn-list li{ margin:0 0 2px; word-break:break-all; }
.md-warn-list li.md-warn-note{ color:var(--sub); }   /* ⏱ 开头的预算/结构提示:次要色,与真警告区分 */
.map-fs .fs-panel-body .md-warn-list{ max-height:200px; }

/* ================= v1.0.324:同款 3D 立体按键语言扩展到「页签 / 顶栏导航 / 浮层开关」 =================
 * 目标:任务单、智能调度中心、调度单、车型库、后台管理 五处的**所有可点按键**观感一致 ——
 *      与 .btn 同一套「会受光的渐变面 + 1px 描边 + 底边厚度 + 内高光/环境影 + 悬停上浮/按下下压」。
 * 做法:保留各控件原有的尺寸/布局规则(本段只改"面子":面、边、影、状态色),颜色一律取令牌。 */
.tabs .tab, .plan-tabs button, .pay-qr-tabs button{
  border:1px solid var(--line-strong);
  background:linear-gradient(180deg, var(--card) 0%, var(--bg-elev) 46%, var(--bg-soft) 100%);
  color:var(--txt);
  border-radius:var(--r-sm);
  font-weight:500;
  box-shadow:inset 0 1px 0 var(--card), inset 0 -2px 0 rgba(0,0,0,.055), 0 2px 0 var(--bg), 0 4px 7px rgba(0,0,0,.10);
  transform:translateY(0);
  transition:transform .12s ease, box-shadow .12s ease, border-color .12s ease, color .12s ease;
}
.tabs .tab:hover, .plan-tabs button:hover, .pay-qr-tabs button:hover{
  border-color:var(--pri); color:var(--pri);
  background:linear-gradient(180deg, var(--card) 0%, var(--bg-tint) 100%);
  box-shadow:inset 0 1px 0 var(--card), inset 0 -2px 0 rgba(0,0,0,.05), 0 3px 0 var(--pri-lite), 0 6px 11px rgba(0,0,0,.13);
  transform:translateY(-1px);
}
.tabs .tab:active, .plan-tabs button:active, .pay-qr-tabs button:active{
  transform:translateY(1px);
  box-shadow:inset 0 2px 5px rgba(0,0,0,.18), inset 0 -1px 0 rgba(0,0,0,.04), 0 1px 0 var(--bg), 0 1px 2px rgba(0,0,0,.08);
}
/* 选中态(页签在当前页 / 布局键当前生效 / 筛选已开启):主色立体面 + 压下一格 = "锁定"的观感 */
.tabs .tab.active, .plan-tabs button.active, .pay-qr-tabs button.active, #nav button.active,
.md-layoutbar .layout-btn.active, .flt-btn.flt-on{
  border-color:var(--pri-d);
  background:linear-gradient(180deg, var(--pri) 0%, var(--pri-2) 100%);
  color:var(--on-accent);
  font-weight:600;
  box-shadow:inset 0 1px 0 var(--pri-lite), inset 0 -2px 0 rgba(0,0,0,.16), 0 1px 0 var(--pri-d), 0 4px 9px rgba(0,0,0,.18);
  transform:translateY(1px);
}
.tabs .tab.active:hover, .plan-tabs button.active:hover, .pay-qr-tabs button.active:hover, #nav button.active:hover{ color:var(--on-accent); border-color:var(--pri-d); }
/* 顶栏导航(切换这五个页面):未选中保持"平"(简洁),悬停浮起成键,选中为主色立体键。
 * 边框改透明 1px 并同步收紧内边距(7/13 + 1px 边 == 原来的 8/14 + 无边),顶栏高度不变。 */
#nav button{
  border:1px solid transparent; border-radius:var(--r-sm);
  padding:7px 13px;
  transform:translateY(0);
  transition:transform .12s ease, box-shadow .12s ease, border-color .12s ease, color .12s ease, background .14s ease;
}
#nav button:hover{
  border-color:var(--line-strong);
  background:linear-gradient(180deg, var(--card) 0%, var(--bg-tint) 100%);
  box-shadow:inset 0 1px 0 var(--card), 0 2px 0 var(--bg), 0 5px 10px rgba(0,0,0,.10);
  transform:translateY(-1px);
}
#nav button:active{ transform:translateY(1px); box-shadow:inset 0 2px 5px rgba(0,0,0,.18), 0 1px 0 var(--bg); }
/* 浮层小按键(全屏退出 / 方案翻页 / 点选 HUD 的「车型」图标键):同样的立体键 */
.map-fs .fs-exit, .plan-box .pb-nav, .map-fs .md-seq-hud .md-veh-toggle{
  border:1px solid var(--line-strong);
  background:linear-gradient(180deg, var(--card) 0%, var(--bg-soft) 100%);
  box-shadow:inset 0 1px 0 var(--card), inset 0 -2px 0 rgba(0,0,0,.05), 0 2px 0 var(--bg), 0 4px 8px rgba(0,0,0,.12);
  transition:transform .12s ease, box-shadow .12s ease, border-color .12s ease, color .12s ease;
}
.map-fs .md-seq-hud .md-veh-toggle{ box-shadow:inset 0 1px 0 var(--card), inset 0 -1px 0 rgba(0,0,0,.045), 0 1px 0 var(--bg), 0 2px 4px rgba(0,0,0,.10); }
.map-fs .fs-exit:hover, .plan-box .pb-nav:hover{ border-color:var(--pri); color:var(--pri); transform:translateY(-1px); }
.map-fs .md-seq-hud .md-veh-toggle:hover{
  border-color:var(--pri); color:var(--pri); transform:translateY(-1px);
  background:linear-gradient(180deg, var(--card) 0%, var(--bg-tint) 100%);
  box-shadow:inset 0 1px 0 var(--card), 0 2px 0 var(--pri-lite), 0 4px 8px rgba(0,0,0,.14);
}
.map-fs .fs-exit:active, .plan-box .pb-nav:active, .map-fs .md-seq-hud .md-veh-toggle:active{
  transform:translateY(1px);
  box-shadow:inset 0 2px 5px rgba(0,0,0,.18), 0 1px 0 var(--bg);
}
/* 皮肤选择卡(后台 → 系统参数 → 界面皮肤):卡片本身,加同样的悬停浮起手感 */
.theme-chip{ transition:transform .12s ease, box-shadow .12s ease, border-color .12s ease; }
.theme-chip:hover{ transform:translateY(-1px); }

/* ================= v1.0.325:全屏地图「浮层透明度」(用户可自定义,退出记住,默认 70% 透明) =================
 * 需求:全屏地图上盖在地图上的浮层 —— 展示框(.md-line-info)、卡片(任务单卡/调度方案卡 .fs-panel*)、
 *      操作窗口(工具条 .fs-tools、询问卡 .fs-ask-card、点选 HUD .md-seq-hud、进度条 .md-progress-fs)、
 *      控件(线路下拉 .fs-route、退出键 .fs-exit、工具条内下拉/时间框、地图缩放键 .leaflet-bar a)、
 *      地图提示气泡 .md-tip —— 都可调透明度:完全透明 / 10%…90% 透明 / 不透明,共 11 档。
 * 做法:JS 把用户档位换算成根元素上的 CSS 变量 `--fs-solid`(浮层「不透明度」百分比 = 100 - 透明度;
 *      默认 70% 透明 ⇒ 不透明度 30%),这里用 color-mix 把主题浮层色按该比例混成半透明底。
 * 要点:① 只改 background ⇒ **文字/图标始终清晰**,完全透明时只看得见文字;
 *      ② 浮层色取令牌 `--overlay` ⇒ 5 套皮肤(含深色)颜色都正确,不会出现刺白块;
 *      ③ 只作用于全屏(`.map-fs:fullscreen`)⇒ 普通视图里的地图/列表观感零变化;
 *      ④ 卡内"整块面板"(.plan-box / 表头 th / 汇总条 .summary-bar / 列表 .pick-list)一并淡化,避免卡片里出现不透明补丁。
 * 注:悬停/选中态(高亮)仍用主题色,保持清晰的操作反馈。
 * ---------------------------------------------------------------------------
 * v1.0.337 修复(用户反馈:全屏地图的浮层透明度「在各皮肤样式都要生效」):
 *   实测(Edge 无头浏览器读 getComputedStyle,脚本 `_veil_probe.js`,5 个皮肤逐一对比
 *   --fs-solid=100% 与 30% 的 background)发现两类问题:
 *   ① **皮肤相关**:卡片内层 `.fs-panel-body .card` 在 tech/vivid/eye 三个皮肤下被皮肤层的
 *      `.card{background:var(--card)}` 盖回不透明(那里特指度 (0,4,0) 高过本文件里
 *      `.map-fs .fs-panel-body .card{background:transparent}` 的 (0,3,0)),经典/lively 正常
 *      ⇒ 用户在不同皮肤下看到"有的生效、有的不生效";
 *   ② **清单不全(所有皮肤都存在的不透明补丁)**:卡内按键/输入框/筛选下拉弹层/线路块、
 *      方案盒翻页键、工具条按键(含 `!important` 的框选激活键)、点选 HUD 的车型输入与建议下拉、
 *      以及**被搬进全屏元素里的弹窗 .modal / 提示条 .toast / 皮肤弹层 .theme-pop** 都没有被淡化。
 *   修法:① 把浮层清单补全(见下);② 声明加 `!important` —— 该透明度是用户显式设定的**覆盖层**,
 *      必须压过任何皮肤规则(含 `.md-box-on{background:…!important}`)与三代皮肤覆盖;因为选择器全部
 *      限定在 `.map-fs:fullscreen`,普通视图零影响;③ 主键/激活态/悬停用「同一档位 + 各自主题色」重新声明,
 *      保证淡化后仍能一眼分清主次;④ `css/themes.css` 末尾保留一份**同清单**的皮肤层重申(带 !important 与
 *      皮肤前缀),并由 test_node 护栏断言两份清单完全一致,防止日后只改一处。
 * 生效范围(全屏地图内):浮层底 + 卡内层 + 控件 + 弹窗/提示 + 地图气泡,基础清单共 36 个选择器(原有 17 + 补齐 19),
 * 另加 5 组「同档位保留主次/反馈」的状态声明;5 个皮肤一致(script `_veil_probe.js` 实测 0 处不生效)。 */
.map-fs:fullscreen .md-progress-fs,
.map-fs:fullscreen .fs-exit,
.map-fs:fullscreen .fs-route,
.map-fs:fullscreen .fs-tools,
.map-fs:fullscreen .fs-launch-card,   /* ★ v1.0.538:新增浮层登记进透明度清单 */
.map-fs:fullscreen .fs-tools .fs-tool-sel,
.map-fs:fullscreen .fs-tools .fs-tool-inp,
.map-fs:fullscreen .fs-panel-tab,
.map-fs:fullscreen .fs-panel-body,
.map-fs:fullscreen .fs-ask-card,
.map-fs:fullscreen .md-seq-hud,
.map-fs:fullscreen .md-line-info,
.map-fs:fullscreen .leaflet-bar a,
.map-fs:fullscreen .fs-panel-body .plan-box,
.map-fs:fullscreen .fs-panel-body th,
.map-fs:fullscreen .fs-panel-body .summary-bar,
.map-fs:fullscreen .fs-panel-body .pick-list,
.map-fs:fullscreen .md-tip,
/* v1.0.337 补全:卡内层 + 控件 + 弹窗/提示 + HUD 控件 + 拖动条 */
.map-fs:fullscreen .fs-panel-body .card,
.map-fs:fullscreen .fs-panel-body .fleet-card,
.map-fs:fullscreen .fs-panel-body .table-wrap,
.map-fs:fullscreen .fs-panel-body .route-block,
.map-fs:fullscreen .fs-panel-body .plan-tabs button,
.map-fs:fullscreen .fs-panel-body .btn,
.map-fs:fullscreen .fs-panel-body .inp,
.map-fs:fullscreen .fs-panel-body .flt-panel,
.map-fs:fullscreen .fs-panel-resize,
.map-fs:fullscreen .fs-panel-wresize,
.map-fs:fullscreen .plan-box .pb-nav,
.map-fs:fullscreen .plan-box .pb-resize,
.map-fs:fullscreen .fs-tools .btn,
.map-fs:fullscreen .md-seq-hud .md-veh-toggle,
.map-fs:fullscreen .md-seq-hud .md-veh-inp,
.map-fs:fullscreen .md-seq-hud .md-veh-sug,
.map-fs:fullscreen .modal,
.map-fs:fullscreen .toast,
.map-fs:fullscreen .theme-pop{
  background:color-mix(in srgb, var(--overlay) var(--fs-solid, 30%), transparent) !important;
}
/* v1.0.405:全屏下上面那条 !important 会把 .toast.err 的红底一起压成半透明浮层色 ⇒ 错误提示在这里重申一次。
 * 沿用同一个 --fs-solid(用户选的浮层透明度)口径,不另造一套透明度;
 * ★ 这里**只写 background 的令牌混色** —— 本段(全屏浮层规则区)有两条硬纪律:不得写死颜色、`!important`
 *   只能出现在 background 的 color-mix 上(见 test_node 的 v1.0.337 护栏)。文字白色与左侧色条由
 *   上面的 .toast.err 基规则与皮肤层的同款规则负责,不在这里抢。 */
.map-fs:fullscreen .toast.err{
  background:color-mix(in srgb, var(--err) var(--fs-solid, 30%), transparent) !important;
}
/* v1.0.337:同一档位下保留主次与操作反馈(仍带 !important,避免被皮肤规则盖回不透明) */
.map-fs:fullscreen .btn.primary,
.map-fs:fullscreen .plan-tabs button.active{
  background:color-mix(in srgb, var(--pri) var(--fs-solid, 30%), transparent) !important;
}
.map-fs:fullscreen .btn.md-box-on{
  background:color-mix(in srgb, var(--accent2-bg) var(--fs-solid, 30%), transparent) !important;
}
.map-fs:fullscreen .pick-item.sel{
  background:color-mix(in srgb, var(--bg-sel) var(--fs-solid, 30%), transparent) !important;
}
.map-fs:fullscreen .btn:hover,
.map-fs:fullscreen .pick-item:hover,
.map-fs:fullscreen .plan-box .pb-nav:hover,
.map-fs:fullscreen .plan-box .pb-resize:hover,
.map-fs:fullscreen .fs-panel-resize:hover,
.map-fs:fullscreen .fs-panel-wresize:hover{
  background:color-mix(in srgb, var(--bg-tint) var(--fs-solid, 30%), transparent) !important;
}

/* ================================================================
 * 【阶段B · AI 批量清洗地址 / AI 脏数据体检】界面样式
 * ----------------------------------------------------------------
 * 口径:一律使用设计令牌(皮肤变量)—— **不写死任何颜色**,5 套皮肤与深色皮肤自动适配。
 * 颜色语义:❌必改 = --err/--err-bg;⚠建议核 = --warn/--warn-bg/--warn-ink;ℹ提示 = --pri/--bg-tint。
 * ================================================================ */
.ai-opts{ display:flex; flex-direction:column; gap:6px; margin:8px 0; }
.ai-opt{ display:flex; align-items:center; gap:8px; padding:6px 10px; border:1px solid var(--line); border-radius:var(--r-sm); background:var(--bg-soft); cursor:pointer; font-size:13px; }
.ai-opt:hover{ background:var(--bg-tint); }
.ai-opt b{ color:var(--pri); font-weight:600; }
.ai-est{ margin:8px 0; padding:8px 10px; border-left:3px solid var(--pri); border-radius:var(--r-sm); background:var(--bg-tint); color:var(--ink-2); font-size:12.5px; line-height:1.6; }
.ai-prog{ display:flex; justify-content:space-between; align-items:center; gap:10px; padding:10px 12px; margin:10px 0; border:1px solid var(--line); border-radius:var(--r-md); background:var(--bg-soft); font-size:13.5px; }
.ai-prog .ai-done{ color:var(--sub); font-size:12.5px; }
.ai-prog .ai-done b{ color:var(--pri); font-size:15px; }
.ai-tbl-wrap{ border:1px solid var(--line); border-radius:var(--r-sm); padding:6px; margin:8px 0; }
.ai-tbl{ width:100%; }
.ai-tbl th, .ai-tbl td{ font-size:12.5px; vertical-align:top; }
.ai-tbl .ai-ck{ width:44px; text-align:center; }
.ai-tbl .ai-no{ white-space:nowrap; }
.ai-tbl .ai-old{ color:var(--sub); }
.ai-tbl .ai-new{ color:var(--ok); font-weight:600; }
.ai-tbl .ai-parts{ display:block; color:var(--pri); font-weight:600; }
.ai-tbl .ai-geo{ color:var(--sub); }
.ai-tbl .ai-conf{ color:var(--sub); font-size:11.5px; }
.ai-chip{ display:inline-block; padding:2px 8px; border-radius:var(--r-pill); font-size:11.5px; }
.ai-chip-ok{ background:var(--ok-bg); color:var(--ok); }
.ai-chip-same{ background:var(--bg-tint); color:var(--sub); }
.ai-chip-warn{ background:var(--warn-bg); color:var(--warn-ink); }
.ai-chip-err{ background:var(--err-bg); color:var(--err); }
.ai-lv{ display:inline-block; padding:2px 9px; border-radius:var(--r-pill); font-size:12px; font-weight:600; white-space:nowrap; }
.ai-lv-must{ background:var(--err-bg); color:var(--err); }
.ai-lv-warn{ background:var(--warn-bg); color:var(--warn-ink); }
.ai-lv-info{ background:var(--bg-tint); color:var(--pri); }
.ai-lvbar{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin:8px 0; }
.ai-lvbar .ai-sum{ color:var(--sub); font-size:12.5px; }
.ai-src{ color:var(--sub); font-size:11.5px; }
.ai-skip{ margin:6px 0; font-size:12.5px; color:var(--sub); }
.ai-skip summary{ cursor:pointer; color:var(--warn-ink); }
.ai-skip-list{ max-height:160px; overflow:auto; padding:6px 10px; margin-top:6px; border:1px solid var(--line); border-radius:var(--r-sm); background:var(--bg-soft); }
.ok-line{ color:var(--ok); font-size:13px; padding:6px 12px; }

/* ============================================================================
 * v1.0.440:「用平台的 / 用我自己的」二选一单选块(用户后台「地图配置 / AI 模型」两页共用)
 * ----------------------------------------------------------------------------
 * 为什么从 JS 内联样式搬到这里(而不是继续写在 sharedSrcPickHtml 里):
 *   ① **布局要能响应窄屏** —— 内联的 grid-template-columns:1fr 1fr 在手机上会把两张卡片挤成一团;
 *      这里照 .form-grid 的既有模式:**默认两列 + 窄屏塌成一列**(断点跟它保持一致,用 800px);
 *   ② **颜色/圆角走主题令牌** —— 项目有 5 套皮肤(含深色),写死色值会串味。
 * 类名与"二选一"这个业务概念同名,便于在 CSS 与 auth.js 之间互相检索。
 * ========================================================================== */
.shared-src-pick{ margin:10px 0 6px; }
.shared-src-pick .ssp-head{ margin:0 0 8px; }
.shared-src-pick .ssp-grid{ display:grid; grid-template-columns:1fr 1fr; gap:10px; align-items:stretch; }
.shared-src-card{
  display:block; padding:10px 12px; border-radius:var(--r-md,8px);
  border:1px solid var(--line); background:transparent;
  cursor:pointer; line-height:1.6; transition:border-color .15s, background .15s;
}
.shared-src-card:hover{ border-color:var(--pri-lite); }
.shared-src-card input[type=radio]{ margin-right:8px; vertical-align:middle; }
.shared-src-card .ssp-sub{ display:block; padding-left:22px; }
.shared-src-card.is-now{ border:2px solid var(--pri); background:var(--bg-tint); }
/* 不可选(平台这一块没配)⇒ 变灰。
 * ★ 用**文字色令牌**变灰,而不是 `opacity`:项目的既有口径是"只淡化底色、不整块降透明度"
 *   (透明会把文字一起变淡,完全透明时不可读 —— 见 v1.0.325 那条断言的口径)。 */
.shared-src-card.is-disabled{ cursor:not-allowed; }
.shared-src-card.is-disabled b,
.shared-src-card.is-disabled .ssp-sub{ color:var(--sub-3); }
.shared-src-pick .ssp-now{ margin:8px 0 0; }
.shared-src-pick .ssp-now b{ color:var(--pri); }
/* 「◀ 当前生效」标记与"当前正在使用…"同色(都表示"这就是现在生效的那一个") */
.shared-src-pick .ssp-now-flag{ color:var(--pri); }
/* 警示句(未授权 / 平台这一块没配)—— 走 warn 令牌,深色皮肤下也协调 */
.shared-src-pick .ssp-warn{ color:var(--warn); }
.shared-src-pick .ssp-fallback{
  border-left:3px solid var(--warn); background:var(--warn-bg); color:var(--warn);
  padding:6px 10px; border-radius:var(--r-sm,6px); margin:8px 0 0;
}
/* 窄屏:两列塌成一列(与 .form-grid 同一断点,免得同一页里两块卡片在不同宽度各自换行) */
@media(max-width:800px){ .shared-src-pick .ssp-grid{ grid-template-columns:1fr; } }
/* 打印:选择器是屏幕上的交互件,不进打印件。
 * ★ 不用 `!important`(项目口径:它只许用在 background 混色声明上)——
 *   `.shared-src-pick` 是类选择器(0,1,0),显示它的都是 `#atab-*` 这类容器,
 *   打印时本来就不打印后台页;这里只是兜底,同权重下后出现的规则胜出。 */
@media print{ .shared-src-pick{ display:none; } }

/* ★ v1.0.529:三个开关并排一行(线路优先 / 跨线搬点 / 加速模式)—— 用户要求。
 *   面板的 .md-ctrl-row 是**两列网格**(首列 5em 放标题),并排放不下 ⇒ 变体行跨整行、
 *   内部用 flex 并排;窄屏(≤800px)允许换行,绝不横向溢出。 */
.md-ctrl-row.md-ctrl-row-3{ grid-template-columns:1fr; }
.md-ctrl-row.md-ctrl-row-3 > *{ min-width:0; }
.md-ctrl-row-3{ display:flex; flex-wrap:wrap; align-items:center; gap:6px 18px; }
.md-ctrl-row-3 .chk{ display:inline-flex; align-items:center; gap:6px; white-space:nowrap; }
.md-ctrl-row-3 .md-ctrl-note:empty{ display:none; }
/* 全屏:三个开关并排 */
.fs-row-switch3{ display:flex; flex-wrap:wrap; gap:6px 18px; align-items:center; }
.fs-row-switch3 .fs-tool-chk{ white-space:nowrap; }
@media (max-width:800px){ .fs-row-switch3{ gap:4px 12px; } }

/* ★ v1.0.532(用户需求一):「生成调度方案」浮卡 —— 可拖动 + 四边磁性吸附 + 可收起。
 *   位置/收起态存进设置(mdFsLaunchDock),与 #mdFsTools 的 mdFsToolsBox 同一套写法。
 *   吸附位:top=正上方(默认)/ bottom=正下方 / left=左中方 / right=右中方(data-dock)。
 *   ⚠ 纪律:不写 opacity/filter;不用 !important(**吸附定位由 JS 清理内联样式实现**);
 *     颜色一律走皮肤变量 var(--*)。收起态只在**全屏浮层**里,面板(非全屏)不受影响。 */
.fs-launch-card{ position:fixed; z-index:2150; display:flex; flex-direction:column; align-items:stretch; gap:6px; box-sizing:border-box; resize:both; overflow:hidden; min-width:280px; min-height:44px; max-width:96vw; max-height:92vh;
  padding:6px 8px; border-radius:10px; background:var(--card); border:1px solid var(--line);
  box-shadow:var(--shadow-2); touch-action:none; user-select:none; }
/* ★ v1.0.550(用户澄清):浮卡左上角 ⣿ 把手**保留**(可拖动整张卡片);右下角**保留**拖大小 */
.fs-launch-card .fs-lc-grip{ cursor:grab; padding:0 4px; color:var(--sub); font-size:14px; line-height:1; }
.fs-launch-card .fs-lc-grip:active{ cursor:grabbing; }
/* 吸附后的定位:由 JS 先清掉内联 left/top/right/bottom/transform,再靠这三个类落位 */
.fs-launch-card[data-dock="top"]{ left:50%; top:64px; right:auto; bottom:auto; transform:translateX(-50%); }   /* ★ v1.0.533:让开全屏进度条(top:10px,z-index 2100) */
.fs-launch-card[data-dock="bottom"]{ left:50%; top:auto; right:auto; bottom:10px; transform:translateX(-50%); }
.fs-launch-card[data-dock="left"]{ left:10px; top:50%; right:auto; bottom:auto; transform:translateY(-50%); }
.fs-launch-card[data-dock="right"]{ left:auto; top:50%; right:10px; bottom:auto; transform:translateY(-50%); }
/* 收起态:只留把手 + 收起按钮 + 回显按钮 */
.fs-launch-card .fs-lc-mini{ display:none; }
.fs-launch-card.fs-lc-collapsed .fs-launch{ display:none; }
.fs-launch-card.fs-lc-collapsed .fs-lc-mini{ display:inline-flex; align-items:center; }
/* 收起/展开按钮 */
.fs-launch-card .fs-lc-toggle{ font-size:12px; line-height:1; padding:3px 6px; }
/* ★ 顶栏让位由 mapdispatch.js 的 mdFsLaunchApplyNudge() **直接设内联 marginTop** 实现 ——
 *   不经 CSS 令牌(与既有 --modal-h 同一路数:运行时值不进令牌表,不破坏皮肤令牌一致性断言)。 */

/* ★ v1.0.536:浮卡 = 整张卡片。卡内 `#mdFsTools` **不再自己定位**(它现在是被拖动的卡片的**内容**),
 *   否则会出现「卡片里再套一张会跑的小卡片」。卡片行(fs-lc-bar)常显,含把手与收起按钮。 */
.fs-launch-card .fs-lc-bar{ display:flex; align-items:center; gap:8px; }
/* ★★★ v1.0.554(**用户要求:拖右下角时「内外两个卡片一起自动大小」**)======================
 *   【原来的病】外层 `.fs-launch-card` 与内层 `#mdFsTools` **各带一个 resize 手柄**
 *     (内层来自 `.map-fs .fs-tools{ resize:both }`),而且内层还被 `mdFsToolsRestore()`
 *     写死了内联 `width/height` ⇒ 拖外层右下角时**只有外层变大、内层不动**;
 *     拖到内层手柄时又只有内层变、外层不动 ⇒ 用户看到"两张卡不同步"。
 *   【现在的口径】**外层是唯一的缩放源**:内层**取消自己的 resize 手柄**、
 *     取消内联尺寸,纯靠 flex 填满外层 ⇒ **拖外层右下角 = 内外一起变**。
 *   `resize:none` 在这里不是装饰 —— 它把内层那颗"多余的右下角手柄"真正去掉。 */
.fs-launch-card #mdFsTools{ position:static; left:auto; right:auto; top:auto; bottom:auto; transform:none;
  margin:0; margin-top:0; max-width:none; max-height:none; resize:none;
  width:100%; height:auto; flex:1 1 auto; min-height:0; min-width:0; overflow:auto; }   /* ★ v1.0.554:内层取消自己的 resize,靠 flex **填满外层** ⇒ 拖外层右下角时内外一起变 */
/* 收起态:整卡只剩(把手 + 收起按钮 + 回显按钮)—— 用户要求「收起时的显示部分为【生成调度方案】」 */
.fs-launch-card.fs-lc-collapsed #mdFsTools{ display:none; }
/* 拖动时不做任何淡化(皮肤纪律:规则内不得出现 opacity / filter) */

/* ★ v1.0.540(用户报障「三组选项没跟浮卡高宽一起调整」):
 *   卡内三组原为 `justify-content:center` + 各 `fs-group` 按**内容定宽** ⇒ 卡片拖宽后仍挤在中间、不铺开。
 *   这里在**卡片语境下**(`.fs-launch-card` 内)改为:分组行占满宽、每个分组按可用宽度**均分并允许收缩**,窄卡自动换行。
 *   ⚠ 只限定在卡内,不影响面板/旧工具条语境(非全屏)的同名类。 */
.fs-launch-card #mdFsTools .fs-groups{ width:100%; justify-content:flex-start; align-items:stretch; }
.fs-launch-card #mdFsTools .fs-group{ flex:1 1 0; min-width:0; box-sizing:border-box; }   /* ★ v1.0.542:**等分**宽度(原来 basis=320px ⇒ 各组宽窄不一) */
/* ★ v1.0.542:卡片太窄时,让整组**换行**成一行一组(而不是把三组各自压扁) */
@media (max-width:760px){
  .fs-launch-card #mdFsTools .fs-group{ flex:1 1 100%; }
}
.fs-launch-card #mdFsTools .fs-row-ops{ min-width:0; }   /* ★ v1.0.542:操作列允许收缩,不撑破分组 */
.fs-launch-card #mdFsTools .fs-tool-sel,
.fs-launch-card #mdFsTools .fs-tool-inp{ max-width:100%; min-width:0; }
.fs-launch-card #mdFsTools .fs-launch{ width:100%; }
