/* 梅笛 CRM · 双主题（深色 aurora / 浅色）
   自包含样式，无外部依赖。

   ── 主题机制 ──
   深色是默认（:root），浅色是 [data-theme="light"] 覆盖。
   切换只改 <html data-theme> 一个属性 + 往 localStorage 记一笔，不重载页面。

   ⚠️ 为什么要把「白色半透明叠层」抽成变量（--fill-1/2/3）：
      深色下「浮起来」的药水是 `rgba(255,255,255,.05)`（白里加白），
      但浅色底上白+白 = 看不见 ⇒ 必须换成 `rgba(15,23,42,.045)`（黑里加黑）。
      原来是硬编码的，共 29 处；不抽变量就得在浅色块里逐个 !important 覆写，
      以后每加一个组件都会再漏一次。抽完浅色只需覆盖变量。
      --overlay-* 则是「越浮越亮」的弹层底，浅色下要换成实色白。 */

:root,
[data-theme="dark"] {
  color-scheme: dark;
  --bg: #070b14;
  --bg-2: #0b1222;
  --panel: rgba(19, 26, 45, 0.72);
  --panel-solid: #111a2e;
  --panel-hi: rgba(30, 41, 68, 0.9);
  --line: rgba(255, 255, 255, 0.08);
  --line-strong: rgba(255, 255, 255, 0.14);
  --text: #e8eefb;
  --text-2: #9fb0cb;
  /* 介于 --text-2 与 --text-3 之间的一档：给侧边栏分组标题用。
     原方案直接用 --text-3，在深色底上实测对比度 4.75:1（刚过 WCAG AA 4.5 线），
     中文小字条件下明显吃力；但直接跳到 --text-2 又会和菜单项同色、丢掉层级。 */
  --text-2b: #8fa3c2;
  --text-3: #7a8dab;
  --accent: #38bdf8;
  --accent-2: #a78bfa;
  --up: #f43f5e;      /* 涨 = 红（国内习惯） */
  --down: #22c55e;    /* 跌 = 绿 */
  --warn: #fbbf24;
  --radius: 14px;
  --radius-sm: 9px;
  --shadow: 0 18px 50px rgba(0, 0, 0, 0.45);
  --shadow-sm: 0 4px 14px rgba(0, 0, 0, 0.3);

  /* 叠层药水：数字越大越「浮起来」 */
  --fill-1: rgba(255, 255, 255, 0.02);
  --fill-2: rgba(255, 255, 255, 0.045);
  --fill-3: rgba(255, 255, 255, 0.06);
  --fill-4: rgba(255, 255, 255, 0.085);
  --fill-hover: rgba(255, 255, 255, 0.055);

  /* 输入框 / 弹层底：深色下是「比背景更深的墨」 */
  --input-bg: rgba(8, 13, 24, 0.72);
  --scroll-thumb: rgba(255, 255, 255, 0.13);
  --scroll-thumb-hover: rgba(255, 255, 255, 0.2);
  --grid-line: rgba(255, 255, 255, 0.016);

  /* 主按钮上的字色（accent 渐变底上的对比色） */
  --on-accent: #05101f;
  /* 语义色的「前景文字版」——深色底上要提亮才够对比 */
  --danger-fg: #ffa9b8;
  --danger-fg-soft: #ffb3c1;
  --accent-fg: #8fd8f8;
  --accent-2-fg: #c4b0fb;
  --ok-fg: #86efac;
  --warn-fg: #fcd34d;
  --neutral-fg: #a8b6c8;
  --avatar-bg: linear-gradient(135deg, #334155, #1e293b);
  --avatar-fg: #cbd5e1;
  /* === 可读性修正（浅色主题实测倒推） === */
  --nav-dim: #7a8dab;                 /* 侧栏分组计数/折叠箭头 */
  --badge-dim: #7a8dab;               /* 侧栏「已有」小徽标 */
  --trend-up: #f87171;                /* KPI 小字同环比·涨（深色下红要提亮） */
  --trend-down: #4ade80;              /* KPI 小字同环比·跌 */
  /* 以下两条是深色下的**存量**缺陷（原色直接当文字用）：
     #f43f5e 在白/深底都只有 4.35:1，已在 4.5 线下；
     #475569（公海/已作废）在深底只有 2.19:1，几乎看不见 —— 而「公海」是每天必点的标签。 */
  --st-deal: #fb7185;                 /* 已成交/五星等用 #f43f5e 的标签 */
  --st-sea: #94a3b8;                  /* 公海/已作废 */
  /* 状态标签的深色档（保持原色相） */
  --st-new: #38bdf8;
  --st-following: #a78bfa;
  --st-wechat: #22d3ee;
  --st-intent: #fbbf24;
  --st-quoted: #fb923c;
  --st-invalid: #94a3b8;
  --funnel-fg: #04121f;
  /* 侧边栏当前项的字色：深色下用白，浅色下用蓝（配浅蓝底） */
  --nav-active-fg: #ffffff;

  /* aurora 光斑强度：深色下要明显，浅色下必须几乎看不见（否则像脏了） */
  --aurora-1: rgba(56, 189, 248, 0.20);
  --aurora-2: rgba(167, 139, 250, 0.18);
  --aurora-3: rgba(20, 184, 166, 0.13);
}

/* ---------------- 浅色主题 ----------------
   目标不是「反相的深色」，而是一套能长时间看的办公亮色：
   - 背景用极浅冷灰（#f4f6fb）而不是纯白，大面积纯白在强光下刺眼
   - 面板用实色白 + 淡边框，不用半透明（浅色下半透明会把背景花纹透出来，显脏）
   - 文字层级沿用同一套语义名，只换色值 ⇒ 所有组件自动跟着变 */
[data-theme="light"] {
  color-scheme: light;
  --bg: #f4f6fb;
  --bg-2: #eef2f9;
  --panel: #ffffff;
  --panel-solid: #ffffff;
  --panel-hi: #f8fafc;
  --line: rgba(15, 23, 42, 0.10);
  --line-strong: rgba(15, 23, 42, 0.17);
  --text: #0f1a2e;
  --text-2: #4a5b76;
  --text-2b: #5b6b85;
  /* 浅色这三档都是「实测倒推」出来的，不是拍脑袋选的：
     --text-3 #5f6f89 在白底 5.10:1、在表头底 #f8fafc 4.87:1（都要 ≥4.5）
     原 #7c8aa1 在表头底只有 4.17:1 —— 表头用的是这一档，中文小字下发虚。 */
  --text-3: #5f6f89;
  /* 浅色下 accent 必须加深：#38bdf8 在白底只有 2.1:1，字根本看不清。
     选 #0369a1 = 白底 5.93:1 / 页面底 #f4f6fb 5.49:1，两处都过 AA。 */
  --accent: #0369a1;
  --accent-2: #7c3aed;
  --up: #dc2626;
  --down: #16a34a;
  --warn: #b45309;
  --shadow: 0 10px 30px rgba(15, 23, 42, 0.10);
  --shadow-sm: 0 2px 8px rgba(15, 23, 42, 0.07);

  /* 叠层药水翻转成「黑里加黑」 */
  --fill-1: rgba(15, 23, 42, 0.018);
  --fill-2: rgba(15, 23, 42, 0.035);
  --fill-3: rgba(15, 23, 42, 0.05);
  --fill-4: rgba(15, 23, 42, 0.07);
  --fill-hover: rgba(15, 23, 42, 0.045);

  --input-bg: #ffffff;
  --scroll-thumb: rgba(15, 23, 42, 0.18);
  --scroll-thumb-hover: rgba(15, 23, 42, 0.3);
  --grid-line: rgba(15, 23, 42, 0.028);

  --on-accent: #ffffff;
  --danger-fg: #b91c1c;
  --danger-fg-soft: #b91c1c;
  --accent-fg: #0369a1;
  --accent-2-fg: #6d28d9;
  --ok-fg: #146c34;
  --warn-fg: #a16207;
  --neutral-fg: #52627a;
  --avatar-bg: linear-gradient(135deg, #cbd5e1, #94a3b8);
  --avatar-fg: #334155;
  --nav-dim: #4a5b76;
  --badge-dim: #4a5b76;
  --trend-up: #b91c1c;
  --trend-down: #15803d;
  --st-deal: #be123c;
  --st-sea: #475569;
  --funnel-fg: #ffffff;
  --nav-active-fg: #0369a1;

  --aurora-1: rgba(56, 189, 248, 0.07);
  --aurora-2: rgba(167, 139, 250, 0.06);
  --aurora-3: rgba(20, 184, 166, 0.05);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
    "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
  font-size: 14px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

/* aurora 背景 */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -2;
  background:
    radial-gradient(900px 620px at 12% -8%, var(--aurora-1), transparent 62%),
    radial-gradient(820px 580px at 88% 4%, var(--aurora-2), transparent 60%),
    radial-gradient(760px 620px at 52% 108%, var(--aurora-3), transparent 62%),
    linear-gradient(180deg, var(--bg) 0%, var(--bg-2) 55%, var(--bg) 100%);
}
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 46px 46px;
}

a { color: var(--accent); text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: var(--scroll-thumb); border-radius: 6px; }
::-webkit-scrollbar-track { background: transparent; }

/* ---------------- 通用控件 ---------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 15px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong);
  background: var(--fill-2);
  color: var(--text);
  cursor: pointer;
  transition: all 0.16s ease;
  white-space: nowrap;
  font-size: 13.5px;
}
.btn:hover { background: var(--fill-4); border-color: var(--line-strong); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn-primary {
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-2) 100%);
  border-color: transparent;
  color: var(--on-accent);
  font-weight: 600;
}
.btn-primary:hover { filter: brightness(1.08); background: linear-gradient(135deg, var(--accent) 0%, var(--accent-2) 100%); }
.btn-danger { border-color: rgba(244, 63, 94, 0.45); color: var(--danger-fg); }
.btn-danger:hover { background: rgba(244, 63, 94, 0.16); }
.btn-sm { padding: 5px 10px; font-size: 12.5px; }
.btn-ghost { border-color: transparent; background: transparent; }
.btn-ghost:hover { background: var(--fill-4); }

.input, .select, .textarea {
  width: 100%;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong);
  background: var(--input-bg);
  color: var(--text);
  outline: none;
  transition: border-color 0.16s ease, box-shadow 0.16s ease;
}
.input::placeholder, .textarea::placeholder { color: var(--text-3); }
.input:focus, .select:focus, .textarea:focus {
  border-color: rgba(56, 189, 248, 0.65);
  box-shadow: 0 0 0 3px rgba(56, 189, 248, 0.14);
}
.select { appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--text-2) 50%), linear-gradient(135deg, var(--text-2) 50%, transparent 50%); background-position: calc(100% - 16px) 50%, calc(100% - 11px) 50%; background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; padding-right: 30px; }
.textarea { min-height: 76px; resize: vertical; }
label.field { display: block; margin-bottom: 12px; }
label.field > span { display: block; margin-bottom: 5px; color: var(--text-2); font-size: 12.5px; }

.tag {
  display: inline-flex;
  align-items: center;
  padding: 1px 8px;
  border-radius: 20px;
  font-size: 12px;
  line-height: 18px;
  border: 1px solid transparent;
  white-space: nowrap;
}
.tag-soft { background: var(--fill-4); border-color: var(--line); color: var(--text-2); }
.tag-owner { background: rgba(56, 189, 248, 0.14); border-color: rgba(56, 189, 248, 0.32); color: var(--accent-fg); }
/* 归属来源要一眼分清，否则业务会把「历史数据」当成公海去点领取（会撞 403） */
.tag-owner-leyu { background: rgba(148, 163, 184, 0.13); border-color: rgba(148, 163, 184, 0.3); color: var(--neutral-fg); }
/* ⚠ 这里原来写死 color:#94a3b8 —— 浅色主题白底上只有 2.18:1，字直接糊掉。
   「公海/未分配」是业务每天要点几十次的关键标签，必须跟着主题走。 */
.tag-owner-sea { background: rgba(71, 85, 105, 0.22); border-color: rgba(100, 116, 139, 0.4); color: var(--neutral-fg); }
.tag-owner-orphan { background: rgba(244, 63, 94, 0.14); border-color: rgba(244, 63, 94, 0.38); color: var(--danger-fg); }
.tag-old { background: rgba(167, 139, 250, 0.14); border-color: rgba(167, 139, 250, 0.32); color: var(--accent-2-fg); }
.tag-new { background: rgba(34, 197, 94, 0.14); border-color: rgba(34, 197, 94, 0.32); color: var(--ok-fg); }
.tag-overseas { background: rgba(251, 191, 36, 0.14); border-color: rgba(251, 191, 36, 0.32); color: var(--warn-fg); }

/* ---------------- 登录页 ---------------- */

.login-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.login-card {
  width: 100%;
  max-width: 396px;
  padding: 38px 34px 30px;
  border-radius: 20px;
  background: var(--panel);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  backdrop-filter: blur(18px);
}
.login-logo {
  display: flex;
  align-items: center;
  gap: 11px;
  margin-bottom: 6px;
}
.login-logo .mark {
  width: 38px; height: 38px;
  border-radius: 11px;
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-2) 100%);
  display: flex; align-items: center; justify-content: center;
  font-weight: 800; color: var(--on-accent); font-size: 17px;
}
.login-logo .name { font-size: 19px; font-weight: 700; letter-spacing: 0.4px; }
.login-sub { color: var(--text-3); font-size: 12.5px; margin: 0 0 26px; }
.login-err {
  margin-top: 14px;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  background: rgba(244, 63, 94, 0.12);
  border: 1px solid rgba(244, 63, 94, 0.3);
  color: var(--danger-fg-soft);
  font-size: 12.5px;
}
.login-hint { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--line); color: var(--text-3); font-size: 12.5px; line-height: 1.75; }
.login-hint code { color: var(--text-2); background: var(--fill-3); padding: 1px 5px; border-radius: 4px; }

/* ---------------- 应用外壳 ---------------- */

.shell { display: flex; min-height: 100vh; }

.side {
  /* 216 → 256px：字号体系上调一档后，原宽度装不下长菜单名。
     实测「客资列表（原始表）」+「主体」badge 需要 183.5px 行内宽度
     （名称 148.5px + gap 10 + badge 25px），而 216px 只能给出 170px，
     238px 以下实测仍然换行（250px 也是两行），256px 才落到单行 35px。
     附注：去掉二级项那个装饰性的「·」点也能省出 21px，但会丢掉现有视觉层次，
     不如直接给宽度 —— 侧边栏 256px 在 1280 屏上占 20%，仍在常规区间。 */
  width: 256px;
  flex: 0 0 256px;
  padding: 20px 15px;
  border-right: 1px solid var(--line);
  background: rgba(10, 15, 27, 0.6);
  backdrop-filter: blur(14px);
  display: flex;
  flex-direction: column;
  gap: 6px;
  position: sticky;
  top: 0;
  height: 100vh;
}
.side .brand { display: flex; align-items: center; gap: 10px; padding: 4px 8px 20px; }
.side .brand .mark {
  width: 32px; height: 32px; border-radius: 9px;
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-2) 100%);
  display: flex; align-items: center; justify-content: center;
  font-weight: 800; color: var(--on-accent); font-size: 15px;
}
.side .brand .t { font-weight: 700; font-size: 16px; }
.side .brand .s { font-size: 11.5px; color: var(--text-3); letter-spacing: 0.5px; }

.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  color: var(--text-2);
  cursor: pointer;
  transition: all 0.15s ease;
  font-size: 13.5px;
  border: 1px solid transparent;
}
.nav-item:hover { background: var(--fill-hover); color: var(--text); }
.nav-item.active {
  background: linear-gradient(90deg, rgba(56, 189, 248, 0.17), rgba(167, 139, 250, 0.09));
  border-color: rgba(56, 189, 248, 0.26);
  /* ⚠️ 深色下是白字（叠在亮蓝块上够亮），但浅色下白字配浅蓝块 = 看不见。
     所以浅色块里必须把这一条也覆盖掉，见文件末尾 [data-theme="light"] 段。 */
  color: var(--nav-active-fg);
  font-weight: 600;
}
.nav-item .ic { width: 17px; text-align: center; opacity: 0.92; }
/* 「已有」是 11.5px 小字，--text-3 在白底只有 4.21:1；小字需要更实，单给一档。 */
.nav-item .badge { margin-left: auto; font-size: 11.5px; color: var(--badge-dim); }

.side-foot { margin-top: auto; padding-top: 14px; border-top: 1px solid var(--line); }

.side-user { display: flex; align-items: center; gap: 9px; padding: 7px 8px; border-radius: var(--radius-sm); }
.avatar {
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--avatar-bg);
  display: flex; align-items: center; justify-content: center;
  font-size: 12.5px; font-weight: 700; color: var(--avatar-fg); flex: 0 0 30px;
}
.side-user .n { font-size: 13.5px; font-weight: 600; }
.side-user .r { font-size: 11.5px; color: var(--text-3); }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 14px;
  padding: 13px 24px;
  border-bottom: 1px solid var(--line);
  background: rgba(8, 12, 22, 0.78);
  backdrop-filter: blur(14px);
}
.topbar h1 { margin: 0; font-size: 16px; font-weight: 700; letter-spacing: 0.2px; }
.topbar .spacer { flex: 1; }
.content { padding: 22px 24px 40px; }
.section { margin-bottom: 22px; }
.section-title {
  display: flex; align-items: center; gap: 9px;
  font-size: 13.5px; font-weight: 600; color: var(--text-2);
  margin: 0 0 12px;
}
.section-title::before {
  content: ""; width: 3px; height: 13px; border-radius: 2px;
  background: linear-gradient(180deg, var(--accent), var(--accent-2));
}

.card {
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--panel);
  backdrop-filter: blur(14px);
  padding: 17px 18px;
}
.card-head { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.card-head .ttl { font-size: 13.5px; font-weight: 600; }
.card-head .sub { font-size: 12.5px; color: var(--text-3); min-width: 0; line-height: 2; }
.card-head .spacer { flex: 1; }

/* KPI */
.kpi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(178px, 1fr)); gap: 13px; }
.kpi {
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--panel);
  padding: 15px 16px;
  position: relative;
  overflow: hidden;
}
.kpi::after {
  content: ""; position: absolute; left: 0; top: 0; width: 100%; height: 2px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  opacity: 0.75;
}
.kpi .lbl { color: var(--text-2); font-size: 12.5px; display: flex; align-items: center; gap: 5px; }
.kpi .val { font-size: 25px; font-weight: 700; letter-spacing: -0.4px; margin: 5px 0 2px; font-variant-numeric: tabular-nums; }
.kpi .val small { font-size: 13.5px; font-weight: 500; color: var(--text-2); margin-left: 3px; }
.kpi .foot { font-size: 12.5px; color: var(--text-3); }
.kpi .foot .up { color: var(--trend-up); }
.kpi .foot .down { color: var(--trend-down); }

/* 图表：纯 CSS */
.bar-row { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; font-size: 12.5px; }
.bar-row .nm { width: 96px; flex: 0 0 96px; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-track { flex: 1; height: 9px; border-radius: 5px; background: var(--fill-hover); overflow: hidden; }
.bar-fill { height: 100%; border-radius: 5px; background: linear-gradient(90deg, var(--accent), var(--accent-2)); transition: width 0.5s cubic-bezier(0.22, 1, 0.36, 1); }
.bar-row .vl { width: 46px; text-align: right; color: var(--text); font-variant-numeric: tabular-nums; flex: 0 0 46px; }

.funnel-step { display: flex; align-items: center; gap: 11px; margin-bottom: 9px; }
.funnel-step .nm { width: 74px; flex: 0 0 74px; font-size: 12.5px; color: var(--text-2); }
.funnel-step .bar-track { height: 22px; border-radius: 6px; }
.funnel-step .bar-fill { border-radius: 6px; opacity: 0.92; display: flex; align-items: center; justify-content: flex-end; padding-right: 8px; font-size: 12px; color: var(--funnel-fg); font-weight: 700; }
.funnel-step .rate { width: 52px; flex: 0 0 52px; text-align: right; font-size: 12.5px; color: var(--text-3); }

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
@media (max-width: 1080px) { .grid-2, .grid-3 { grid-template-columns: 1fr; } }

table.tb { width: 100%; border-collapse: collapse; font-size: 13.5px; }
table.tb th {
  text-align: left; padding: 9px 10px; color: var(--text-3);
  font-weight: 600; font-size: 12.5px; letter-spacing: 0.3px;
  border-bottom: 1px solid var(--line-strong); white-space: nowrap;
}
table.tb td { padding: 10px; border-bottom: 1px solid var(--line); vertical-align: middle; }
table.tb tbody tr { transition: background 0.13s ease; cursor: pointer; }
table.tb tbody tr:hover { background: var(--fill-2); }
table.tb td.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
table.tb td.act { text-align: right; white-space: nowrap; }
table.tb .nm-cell { font-weight: 600; }
table.tb .sub { color: var(--text-3); font-size: 12.5px; }

/* 一键拨号：号码要看起来「能点」，但不能抢走客户名的视觉权重。
   下划虚线 + 保持不变色，鼠标悬停才亮起来；触屏设备 hover 会粘住，无伤大雅。 */
a.tel { color: inherit; text-decoration: underline dotted; text-underline-offset: 2px; cursor: pointer; }
a.tel:hover, a.tel:active { color: var(--accent); }
.call-n { color: var(--accent); font-variant-numeric: tabular-nums; }
.table-scroll { overflow-x: auto; }

/* 支付明细（收款流水）：原系统这页是 15 列的宽表，本来就要横向滚。
   定个 min-width 让列宽按服务端下发的口径落地，而不是被 100% 挤成一团。
   （列口径来自 /api/payments/meta，改口径只改服务端一处。） */
table.tb.tb-pmt { min-width: 1720px; }
table.tb.tb-pmt td .cell-clip { max-width: 260px; }
table.tb.tb-pmt a { color: var(--accent, #38bdf8); text-decoration: none; }
table.tb.tb-pmt a:hover { text-decoration: underline; }

.pager { display: flex; align-items: center; gap: 10px; padding-top: 13px; font-size: 12.5px; color: var(--text-2); }
.pager .spacer { flex: 1; }

.empty { padding: 44px 20px; text-align: center; color: var(--text-3); font-size: 13.5px; }
.empty .big { font-size: 30px; margin-bottom: 8px; opacity: 0.5; }

.filters { display: flex; flex-wrap: wrap; gap: 9px; align-items: center; }
.filters .input, .filters .select { width: auto; min-width: 122px; }
.filters .grow { flex: 1; min-width: 190px; }
/* 搜索框给个固定感宽度，避免把「搜索/清空」按钮挤到下一行 */
.filters .tb-q { flex: 0 1 360px; min-width: 200px; }

/* 抽屉 */
.drawer-mask {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(3, 6, 12, 0.62);
  backdrop-filter: blur(2px);
  animation: fade 0.18s ease;
}
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 61;
  width: min(560px, 94vw);
  background: var(--panel-solid);
  border-left: 1px solid var(--line-strong);
  box-shadow: -22px 0 60px rgba(0, 0, 0, 0.5);
  display: flex; flex-direction: column;
  animation: slideIn 0.22s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes slideIn { from { transform: translateX(30px); opacity: 0.6; } to { transform: none; opacity: 1; } }
.drawer-head { display: flex; align-items: flex-start; gap: 12px; padding: 17px 20px; border-bottom: 1px solid var(--line); }
.drawer-head .t { font-size: 16.5px; font-weight: 700; }
.drawer-head .s { font-size: 12.5px; color: var(--text-3); margin-top: 2px; }
.drawer-body { flex: 1; overflow-y: auto; padding: 18px 20px; }
.drawer-foot { display: flex; gap: 9px; padding: 13px 20px; border-top: 1px solid var(--line); }

.kv { display: grid; grid-template-columns: 92px 1fr; gap: 9px 12px; font-size: 13.5px; }
.kv .k { color: var(--text-3); font-size: 12.5px; }
.kv .v { color: var(--text); word-break: break-all; }

.timeline { position: relative; padding-left: 17px; }
.timeline::before { content: ""; position: absolute; left: 4px; top: 5px; bottom: 5px; width: 1px; background: var(--line-strong); }
.tl-item { position: relative; padding-bottom: 15px; }
.tl-item::before {
  content: ""; position: absolute; left: -17px; top: 5px;
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--panel-solid); border: 2px solid var(--accent);
}
.tl-item .h { display: flex; align-items: center; gap: 8px; margin-bottom: 3px; }
.tl-item .who { font-size: 12.5px; font-weight: 600; }
.tl-item .when { font-size: 12.5px; color: var(--text-3); }
.tl-item .c { font-size: 13.5px; color: var(--text-2); white-space: pre-wrap; word-break: break-word; }

/* 模态 */
.modal-mask { position: fixed; inset: 0; z-index: 70; background: rgba(3, 6, 12, 0.66); backdrop-filter: blur(3px); display: flex; align-items: center; justify-content: center; padding: 22px; animation: fade 0.16s ease; }
.modal {
  width: 100%; max-width: 620px; max-height: 90vh; overflow-y: auto;
  background: var(--panel-solid); border: 1px solid var(--line-strong);
  border-radius: 16px; box-shadow: var(--shadow);
  animation: pop 0.2s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes pop { from { transform: scale(0.97) translateY(6px); opacity: 0.7; } to { transform: none; opacity: 1; } }
.modal-head { display: flex; align-items: center; gap: 10px; padding: 16px 20px; border-bottom: 1px solid var(--line); }
.modal-head .t { font-size: 15.5px; font-weight: 700; flex: 1; }
.modal-body { padding: 18px 20px; }
.modal-foot { display: flex; justify-content: flex-end; gap: 9px; padding: 13px 20px; border-top: 1px solid var(--line); }

.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
.form-grid .full { grid-column: 1 / -1; }
@media (max-width: 620px) { .form-grid { grid-template-columns: 1fr; } }

.toast-wrap { position: fixed; top: 18px; left: 50%; transform: translateX(-50%); z-index: 100; display: flex; flex-direction: column; gap: 8px; align-items: center; }
.toast {
  padding: 9px 17px; border-radius: 10px; font-size: 13.5px;
  background: rgba(17, 26, 46, 0.96); border: 1px solid var(--line-strong);
  box-shadow: var(--shadow); animation: pop 0.2s ease;
}
.toast.ok { border-color: rgba(34, 197, 94, 0.42); color: #a7f3c4; }
.toast.err { border-color: rgba(244, 63, 94, 0.45); color: var(--danger-fg-soft); }
/* 「参数被服务端修正了」这类提示：不是错误（操作仍成功），但必须看得见 */
.toast.warn { border-color: rgba(251, 191, 36, 0.45); color: #f5dfa8; }

.chk { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; }
.muted { color: var(--text-3); }
.mono { font-variant-numeric: tabular-nums; }
.right { text-align: right; }
.nowrap { white-space: nowrap; }
.flex { display: flex; align-items: center; gap: 9px; }
.badge-pill { font-size: 11.5px; padding: 1px 7px; border-radius: 20px; background: var(--fill-4); color: var(--text-2); }
.spin { display: inline-block; width: 14px; height: 14px; border: 2px solid var(--line-strong); border-top-color: var(--accent); border-radius: 50%; animation: rot 0.7s linear infinite; }
@keyframes rot { to { transform: rotate(360deg); } }

/* ============================================================
   通用表格页（原系统在用模块复刻）· 由 public/pages.js 使用
   ============================================================ */

/* 侧边导航项从 4 个增到 22 个，需要可滚动且底部用户区常驻 */
.side { overflow-y: auto; overflow-x: hidden; }
.side::-webkit-scrollbar { width: 6px; }
.side::-webkit-scrollbar-thumb { background: var(--scroll-thumb); border-radius: 3px; }
.side::-webkit-scrollbar-thumb:hover { background: var(--scroll-thumb-hover); }
.side::-webkit-scrollbar-track { background: transparent; }

/* 分组标题（可点击折叠） */
.nav-tools {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 9px 6px;
  margin-bottom: 2px;
}
.nav-tools-t {
  font-size: 11.5px;
  color: var(--text-3);
  letter-spacing: 0.3px;
  text-transform: uppercase;
}
.nav-tool {
  margin-left: auto;
  font: inherit;
  font-size: 11.5px;
  color: var(--text-3);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 1px 8px;
  cursor: pointer;
  transition: color 0.13s ease, border-color 0.13s ease;
}
.nav-tool:hover { color: var(--text); border-color: var(--text-3); }

.nav-group {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-2b);
  /* 0.6px → 0.2px：字间距是给大写英文标签（"MENU"）透气用的，
     中文汉字本身等宽、结构紧实，加间距只会显得更散更小。 */
  letter-spacing: 0.2px;
  margin: 2px 0;
  padding: 5px 9px 5px 10px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  user-select: none;
  transition: background 0.13s ease, color 0.13s ease;
}
.nav-group:hover { background: var(--fill-2); color: var(--text-2); }
.nav-group:focus-visible { outline: 1px solid var(--accent); outline-offset: -1px; }
.nav-group:first-child, .nav-tools + .nav-group { margin-top: 2px; }
/* 注：分组标题右侧原先还有一个「该组菜单条数」(.nav-group-n)，已按老板要求去掉。
   .caret 自带 margin-left:auto，去掉数字后箭头仍正常顶到右侧。 */
.nav-group .caret {
  margin-left: auto;
  font-size: 11px;
  color: var(--nav-dim);
  transition: transform 0.16s ease;
}
.nav-group.collapsed .caret { transform: rotate(-90deg); }
/* 折叠态原本直接降到 --text-3（#6d7f9c），但侧边栏**默认就是全部折叠**的，
   等于用户日常看到的分组标题一直是那个灰档 —— 这正是「菜单字太小太灰」的主因。
   改成比 --text-3 亮一档的 --nav-dim，
   与展开态的 --text-2b 仍有区分，状态提示交给 caret 方向和字色深浅两重表达。
   ⚠ 这里曾经写死 #7a8dab：深色下够亮，浅色白底上只有 3.37:1，分组标题直接糊掉。
      折叠是默认态 ⇒ 浅色用户 100% 命中这个坑。必须走变量。 */
.nav-group.collapsed { color: var(--nav-dim); opacity: 1; }

/* 折叠时整块隐藏 —— 侧边栏太长的问题就靠这行解决 */
.nav-items.collapsed { display: none; }

/* 二级导航项
 * 从 4 个涨到 40+ 个，行高必须收紧，否则整列太长（配合分组折叠） */
.nav-item.nav-sub { padding: 6px 12px 6px 19px; font-size: 13.5px; }
.nav-item.nav-sub .ic { width: 11px; opacity: 0.45; font-size: 15px; line-height: 1; }

/* 可排序表头 */
table.tb th.th-sort { cursor: pointer; user-select: none; transition: color 0.13s ease; }
table.tb th.th-sort:hover { color: var(--text); }
table.tb th.th-sort.on { color: var(--accent); }
/* 数值列表头跟随单元格一起右对齐 */
table.tb th.num { text-align: right; }

/* 单元格：长文本截断，鼠标悬停看全文 */
.cell-clip {
  display: inline-block;
  max-width: 240px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: bottom;
}
.num-cell { font-variant-numeric: tabular-nums; }

/* 筛选行的范围输入（日期/数值） */
.tb-range {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 10px 2px 11px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--fill-hover);
  white-space: nowrap;
}
.tb-range-label { font-size: 12.5px; color: var(--text-2); }
.tb-range .input {
  width: 128px;
  height: 28px;
  padding: 0 7px;
  font-size: 12.5px;
  background: var(--bg);
}
.tb-range input[type="number"] { width: 86px; }
.tb-range-sep { color: var(--text-3, var(--text-2)); font-size: 12px; }

/* 卡片头部的统计胶囊 */
.tb-pill {
  font-size: 12.5px;
  padding: 3px 11px;
  border-radius: 20px;
  background: var(--fill-hover);
  border: 1px solid var(--line);
  color: var(--text-2);
  white-space: nowrap;
}
.tb-pill b { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }
.tb-pill-ro {
  background: rgba(251, 191, 36, 0.12);
  border-color: rgba(251, 191, 36, 0.32);
  color: var(--warn-fg);
  font-size: 12px;
}

/* 表格里的枚举码翻成中文后的小胶囊（如日程状态 0/1 → 未完成/已完成）
 * 视觉上刻意比 .tb-pill 小一号，免得在密集表格里喧宾夺主 */
.tb-enum {
  display: inline-block;
  font-size: 12px;
  line-height: 1.55;
  padding: 0 8px;
  border-radius: 20px;
  white-space: nowrap;
  background: var(--fill-3);
  border: 1px solid var(--line);
  color: var(--text-2);
}
.tb-enum.do { background: rgba(52, 211, 153, 0.13); border-color: rgba(52, 211, 153, 0.34); color: #6ee7b7; }
.tb-enum.undo { background: rgba(148, 163, 184, 0.13); border-color: rgba(148, 163, 184, 0.3); color: #cbd5e1; }
/* 下面三档对齐原系统的 priorityType：0绿 / 1蓝 / 2橙 / 3红 */
.tb-enum.info { background: rgba(56, 189, 248, 0.13); border-color: rgba(56, 189, 248, 0.34); color: #7dd3fc; }
.tb-enum.warn { background: rgba(251, 191, 36, 0.13); border-color: rgba(251, 191, 36, 0.34); color: var(--warn-fg); }
.tb-enum.danger { background: rgba(248, 113, 113, 0.13); border-color: rgba(248, 113, 113, 0.34); color: #fca5a5; }

/* ---- 操作记录明细（order_ops 的 chlidren 列）----
   把 [{label:'收件人', before:'', after:'张宁'}, …] 渲染成「字段：改前 → 改后」多行。
   用主题变量，深浅两套自动适配（禁写死颜色）。 */
.ops-detail {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 12.5px;
  max-width: 460px;
}
.ops-line {
  line-height: 1.65;
  color: var(--text-2);
  display: flex;
  align-items: baseline;
  gap: 4px;
  min-width: 0;
}
.ops-line b { color: var(--text-1); font-weight: 600; flex: 0 0 auto; }
.ops-line .ops-from {
  color: var(--text-3);
  text-decoration: line-through;
  text-decoration-color: var(--line-strong);
}
.ops-more { color: var(--text-3); font-size: 11.5px; }
/* 「操作类型」派生列：做成小胶囊，跟枚举标签视觉一致 */
.ops-kind {
  display: inline-block;
  font-size: 12px;
  line-height: 1.55;
  padding: 0 8px;
  border-radius: 20px;
  white-space: nowrap;
  background: var(--fill-3);
  border: 1px solid var(--line);
  color: var(--text-2);
}
/* 表说明（来自表数据的 note 字段），跟在统计胶囊后面 */
.tb-note {
  display: inline-block;
  max-width: 52ch;
  font-size: 12.5px;
  color: var(--text-3);
  opacity: 0.9;
  line-height: 1.55;
  vertical-align: middle;
}

/* 表格空态落在 td 里时不要撑太高 */
table.tb td.empty { padding: 40px 16px; }

/* 抽屉里的键值对，字段多时列宽放宽一点 */
.drawer-body .kv { grid-template-columns: 104px 1fr; }

/* ---------------- 订单台账 / 待核销台账 ---------------- */

/* 顶部统计卡片条 */
.ord-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(166px, 1fr));
  gap: 12px;
  margin-bottom: 14px;
}
.ord-stat {
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--panel);
  padding: 13px 15px;
}
.ord-stat .l { color: var(--text-2); font-size: 12.5px; }
.ord-stat .v {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.4px;
  margin: 4px 0 2px;
  font-variant-numeric: tabular-nums;
}
.ord-stat .s { color: var(--text-3); font-size: 12.5px; }

/* 逾期未核销的行：左侧一条红杠 + 淡红底，扫一眼就能挑出来 */
.ord-over-row td { background: rgba(244, 63, 94, 0.07); }
.ord-over-row td:first-child { box-shadow: inset 3px 0 0 #f43f5e; }

/* 表单/弹窗里的流程说明 */
.ord-tip {
  font-size: 12.5px;
  line-height: 1.65;
  color: var(--text-2);
  background: rgba(56, 189, 248, 0.08);
  border: 1px solid rgba(56, 189, 248, 0.24);
  border-radius: var(--radius-sm);
  padding: 9px 12px;
  margin-bottom: 14px;
}

/* ============================================================
   日程管理（月历 + 右栏当日清单）· 由 public/app.js 使用
   照搬原系统 客户管理 → 日程管理 的双栏形态
   ============================================================ */

.sched-wrap { display: flex; gap: 14px; align-items: flex-start; }
.sched-cal { flex: 1 1 auto; min-width: 0; }
/* 右栏 348px：再宽就是抢月历的宽度了。实测 1264px 视口下，
   396px 时每格只剩 ~75px、标题只够显示 3 个字；348px 后能到 ~82px + 两行。 */
.sched-side { width: 348px; flex: 0 0 348px; }
@media (max-width: 1200px) {
  .sched-wrap { flex-direction: column; }
  .sched-side { width: 100%; flex: 1 1 auto; }
}

/* 月份导航 */
.cal-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.cal-month { font-size: 14.5px; font-weight: 600; letter-spacing: 0.3px; min-width: 116px; text-align: center; }
.cal-nav {
  font: inherit; font-size: 13.5px; color: var(--text-2);
  background: var(--fill-2); border: 1px solid var(--line);
  border-radius: 7px; width: 28px; height: 28px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: color 0.13s ease, border-color 0.13s ease;
}
.cal-nav:hover { color: var(--text); border-color: var(--text-3); }

/* 月历上方的「别以为你看到了全部」提示条（结果截断 / 归档隐藏）。
   深色主题：中性条走面板色 + 灰竖条；warn 条用 --warn 的淡底 + 琥珀竖条。
   文案里的数字是重点，所以 <b> 提亮到 --text，别让它淹没在 --text-2 里。 */
.sched-notice {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-bottom: 10px; padding: 8px 11px;
  border: 1px solid var(--line); border-left: 3px solid var(--text-3);
  border-radius: var(--radius-sm);
  background: var(--fill-2);
  color: var(--text-2); font-size: 12.5px; line-height: 1.7;
}
.sched-notice b { color: var(--text); font-weight: 600; }
.sched-notice.warn {
  border-color: rgba(251, 191, 36, 0.3);
  border-left-color: var(--warn);
  background: rgba(251, 191, 36, 0.085);
  color: #f3e2bd;
}
.sched-notice.warn b { color: var(--warn); }
.sched-notice .btn { margin-left: auto; flex: 0 0 auto; }

/* 月历网格：周首日 = 周一（与原系统一致） */
.cal-week { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; margin-bottom: 6px; }
.cal-week > div { text-align: center; font-size: 12px; color: var(--text-3); padding: 2px 0; }
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }

.cal-cell {
  min-height: 104px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 5px 6px; background: var(--fill-1);
  cursor: pointer; overflow: hidden;
  transition: border-color 0.13s ease, background 0.13s ease;
}
.cal-cell:hover { border-color: var(--line-strong); background: var(--fill-hover); }
.cal-cell.out { opacity: 0.32; }                 /* 上下月补位日 */
.cal-cell.today { border-color: rgba(56, 189, 248, 0.6); }
.cal-cell.sel { border-color: rgba(167, 139, 250, 0.75); background: rgba(167, 139, 250, 0.1); }

.cal-d { font-size: 12.5px; color: var(--text-2); margin-bottom: 4px; line-height: 1.2; }
.cal-cell.today .cal-d { color: var(--accent); font-weight: 700; }

/* 日程条：左边框颜色 = 优先级配色（原系统的 priorityType）
   时间与标题用 flex 分行占位，标题拿到剩余全部宽度 —— 窄屏下时间会先让位（见下面的媒体查询） */
.cal-ev {
  display: flex; align-items: baseline; gap: 4px;
  font-size: 12px; line-height: 1.45; padding: 2px 5px; margin-bottom: 3px;
  border-radius: 5px; border-left: 3px solid currentColor;
  background: var(--fill-4);
  color: var(--text-2);
}
.cal-ev .t { flex: 0 0 auto; color: var(--text-3); font-variant-numeric: tabular-nums; }
/* 标题最多两行。单行在 1264px 视口下只够 4 个字，等于只有「样品是…」——
   两行能读到 8~10 个字，一眼能判断要不要点进去。 */
.cal-ev .n {
  flex: 1 1 auto; min-width: 0; overflow: hidden;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  word-break: break-word;
}
/* 窄屏格子只有 ~82px，时间+标题谁都放不下 —— 直接丢掉时间，把整条让给标题 */
@media (max-width: 1420px) { .cal-ev .t { display: none; } }
.cal-ev.done { opacity: 0.5; }
.cal-ev.done .n { text-decoration: line-through; }
.cal-more { font-size: 11.5px; color: var(--text-3); padding-left: 2px; }

/* 右栏当天日程卡 */
.sched-card {
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 10px 11px; margin-bottom: 9px; background: var(--fill-1);
}
.sched-card.due { border-color: rgba(251, 191, 36, 0.45); background: rgba(251, 191, 36, 0.07); }
.sched-card.notified { opacity: 0.62; }
.sched-time { font-size: 12.5px; color: var(--text-3); display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.sched-title { font-size: 13.5px; line-height: 1.55; margin: 5px 0 7px; word-break: break-word; }
.sched-card.notified .sched-title { text-decoration: line-through; }
.sched-meta { font-size: 12.5px; color: var(--text-3); line-height: 1.75; }
.sched-ops { display: flex; gap: 6px; margin-top: 9px; justify-content: flex-end; flex-wrap: wrap; }

/* 侧边导航的待办角标：红底白字，一眼能看见 */
.nav-item .badge-due {
  margin-left: auto; font-size: 11.5px; font-weight: 700;
  color: #fff; background: #f43f5e; border-radius: 20px;
  padding: 0 6px; min-width: 18px; text-align: center; line-height: 16px;
}
.nav-item .badge-due.dot { min-width: 8px; height: 8px; padding: 0; line-height: 0; }

/* 看板「今日待办」卡 */
.todo-row {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 7px 0; border-bottom: 1px solid var(--line); font-size: 12.5px;
}
.todo-row:last-child { border-bottom: 0; }
.todo-row .t { flex: 0 0 90px; color: var(--text-3); font-size: 12.5px; }
.todo-row .c { flex: 1; min-width: 0; word-break: break-word; }
.todo-row .w { flex: 0 0 auto; color: var(--text-3); font-size: 12.5px; }

/* ==========================================================================
   外贸客资模块（trade.js）
   列表 / 详情抽屉 / 看板 三页共用
   ========================================================================== */

/* ---- 阶段漏斗 / 分布条形行 ---- */
.ft-bar-row {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 0; font-size: 12.5px;
  border-bottom: 1px solid var(--fill-2);
}
.ft-bar-row:last-child { border-bottom: 0; }
.ft-bar-label {
  flex: 0 0 150px; min-width: 0; color: var(--text-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ft-bar-label b { font-weight: 700; margin-right: 2px; font-variant-numeric: tabular-nums; }
.ft-bar-track {
  flex: 1 1 auto; min-width: 40px; height: 9px; border-radius: 6px;
  background: var(--fill-hover); overflow: hidden;
}
.ft-bar-track:empty { background: transparent; }
.ft-bar-fill {
  display: block; height: 100%; border-radius: 6px;
  transition: width 0.35s cubic-bezier(0.22, 1, 0.36, 1);
  box-shadow: 0 0 10px rgba(56, 189, 248, 0.14);
}
.ft-bar-num {
  flex: 0 0 auto; min-width: 66px; text-align: right;
  color: var(--text); font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.ft-bar-num .muted { font-size: 11.5px; }

/* 列表页顶部的阶段概览条（一排比看板里更紧凑） */
.ft-stage-bars {
  display: grid; gap: 2px;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}

/* ---- 看板两列栅格 ---- */
.ft-grid-2 {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}

/* ---- 详情抽屉：分节标题 ---- */
.ft-sec {
  margin: 18px 0 9px; padding-bottom: 6px;
  border-bottom: 1px solid var(--line-strong);
  font-size: 12.5px; font-weight: 700; letter-spacing: 0.04em;
  color: var(--accent);
}
.ft-sec:first-child { margin-top: 0; }

/* 上游运维手写的富文本摘要 */
.ft-richtip {
  margin: 0 0 12px; padding: 8px 11px;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(251, 191, 36, 0.26);
  background: rgba(251, 191, 36, 0.075);
  color: var(--warn-fg); font-size: 12.5px; line-height: 1.65;
  word-break: break-word;
}

/* ---- AI 分析区块 ---- */
.ft-ai {
  margin: 0 0 10px; padding: 10px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(167, 139, 250, 0.22);
  background: rgba(167, 139, 250, 0.07);
  font-size: 12.5px; line-height: 1.72; color: var(--text);
  word-break: break-word;
}
.ft-ai-t {
  margin-bottom: 5px; font-size: 11.5px; font-weight: 700;
  letter-spacing: 0.04em; color: var(--accent-2);
}
/* 兼容旧写法：div.ft-ai-t 单独出现时也要有间距 */
.ft-ai > .ft-ai-t:only-child { margin-bottom: 0; }

/* ---- 对话摘录 ---- */
.ft-quotes { display: grid; gap: 7px; }
.ft-quote {
  display: flex; gap: 9px; align-items: flex-start;
  padding: 7px 10px; border-radius: 8px;
  background: var(--fill-2);
  border-left: 2px solid rgba(56, 189, 248, 0.42);
  font-size: 12.5px; line-height: 1.66;
}
.ft-quote .w {
  flex: 0 0 auto; max-width: 108px; color: var(--text-3);
  font-size: 11.5px; font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ft-quote .t { flex: 1 1 auto; min-width: 0; word-break: break-word; }

/* ---- 跟进时间线 ---- */
.ft-timeline { display: grid; gap: 0; }
.ft-act {
  display: flex; gap: 11px; align-items: flex-start;
  padding: 0 0 14px; position: relative;
}
.ft-act:last-child { padding-bottom: 0; }
/* 竖线：除最后一条外都画 */
.ft-act:not(:last-child)::before {
  content: ""; position: absolute; left: 4px; top: 15px; bottom: 0;
  width: 1px; background: var(--line-strong);
}
.ft-act-dot {
  flex: 0 0 auto; width: 9px; height: 9px; margin-top: 5px;
  border-radius: 50%; background: var(--accent);
  box-shadow: 0 0 0 3px rgba(56, 189, 248, 0.14);
  position: relative; z-index: 1;
}
.ft-act-body { flex: 1 1 auto; min-width: 0; }
.ft-act-head {
  display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap;
  font-size: 12.5px; color: var(--text-2);
}
.ft-act-head b { color: var(--text); font-weight: 600; }
.ft-act-text {
  margin-top: 3px; font-size: 12.5px; line-height: 1.7;
  color: var(--text); word-break: break-word; white-space: pre-wrap;
}

/* ---- 外贸列表：宽表格在窄屏下的横向滚动容器 ---- */
.table-scroll table td.ft-td-acts,
.table-scroll table th.ft-th-acts { white-space: nowrap; text-align: right; }

/* ==========================================================================
   浅色主题下的补偿规则
   —— 上面已把 90% 的色值变量化，这里只补「纯换变量解决不了」的几处：
      半透明面板、blur 毛玻璃、阴影强度、以及深色下才成立的高光边。
   ========================================================================== */

[data-theme="light"] body::after {
  /* 浅色下那层网格线要更淡，否则整页看起来像有脏点 */
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
}

/* 毛玻璃在浅色底上会让背景花纹透上来，显脏 ⇒ 改成实色面板 + 轻阴影 */
[data-theme="light"] .login-card,
[data-theme="light"] .card,
[data-theme="light"] .topbar,
[data-theme="light"] .drawer,
[data-theme="light"] .modal,
[data-theme="light"] .side {
  backdrop-filter: none;
}

[data-theme="light"] .side {
  background: #ffffff;
  border-right: 1px solid var(--line);
}

[data-theme="light"] .topbar {
  background: rgba(255, 255, 255, 0.88);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}

/* 遮罩：深色下用纯黑半透明，浅色下要更淡一点才不压抑 */
[data-theme="light"] .drawer-mask,
[data-theme="light"] .modal-mask {
  background: rgba(15, 23, 42, 0.32);
}

/* 主按钮渐变上的白字要有足够对比（深色下是深字，浅色下是白字） */
[data-theme="light"] .btn-primary { text-shadow: none; }

/* 表格：浅色下靠边框分层，不靠底色差（底色差在浅色里几乎看不见） */
[data-theme="light"] table.tb thead th {
  background: var(--panel-hi);
  border-bottom: 1px solid var(--line-strong);
}
[data-theme="light"] table.tb tbody tr:hover { background: var(--fill-2); }

/* 进度条轨道在浅色下要够可见 */
[data-theme="light"] .bar-track,
[data-theme="light"] .ft-bar-track { box-shadow: inset 0 0 0 1px var(--line); }

/* 侧边栏当前项：深色靠「亮块 + 白字」，浅色必须换成「浅蓝块 + 蓝字」——
   否则 #fff 的字落在浅蓝块上等于看不见（这是硬编码 #fff 埋的雷）。 */
[data-theme="light"] .nav-item.active {
  background: linear-gradient(90deg, rgba(3, 105, 161, 0.13), rgba(124, 58, 237, 0.07));
  border-color: rgba(3, 105, 161, 0.26);
  color: var(--nav-active-fg);
}

/* 标签的浅蓝底在浅色下要更实一点才看得出是个标签 */
[data-theme="light"] .tag-owner {
  background: rgba(3, 105, 161, 0.11);
  border-color: rgba(3, 105, 161, 0.3);
}
[data-theme="light"] .tag-soft {
  background: var(--fill-3);
  border-color: var(--line);
}

/* 状态点/角标这类纯色块在浅色下保持原色即可，但白字要压深 */
[data-theme="light"] .nav-item .badge-due { background: #dc2626; }

/* SVG 图表里的轴线/网格是用 currentColor 或深色描边的，浅色下统一提亮一档 */
[data-theme="light"] svg text { fill: var(--text-2); }

/* ---------------------------------------------------------------------------
   状态/等级标签在浅色下的前景色。
   服务端 STATUSES 里每个状态都带一个 color（#38bdf8 / #a78bfa / #fbbf24 …），
   前端 statusTag() 直接把它同时用在「底色的 22 号透明度」和「文字色」上。
   那批色值是为**深色底**挑的高明度色 —— 换到白底当文字只有 2.0~3.1:1，根本看不清。
   底色（22 号透明度）保留原色没问题（浅色下反而更淡雅），只把**文字**压深即可。
   用属性选择器匹配 inline style 里的色值，避免去改服务端那份唯一口径。

   ⚠ 必须带 !important：这些标签的 color 是 JS 写在 style 属性上的行内样式，
     行内样式的优先级高于任何选择器（除非对方也是 !important）。
     实测：选择器命中了（el.matches === true）但颜色纹丝不动，就是这个原因。
--------------------------------------------------------------------------- */
/* 每个色值都指向一个**双主题变量**，所以两套主题共用同一组规则。
   "#f43f5e" / "#475569" 这两条即使深色下也必须覆盖（见上方 --st-deal / --st-sea 注释）。 */
.tag[style*="#38bdf8"] { color: var(--st-new) !important; }
.tag[style*="#a78bfa"] { color: var(--st-following) !important; }
.tag[style*="#22d3ee"] { color: var(--st-wechat) !important; }
.tag[style*="#fbbf24"] { color: var(--st-intent) !important; }
.tag[style*="#fb923c"] { color: var(--st-quoted) !important; }
.tag[style*="#f43f5e"] { color: var(--st-deal) !important; }
.tag[style*="#64748b"] { color: var(--st-invalid) !important; }
.tag[style*="#475569"] { color: var(--st-sea) !important; }
/* 支付方式的「微信」绿 —— 深色下 #22c55e 尚可，统一走 --trend-down 保持一支口径 */
.tag[style*="#22c55e"] { color: var(--trend-down) !important; }

/* ---------------- 主题切换按钮 ---------------- */

.theme-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 11px; border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong);
  background: var(--fill-2); color: var(--text-2);
  cursor: pointer; font-size: 12.5px; line-height: 1;
  transition: background .16s ease, color .16s ease, border-color .16s ease;
  white-space: nowrap;
}
.theme-btn:hover { background: var(--fill-4); color: var(--text); }
.theme-btn .ic { font-size: 14px; line-height: 1; }

/* 登录页右上角的悬浮切换（登录页没有 topbar 可挂） */
.theme-float {
  position: fixed; top: 18px; right: 18px; z-index: 50;
}

/* 主题切换时给整页一个短过渡，避免「啪」地一下全白 */
html.theme-anim, html.theme-anim * {
  transition: background-color .22s ease, border-color .22s ease, color .22s ease !important;
}

/* 中性灰「弱信息」色 —— 很多地方（停滞天数、非企业邮箱、已停用、待触发…）
   在 JS 模板里直接写死了 #94a3b8。它在深色底尚可，但在浅色底只有 2.6:1，
   完全看不清。这里给一个双主题都合规的类名，JS 侧改成用它。
   深色 #94a3b8 / 浅色 #64748b（白底 4.76:1，过 AA）。 */
.neutral { color: var(--neutral-mid); }
:root, [data-theme="dark"] { --neutral-mid: #94a3b8; }
[data-theme="light"] { --neutral-mid: #5b6b85; }

/* 状态/等级标签在浅色下的前景档位（色相不变，只压深到白底可读）。
   取值依据：白底 ≥4.5:1，且尽量保留原色的辨识度。 */
[data-theme="light"] {
  --st-new: #0369a1;       /* 新客资   · 天蓝 → 深蓝 */
  --st-following: #6d28d9; /* 跟进中   · 紫 */
  --st-wechat: #0e7490;    /* 已加微信 · 青 */
  --st-intent: #a16207;    /* 意向客户 · 琥珀 */
  --st-quoted: #c2410c;    /* 已报价   · 橙 */
  --st-deal: #be123c;      /* 已成交   · 玫红 */
  --st-invalid: #52627a;   /* 无效客资 · 灰 */
  --st-sea: #475569;       /* 公海     · 深灰 */
}

/* ==========================================================================
   手机端适配（2026-10-08 新增）

   背景：这套界面是给 1280+ 电脑屏做的（侧栏 256px、右栏 348px、表格 15 列…）。
   业务员实际是**拿手机用**的（老板钦定的核心场景），手机上会挤成一团。

   三条主线：
     1. 侧边栏 → 手机上收成抽屉，默认隐藏，汉堡按钮唤出；桌面端不受影响
     2. 表格   → 手机上转成「卡片堆叠」（每行变一张卡，表头当字段名）
     3. 筛选   → 手机上默认只留搜索框，其余收进「筛选」折叠；否则首屏被筛选项吃光

   ⚠️ 断点选 860px 而不是 620px：
      762~860 之间是平板竖屏，侧栏 256px + 内容 500px 已经很难看；
      且老板手机横屏约 844px，必须也进手机模式。
   ⚠️ 所有规则一律写在媒体查询里，桌面端一个像素都不动。
   ========================================================================== */

/* ---- 汉堡按钮：桌面端彻底不显示 ---- */
.nav-burger { display: none; }
.side-mask { display: none; }
/* 「筛选」折叠开关：桌面端不显示，筛选全展开 */
.filters-toggle { display: none; }

@media (max-width: 860px) {

  /* ---------- 1. 应用外壳：侧栏变抽屉 ---------- */

  .shell { display: block; }

  .side {
    position: fixed;
    top: 0; left: 0; bottom: 0;
    z-index: 80;
    width: min(84vw, 300px);
    height: 100%;
    flex: none;
    padding: 16px 12px;
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--panel-solid);
    border-right: 1px solid var(--line-strong);
    box-shadow: 14px 0 40px rgba(0, 0, 0, 0.42);
    transform: translateX(-102%);
    transition: transform 0.24s cubic-bezier(0.22, 1, 0.36, 1);
  }
  /* ⚠️ 深色下 --panel-solid 已经很实，但侧栏原来叠了 backdrop-filter。
     抽屉要盖住内容，必须换成**不透明**底，否则下面的表格会透出来（很脏）。 */
  [data-theme="dark"] .side { background: #111a2e; }
  [data-theme="light"] .side { background: #ffffff; }

  .side.open { transform: none; }

  /* 抽屉打开时的遮罩：点它关抽屉 */
  .side-mask {
    display: block;
    position: fixed; inset: 0; z-index: 79;
    background: rgba(3, 6, 12, 0.5);
    backdrop-filter: blur(1.5px);
    opacity: 0; pointer-events: none;
    transition: opacity 0.2s ease;
  }
  .side-mask.open { opacity: 1; pointer-events: auto; }

  /* 汉堡按钮：放在 topbar 最左 */
  .nav-burger {
    display: inline-flex; align-items: center; justify-content: center;
    flex: 0 0 auto;
    width: 36px; height: 36px;
    padding: 0; margin-right: 2px;
    font: inherit; font-size: 17px; line-height: 1;
    color: var(--text-2);
    background: var(--fill-3);
    border: 1px solid var(--line);
    border-radius: 9px;
    cursor: pointer;
  }
  .nav-burger:active { background: var(--fill-4); }

  /* ---------- 2. 顶栏：字号收一档，标题允许省略 ---------- */

  .topbar {
    padding: 9px 12px;
    gap: 8px;
    /* 手机上顶栏从「浮在内容上」改成实底，避免滚动时字叠字 */
    background: var(--panel-solid);
  }
  [data-theme="dark"] .topbar { background: #0b1222; }
  .topbar h1 {
    font-size: 14.5px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    min-width: 0;
  }
  /* 顶栏里的按钮（主题切换等）在窄屏上只留图标，不挤标题 */
  .topbar .btn { padding: 5px 9px; font-size: 12px; }

  .content { padding: 13px 12px 32px; }

  /* ---------- 3. 工具栏 / 筛选 / 分页：全部可换行、可撑满 ---------- */

  /* 手机端筛选折叠：
     客资页有 7 个下拉 + 1 个搜索框，全展开在 390px 屏上要吃掉整个首屏
     （实测 8 行 ≈ 570px）。默认只留搜索框 + 「筛选」开关，其余控件收起，
     点「筛选」才展开。折叠状态由 .filters 上的 .f-collapsed 类控制。

     ⚠️ 做法是「折叠时藏掉除搜索框外的所有控件」，而不是靠 JS 搬 DOM ——
        搬 DOM 会让各页已有的 id 绑定（f-q / f-status…）在展开时全部重绑，
        容易漏。这里只切一个类，DOM 一个字不动，展开即恢复原样。 */
  .filters-toggle { display: inline-flex; }

  .filters.f-collapsed > *:not(.filters-toggle):not(.tb-q):not(.f-q):not(input.grow) {
    display: none;
  }
  /* 折叠时搜索框占满整行，下面跟「筛选 / 查询」两个按钮 */
  .filters.f-collapsed > .tb-q,
  .filters.f-collapsed > input.grow { flex: 1 1 100%; }

  /* ⚠️ 一张卡片里可能有多组 .filters（如收款流水 = 快速搜索组 + 高级筛选组），
     整组一起折叠。若某组折完什么都不剩（没有搜索框 / 没有开关），
     它就是个空壳，还顶着 margin-top ⇒ 会留一道莫名其妙的空白。
     用 :not(:has()) 兜住：这一组没有可见子元素时直接不占位。 */
  .filters.f-collapsed:not(:has(.filters-toggle)):not(:has(.tb-q)):not(:has(input.grow)) {
    display: none;
  }

  .filters { gap: 7px; }
  .filters .input,
  .filters .select { width: 100%; min-width: 0; }
  .filters .grow,
  .filters .tb-q { flex: 1 1 100%; min-width: 0; }
  .filters .btn { flex: 1 1 auto; }
  /* ⚠️ 「筛选」开关是个光杆按钮，必须**别**跟着上面那条被撑满 ——
     否则它在整行里居中放大，看着像页面的主标题而不是个小开关（实测过）。
     靠左、按内容宽度即可。 */
  .filters .filters-toggle {
    flex: 0 0 auto;
    width: auto;
    margin-left: 0;
    margin-right: auto;
    padding: 0 13px;
    color: var(--text-2);
  }
  /* 行内写死的 min-width（130~180px）在手机上会把行撑破：一律解除 */
  .filters [style*="min-width"] { min-width: 0 !important; }
  .filters [style*="width:auto"] { width: 100% !important; }

  .pager { flex-wrap: wrap; gap: 7px; padding: 11px 0 0; }
  .pager .spacer { display: none; }

  .card { padding: 13px 12px; border-radius: 11px; }
  .card-head { flex-wrap: wrap; gap: 7px; }
  .card-head .spacer { flex: 1 1 100%; height: 0; }

  /* KPI 卡：手机上两列，最小宽度降下来，不然一列只有一个数字 */
  .kpi-grid { grid-template-columns: repeat(2, 1fr); gap: 8px; }
  .kpi { padding: 11px 12px; }
  .kpi .val { font-size: 20px; }

  /* ⚠️ 订单页的统计条是另一个类（.ord-stats/.ord-stat，不是 .kpi-grid/.kpi），
     它的 minmax(166px) 在 390px 上只排得下一列 ⇒ 5 张卡占满整屏。
     这里同样强制两列。
     ⚠️ 子元素类名也不同（.l/.v/.s vs .lbl/.val/.foot）—— 别照着上面那组抄。 */
  .ord-stats { grid-template-columns: repeat(2, 1fr); gap: 8px; }
  .ord-stat { padding: 11px 12px; }
  .ord-stat .v { font-size: 19px; }

  /* ---------- 4. 表格 → 卡片堆叠 ---------- */
  /* 原理：把每个 <tr> 变成一张卡，<td> 变块级，表头字（data-label）放左边。
     ⚠️ 表头字来自 JS 写入的 data-label（见 app.js 的 tabularizeLabels）。
        没写 data-label 的 td（主列 / 复选框列 / 操作列）就不显示标签。
     ⚠️ 卡片用 flex-wrap 排：主列和操作列各占整行，中间字段两两并排 ——
        纯 block 的话 11 个字段要滚两屏，两列能把高度砍掉近一半。 */

  .table-scroll { overflow-x: visible; }

  table.tb { font-size: 13px; width: 100% !important; min-width: 0 !important; table-layout: fixed; }
  /* ⚠️ 上面 width/min-width 两条必须带 !important：
        出入库、收款流水那几张表在桌面端有自己的 min-width（tb-pmt 是 1720px），
        不压掉就会在卡片模式下把 table 撑到 1813px ⇒ 整页横向溢出（实测踩过）。
        table-layout:fixed 是让 td 的 flex 宽度声明真正生效，否则浏览器按内容宽度算。 */
  table.tb thead { display: none; }
  table.tb tbody { display: block; }
  table.tb tbody tr {
    display: flex;
    flex-wrap: wrap;
    border: 1px solid var(--line);
    border-radius: 10px;
    background: var(--fill-1);
    padding: 9px 11px;
    margin-bottom: 9px;
  }
  /* 手机上取消 hover 变色（触屏 hover 会粘住） */
  table.tb tbody tr:hover { background: var(--fill-1); }

  table.tb td {
    /* 默认一列一个字段，占满整行 */
    flex: 1 1 100%;
    padding: 3px 0;
    border-bottom: 0;
    text-align: left !important;
    white-space: normal !important;
    display: flex;
    align-items: baseline;
    gap: 7px;
    min-width: 0;
  }
  /* 短字段两列并排（省一半滚动高度）。
     ⚠️ 只挑明确「内容短」的：数值列 / 状态标签类 / 时间列。
        文本长的（备注、地址）保持整行，否则会被压成竖排。 */
  table.tb td.num,
  table.tb td.mono,
  table.tb td.nowrap { flex: 1 1 46%; }
  table.tb td.num { text-align: left; }

  /* 字段名（JS 注入的 data-label） */
  table.tb td[data-label]::before {
    content: attr(data-label);
    flex: 0 0 auto;
    min-width: 62px;
    font-size: 11.5px;
    color: var(--text-3);
    line-height: 1.6;
    order: -1;
  }
  /* 单元格内的内容区：允许换行、允许截断长串 */
  table.tb td > * { min-width: 0; max-width: 100%; }

  /* 「客户名」这类主列：手机上要突出，占满一行且大一号。
     ⚠️ 关键：主列 td 在 JS 打标签时被**故意跳过**（不打 data-label），见 app.js
        tabularizeLabels 里的注释 —— 否则「客户 姓名 电话」+ 下一行子字段会重复显示号码。
        所以这里靠 :has(.nm-cell) 认它，而不是靠属性。
     ⚠️ :has() 需要 Chrome 105+ / Safari 15.4+。老浏览器不认这条选择器，
        结果是主列退化成普通行（多个「客户」前缀）—— 只是不好看，不影响功能。 */
  table.tb td:has(.nm-cell),
  table.tb td.nm-cell {
    flex: 1 1 100%;
    display: block;
    font-size: 14.5px;
    font-weight: 700;
    padding-bottom: 6px;
    border-bottom: 1px dashed var(--line);
    margin-bottom: 3px;
  }
  table.tb td:has(.nm-cell)::before,
  table.tb td.nm-cell::before { content: none; }
  /* 主列里嵌的说明行（电话/公司）不该跟着变粗变大 */
  table.tb td:has(.nm-cell) .sub {
    font-size: 12.5px; font-weight: 400; color: var(--text-3);
  }

  /* 复选框列：不占整行，缩成一个小方块贴在左上角 */
  table.tb td.td-check {
    flex: 0 0 auto;
    padding: 0 6px 0 0;
    align-self: center;
  }

  /* 操作列：按钮撑满一行（手机上手指点得准） */
  table.tb td.act {
    flex: 1 1 100%;
    display: flex;
    gap: 7px;
    padding-top: 8px;
    margin-top: 5px;
    border-top: 1px dashed var(--line);
    white-space: normal;
  }
  table.tb td.act::before { content: none; }
  table.tb td.act .btn { flex: 1 1 auto; justify-content: center; }

  /* 支付明细那张表原来锁了 min-width:1720px，手机上必须放开 */
  table.tb.tb-pmt { min-width: 0; }
  table.tb.tb-pmt td .cell-clip { max-width: none; }

  /* ---------- 5. 抽屉 / 弹窗：手机上占满宽度 ---------- */

  .drawer { width: 100%; }
  .drawer-head { padding: 13px 14px; }
  .drawer-head .t { font-size: 15.5px; }
  .drawer-body { padding: 13px 14px; }
  .drawer-foot { padding: 11px 14px; flex-wrap: wrap; }
  .drawer-foot .btn { flex: 1 1 auto; justify-content: center; }

  .modal { width: auto !important; max-width: none !important; margin: 10px; max-height: 92vh; }
  .modal-body { padding: 13px 14px; }
  .modal-foot { padding: 11px 14px; flex-wrap: wrap; }
  .modal-foot .btn { flex: 1 1 auto; justify-content: center; }

  /* 键值对表：左列 92px 太宽，手机压到 76px */
  .kv { grid-template-columns: 76px 1fr; gap: 7px 10px; font-size: 13px; }
  .drawer-body .kv { grid-template-columns: 76px 1fr; }

  /* 表单：单列（原来 620px 才切，现在 860px 就切，平板竖屏也不必两列） */
  .form-grid { grid-template-columns: 1fr; }

  .grid-2, .grid-3 { grid-template-columns: 1fr; }

  /* ---------- 6. 日程月历：手机上格子矮一半，否则 7 列全挤烂 ---------- */

  .sched-wrap { flex-direction: column; }
  .sched-side { width: 100%; flex: 1 1 auto; }
  .cal-grid, .cal-week { gap: 3px; }
  .cal-cell { min-height: 62px; padding: 3px 3px; border-radius: 7px; }
  .cal-d { font-size: 11.5px; margin-bottom: 2px; }
  .cal-ev { font-size: 10.5px; padding: 1px 3px; border-left-width: 2px; }
  .cal-ev .t { display: none; }
  .cal-nav { width: 32px; height: 32px; }
  .cal-month { min-width: 96px; font-size: 13.5px; }

  /* ---------- 7. 其它零散 ---------- */

  .bar-row .vl { width: 40px; flex: 0 0 40px; }
  .funnel-step .nm { width: 58px; flex: 0 0 58px; font-size: 12px; }
  .funnel-step .rate { width: 44px; flex: 0 0 44px; }

  .toast-wrap { left: 10px; right: 10px; transform: none; }
  .toast { width: 100%; text-align: center; }

  .login-card { margin: 0 14px; padding: 22px 18px; }

  .section { margin-bottom: 16px; }
}

/* 超窄屏（iPhone SE / 小屏安卓 320~360）：再压一档 */
@media (max-width: 380px) {
  .kpi-grid { grid-template-columns: 1fr; }
  .topbar h1 { font-size: 13.5px; }
  table.tb td[data-label]::before { flex: 0 0 62px; font-size: 11px; }
  .cal-cell { min-height: 52px; }
}

/* ==========================================================================
   乐语 1:1 复刻层（2026-10-08）
   —— 老板要求：界面/布局/排版/颜色完全照搬乐语，员工零学习成本。
      实测像素全部来自**真实乐语 DOM**（tools/_scrape-leyu-tree.mjs 现场量的），
      数据落在 data/leyu-menu-tree.json 的 style 段，不是猜的：
        侧栏宽 200px · 底色 rgb(0,21,41) · 文字 rgb(81,90,110)
        选中色 rgb(45,140,240) · 行高 43px · 字号 12px
        顶栏白底 · 顶栏高 45px
   ========================================================================== */

/* ---- 乐语 iconfont（原件从 api.jiain.net 下载，放 public/fonts/） ---- */
@font-face {
  font-family: 'leyu-iconfont';
  src: url('/fonts/leyu-iconfont.woff2') format('woff2'),
       url('/fonts/leyu-iconfont.woff') format('woff'),
       url('/fonts/leyu-iconfont.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: block;
}
.leyu-ic {
  font-family: 'leyu-iconfont' !important;
  font-style: normal;
  font-weight: 400;
  line-height: 1;
  display: inline-block;
  speak: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ---- 侧栏：200px / 深蓝底 ---- */
.side {
  width: 200px;
  flex: 0 0 200px;
  padding: 0;
  background: #001529;
  border-right: none;
  gap: 0;
}
/* 乐语的 logo 区是深色带，不是白底卡片 */
.side .brand {
  height: 45px;
  padding: 0 14px;
  gap: 8px;
  background: #002140;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  flex: 0 0 45px;
}
.side .brand .mark {
  width: 22px; height: 22px; border-radius: 4px;
  font-size: 12px;
  background: #2d8cf0;
  color: #fff;
}
.side .brand .t { font-size: 13px; font-weight: 600; color: #fff; }
.side .brand .s { display: none; }

/* ---- 一级分组标题（乐语 .ivu-menu-submenu-title）：43px 行高 ---- */
.nav-group {
  margin: 0;
  padding: 0 16px;
  /* 🚨 43px 必须配 `flex: none`：
     .side 是 `display:flex; flex-direction:column`（见文件上方原始定义），
     侧栏内容总高（19 组 × 43 + 展开后的二级）远超视口 ⇒ flex 会把每个子项**压扁**。
     实测不加这条时分组标题只有 19px、隐藏的二级项压成 0px —— 而且因为被压扁，
     43px 这个「照搬乐语的实测值」根本没生效。
     加 flex:0 0 auto（= none）后行高才是真的 43px。二级项同理，见 .nav-item。 */
  flex: none;
  height: 43px;
  box-sizing: border-box;
  border-radius: 0;
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 0;
  color: rgba(255, 255, 255, 0.65);
  gap: 8px;
  transition: color 0.2s ease;
}
.nav-group:hover { background: transparent; color: #fff; }
.nav-group:focus-visible { outline: none; }
.nav-group:first-child, .nav-tools + .nav-group { margin-top: 0; }
.nav-group.collapsed { color: rgba(255, 255, 255, 0.65); }
/* 分组前的图标位（乐语有一级图标） */
.leyu-grp-ic {
  font-size: 15px;
  width: 18px;
  text-align: center;
  flex: 0 0 18px;
  opacity: 0.92;
}
.nav-group .caret {
  font-size: 10px;
  color: rgba(255, 255, 255, 0.5);
  margin-left: auto;
}
.nav-group:hover .caret { color: rgba(255, 255, 255, 0.6); }

/* ---- 二级项（乐语 .ivu-menu-item）：43px 行高、左缩进 40px ---- */
.nav-item {
  padding: 0 16px 0 40px;
  flex: none;              /* 同 .nav-group：不写会被 flex 容器压扁（实测压到 0） */
  height: 43px;
  box-sizing: border-box;
  border-radius: 0;
  font-size: 12px;
  border: none;
  gap: 0;
  color: rgba(255, 255, 255, 0.65);
  transition: color 0.2s ease;
}
.nav-item:hover { background: transparent; color: #fff; }
.nav-item .ic { display: none; }
/* 选中：乐语此处只有字色变化（background 实测是 transparent）+ 右侧一条蓝边 */
.nav-item.active,
[data-theme="light"] .nav-item.active {
  background: transparent;
  border-color: transparent;
  color: #2d8cf0;
  font-weight: 400;
}
.nav-item.nav-sub { padding: 0 16px 0 40px; font-size: 12px; }
.nav-item.nav-sub .ic { display: none; }
/* 一级单项（首页 / 消息中心…）：图标在左，不缩进 */
.nav-item.nav-top { padding: 0 16px; gap: 8px; }
.nav-item.nav-top .ic { display: inline-block; width: 18px; text-align: center; font-size: 15px; opacity: 0.92; }

/* 角标（待办数）—— 乐语用小红点 */
.nav-item .badge-due { margin-left: auto; }

/* ---- 「全部折叠」工具条：乐语没有，为不破坏照搬观感做弱化 ---- */
.nav-tools {
  padding: 6px 16px 6px;
  margin: 0;
  flex: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.nav-tools-t { font-size: 11px; color: rgba(255, 255, 255, 0.5); letter-spacing: 0; text-transform: none; }
.nav-tool {
  font-size: 11px;
  color: rgba(255, 255, 255, 0.55);
  border-color: rgba(255, 255, 255, 0.22);
}
.nav-tool:hover { color: #fff; border-color: rgba(255, 255, 255, 0.45); }

/* ---- 底部用户区：深色底上的浅色字 ---- */
.side-foot { border-top: 1px solid rgba(255, 255, 255, 0.08); padding: 10px 12px; }
.side-user .n { font-size: 12.5px; color: #fff; }
.side-user .r { font-size: 11px; color: rgba(255, 255, 255, 0.58); }
.side-foot .btn-ghost {
  color: rgba(255, 255, 255, 0.6);
  border-color: rgba(255, 255, 255, 0.16);
  background: transparent;
}
.side-foot .btn-ghost:hover { color: #fff; background: rgba(255, 255, 255, 0.08); }

/* ---- 头像 & 主题按钮：这两样原本是按「浅色侧栏」配的，
   现在侧栏恒为 #001529 深色 ⇒ 必须就地改配色，否则头像字看不见 ---- */
.side .avatar {
  /* 浅灰蓝底 + 深字：在深侧栏上对比 9.6:1（原 #334155 底 + #cbd5e1 字只有 1.78:1）。
     ⚠️ 这里必须用 **实色 background-color**，不能用 linear-gradient：
       验收脚本沿祖先链取的是 computed `backgroundColor`，渐变只写在 `background-image` 上，
       于是取不到底色、一路穿透到深侧栏 ⇒ 明明改好了却仍被报 1.78:1（假失败）。
       用实色后脚本能取到，且视觉上深侧栏里的圆头像本来也不需要渐变。 */
  background-color: #dbe3ee;
  background-image: none;
  color: #334155;
}

/* 顶栏在乐语里是白的 ⇒ 深色主题下顶栏上的主题按钮也是深字浅底？
   不 —— 顶栏白底对两套主题都成立（照搬乐语），所以按钮统一按浅底走。
   实测 rgba(159,176,203) 在白底上只有 2.2:1，必须改成深色。 */
.topbar .theme-btn {
  color: #515a6e;
  border-color: #dcdee2;
  background: #fff;
}
.topbar .theme-btn:hover { color: #17233d; border-color: #b7bcc4; background: #f5f7f9; }

/* ---- 顶栏：乐语白底 45px ---- */
.topbar {
  height: 45px;
  padding: 0 16px;
  gap: 10px;
  background: #fff;
  border-bottom: 1px solid #e8eaec;
  backdrop-filter: none;
}
.topbar h1 { font-size: 14px; font-weight: 500; color: #17233d; letter-spacing: 0; }
.topbar .btn { font-size: 12px; }
.content { padding: 16px; background: #f5f7f9; }
[data-theme="dark"] .content { background: #0b1222; }

/* 侧栏滚动条在深底上要浅色 */
.side::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.16); }
.side::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.28); }

/* 浅色主题下侧栏**仍然保持深色**（乐语就只有一套深色侧栏，不随主题变） */
[data-theme="light"] .side { background: #001529; border-right: none; }
[data-theme="light"] .side .brand { background: #002140; }
[data-theme="light"] .nav-group { color: rgba(255, 255, 255, 0.65); }
[data-theme="light"] .nav-item { color: rgba(255, 255, 255, 0.65); }
[data-theme="light"] .side-user .n { color: #fff; }

/* ---- 空壳页（C 档）：乐语的「功能未开通」占位观感 ---- */
.leyu-stub {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  min-height: 420px; gap: 10px; text-align: center;
  /* #808695 在 #f5f7f9 上只有 3.39:1（不达 AA 4.5）⇒ 压深到 #5a6275（6.1:1）。
     这是**说明文字**不是装饰，老板的验收脚本按正文标准卡，必须达标。 */
  color: #5a6275;
}
.leyu-stub .big { font-size: 42px; line-height: 1; opacity: 0.35; }
.leyu-stub .t { font-size: 15px; color: #17233d; font-weight: 500; }
.leyu-stub .s { font-size: 12.5px; line-height: 1.9; }
[data-theme="dark"] .leyu-stub .t { color: var(--text); }
[data-theme="dark"] .leyu-stub { color: var(--text-3); }
.leyu-stub code {
  background: rgba(128, 134, 149, 0.14);
  padding: 1px 6px; border-radius: 3px; font-size: 12px;
}

/* ---- 手机端：抽屉里的乐语侧栏保持深色 ---- */
@media (max-width: 860px) {
  [data-theme="dark"] .side,
  [data-theme="light"] .side { background: #001529; }
  .side { padding: 0; }
  .nav-group, .nav-item { height: 44px; }
  .content { padding: 12px 10px 32px; }
  .topbar { padding: 0 10px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   【乐语 1:1 复刻层 · 第 2 部分】列表页组件规格
   ══════════════════════════════════════════════════════════════════════════

   来源：**从乐语真机上量的 computed style**（不是凭印象画的）。
     抓取脚本 tools/_scrape-leyu-page.mjs，样本落在 data/.leyu-menu/page-*.json
     取了两页交叉验证，规格一致：
       /customers/list  「联系人列表」  5259 条
       /Order/order     「订单管理」    16349 条

   乐语实测规格（两页一致）：
     ┌ 布局 ────────────────────────────────────────────────
     │ 侧栏 200px  ·  顶栏 45px  ·  内容区底色 rgb(245,247,249)
     │ 内容区从 x=200 y=45 起，无外 padding（内边距在卡片里）
     ├ 卡片 ────────────────────────────────────────────────
     │ 白底、无圆角、无阴影、1px 边框
     ├ 大搜索框 ───────────────────────────────────────────
     │ h:40  fs:14px  radius:4px  placeholder「XXX/XXX/XXX」
     │ ⚠️ 它**居中占很宽**（实测 677px），不是普通 input
     ├ 筛选下拉 / 日期框 ──────────────────────────────────
     │ h:32  fs:14px  radius:4px  1px solid #dcdee2
     ├ 按钮 ───────────────────────────────────────────────
     │ 小按钮 h:24  fs:12px  radius:3px
     │ 常规 = 白底 + #515a6e 字 + 1px solid #dcdee2
     │ 主色 = #2d8cf0 底 + 白字
     │ 🚨「清除」= rgb(237,64,20) 底 + 白字（危险橙红，最容易漏的一条）
     ├ 表格 ───────────────────────────────────────────────
     │ 类名语义 = ivu-table-small + border + fixed-top
     │ 表头 h:36  bg:rgb(248,248,249)  color:#515a6e  fs:12px  **fw:700**
     │ 行   h:40  fs:12px  color:#515a6e  白底  1px 下边框
     │ 表格外框 1px solid #e8eaec，白底
     ├ 分页 ───────────────────────────────────────────────
     │ h:33  文案「共 N 条」+ 首页/上下页 + 页码 + 跳页 + 「20 条/页」选择器
     └─────────────────────────────────────────────────────
   ⚠️ 这些都是「员工一天到晚盯着看」的东西 ⇒ 越像，重新教育成本越低。

   ⚠️ 深色主题怎么办：乐语只有一套浅色。但本系统有换肤（老板 10-04 要的）。
      策略 = **浅色主题走乐语原味，深色主题保留原有 aurora 观感**。
      所以下面全部用 `[data-theme="light"]` 前缀限定，深色下不动。
      这样「像乐语」与「能用深色」两个诉求都不牺牲。
   ══════════════════════════════════════════════════════════════════════════ */

/* ---- 1. 内容区：乐语底色 + 无外 padding ---- */
[data-theme="light"] .content { background: #f5f7f9; padding: 0; }

/* ---- 2. 列表卡片：白底、直角、1px 边框、无阴影 ---- */
[data-theme="light"] .card {
  background: #fff;
  border: 1px solid #e8eaec;
  border-radius: 0;
  box-shadow: none;
  padding: 10px 16px 14px;
}

/* ---- 3. 卡片头：乐语没有「标题+副标题」那种花哨，只有一条窄信息帯 ---- */
[data-theme="light"] .card-head { margin-bottom: 10px; min-height: 24px; }
[data-theme="light"] .card-head .sub { font-size: 12px; line-height: 24px; color: #515a6e; }

/* ---- 4. 信息药丸：改成乐语那种「灰字 + 竖线分隔」的朴素样式 ---- */
[data-theme="light"] .tb-pill {
  background: transparent;
  border: none;
  border-radius: 0;
  padding: 0 10px 0 0;
  margin-right: 10px;
  font-size: 12px;
  color: #515a6e;
  box-shadow: none;
}
[data-theme="light"] .tb-pill + .tb-pill { border-left: 1px solid #e8eaec; padding-left: 10px; }
[data-theme="light"] .tb-pill b { color: #17233d; font-weight: 700; }
[data-theme="light"] .tb-pill-ro {
  color: #808695;
  border-left: 1px solid #e8eaec !important;
  padding-left: 10px;
}
[data-theme="light"] .tb-note { color: #808695; font-size: 12px; }

/* ---- 5. 输入框 / 下拉：乐语 h:32 radius:4px ---- */
[data-theme="light"] .filters .input,
[data-theme="light"] .filters .select,
[data-theme="light"] .tb-range .input {
  height: 32px;
  font-size: 14px;
  border-radius: 4px;
  border: 1px solid #dcdee2;
  background: #fff;
  color: #515a6e;
  padding: 0 10px;
}
[data-theme="light"] .filters .input::placeholder { color: #c5c8ce; }
[data-theme="light"] .filters .input:focus,
[data-theme="light"] .filters .select:focus,
[data-theme="light"] .tb-range .input:focus {
  border-color: #57a3f3;
  box-shadow: 0 0 0 2px rgba(45, 140, 240, 0.2);
}

/* ⭐ 大搜索框：乐语把它做成一个又高又宽的「主搜索」，居中撑开。
   这是列表页第一眼最强的辨识特征，必须照搬。 */
[data-theme="light"] .filters .tb-q {
  flex: 1 1 420px;
  height: 40px;
  font-size: 14px;
  border-radius: 4px;
  max-width: 760px;
}

/* ---- 6. 按钮：小按钮 h:24 fs:12 radius:3px ---- */
[data-theme="light"] .btn {
  height: 32px;
  border-radius: 4px;
  font-size: 13px;
  background: #fff;
  border: 1px solid #dcdee2;
  color: #515a6e;
  font-weight: 400;
  box-shadow: none;
}
[data-theme="light"] .btn:hover { background: #fff; border-color: #57a3f3; color: #57a3f3; }
/* 工具栏里的小按钮（乐语 h:24） */
[data-theme="light"] .card-head .btn,
[data-theme="light"] .pager .btn,
[data-theme="light"] .filters .btn {
  height: 24px;
  padding: 0 8px;
  font-size: 12px;
  border-radius: 3px;
  line-height: 22px;
}
[data-theme="light"] .btn-primary {
  background: #2d8cf0;
  border-color: #2d8cf0;
  color: #fff;
}
[data-theme="light"] .btn-primary:hover { background: #57a3f3; border-color: #57a3f3; color: #fff; }
/* 🚨 乐语的「清除」是**危险橙红**，不是普通的灰按钮 —— 员工一眼就认这个红。
   实测 computed：bg rgb(237,64,20) / color #fff / 1px solid rgb(237,64,20)。 */
[data-theme="light"] [data-tbclear] {
  background: #ed4014;
  border-color: #ed4014;
  color: #fff;
}
[data-theme="light"] [data-tbclear]:hover {
  background: #f16643; border-color: #f16643; color: #fff;
}
/* 幽灵按钮在乐语体系里 = 普通白底按钮 */
[data-theme="light"] .btn-ghost {
  background: #fff; border: 1px solid #dcdee2; color: #515a6e;
}

/* ---- 7. 表格：这就是员工看了四五年那张表 ---- */
[data-theme="light"] .table-scroll { border: 1px solid #e8eaec; background: #fff; }

[data-theme="light"] table.tb { border-collapse: separate; border-spacing: 0; }

/* 表头：h36 / #f8f8f9 / #515a6e / 12px / **加粗** */
[data-theme="light"] table.tb thead th {
  height: 36px;
  padding: 0 10px;
  background: #f8f8f9;
  color: #515a6e;
  font-size: 12px;
  font-weight: 700;
  border-bottom: 1px solid #e8eaec;
  border-right: 1px solid #e8eaec;
  white-space: nowrap;
}
[data-theme="light"] table.tb thead th:last-child { border-right: none; }
[data-theme="light"] table.tb th.th-sort:hover { color: #2d8cf0; background: #f0f1f3; }
[data-theme="light"] table.tb th.th-sort.on { color: #2d8cf0; }

/* 行：h40 / 12px / #515a6e / 白底 + 1px 下边框 */
[data-theme="light"] table.tb tbody td {
  height: 40px;
  padding: 0 10px;
  font-size: 12px;
  color: #515a6e;
  border-bottom: 1px solid #e8eaec;
  border-right: 1px solid #e8eaec;
  background: #fff;
  vertical-align: middle;
}
[data-theme="light"] table.tb tbody td:last-child { border-right: none; }
[data-theme="light"] table.tb tbody tr:hover td { background: #ebf7ff; }
[data-theme="light"] table.tb tbody tr:last-child td { border-bottom: none; };

/* ---- 8. 分页器：iView .ivu-page 的观感 ---- */
[data-theme="light"] .pager {
  padding-top: 12px;
  gap: 6px;
  font-size: 12px;
  color: #515a6e;
  align-items: center;
}
[data-theme="light"] .pager .btn {
  background: #fff;
  border: 1px solid #dcdee2;
  border-radius: 3px;
  color: #515a6e;
}
[data-theme="light"] .pager .btn:hover:not([disabled]) { border-color: #2d8cf0; color: #2d8cf0; }
[data-theme="light"] .pager .btn[disabled] { color: #c5c8ce; border-color: #e8eaec; background: #f7f7f7; }
[data-theme="light"] .pager .select { height: 24px; font-size: 12px; border-radius: 3px; }

/* ---- 9. 筛选区：乐语是一行排开、等距 ---- */
[data-theme="light"] .filters { gap: 10px; margin-bottom: 0 !important; }

/* ---- 10. 抽屉 / 弹窗：乐语直角白卡 ---- */
[data-theme="light"] .drawer-panel,
[data-theme="light"] .modal-box {
  background: #fff;
  border: 1px solid #e8eaec;
  border-radius: 4px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

/* ---- 11. 分页器文案元素（乐语文案口径） ---- */
.page-total { color: #515a6e; font-size: 12px; margin-right: 4px; }
.page-total b { color: #17233d; font-weight: 700; }
.page-cur { color: #515a6e; font-size: 12px; padding: 0 4px; }
.page-cur b { color: #17233d; font-weight: 700; }
.page-hint { color: #808695; font-size: 12px; }
[data-theme="dark"] .page-total, [data-theme="dark"] .page-cur { color: var(--text-2); }
[data-theme="dark"] .page-total b, [data-theme="dark"] .page-cur b { color: var(--text); }
[data-theme="dark"] .page-hint { color: var(--text-3); }

/* ══════════════════════════════════════════════════════════════════════════
   【乐语 1:1 复刻层 · 第 3 部分】表格工具条 + 筛选区（第二次钻孔取样）
   ══════════════════════════════════════════════════════════════════════════

   ⚠️ 这一层推翻了第 2 部分里「工具栏按钮 = 有边框的小按钮」的假设。
      第二次用文本锚点精确钻取（tools/_scrape-leyu-drill.mjs / _scrape-leyu-pill.mjs）
      拿到的真实结构是：

   ① 表格上方那一行 **不是按钮，是「图标 + 文字的链接」**：
        容器 class `nav_showSearch`，h:37，**透明底 / 无边框**
        每一项 class `tool-item line line1 blod cursor`，h:37，透明底 / 无边框
        图标 = `<i class="ivu-icon">` font-size:20px，**每个功能一个专属颜色**：
          ＋新增   → 绿 rgb(25,190,107)
          ↑导入   → 蓝 rgb(92,173,255)
          文字 12px / color rgb(23,35,61)
        实测项序（联系人列表）：
          新增 · 批量操作 · 联系人选项配置 · 联系人冲突和校验 · 企微配置
          · 导入 · 导出 · 释放公海配置 · 查重 · 统计 · 其他设置
      🔎 一眼识别的关键：**颜色来自图标**，按钮本身是"裸"的。
         我们原来做成一排带边框的按钮，观感完全不一样 —— 员工会觉得"这不是乐语"。

   ② 筛选区不是「一排下拉框」，是**「标签 + 可选药丸」的成行结构**：
        容器 `one_selectBox`，每行 h:27，左侧 100px 标签（`one_selectLabel`，14px）
        右侧选项 `one_selectOptions`（h:27 容器，里面 21px 高的 item 包一个 tag）
        药丸 = `<span class="ant-tag-checkable ant-tag">`：
          h:24 / pad:4px 6px / radius:4px
          未选：透明底 + rgb(81,90,110) 字
          🚨 **选中：蓝底 rgb(24,144,255) + 白字**（Ant Design 蓝，**不是** iView 的 #2d8cf0！
             两个蓝差一点，但并排看就是不一样 —— 乐语混用了两套组件库，照搬就得分开）
        实测行序（联系人列表）：
          常用筛选 / 负责人 / 创建日期 / 联系人等级 / 最近联系日期
          / 跟进过程 / 创建人 / 推广人 / 更多筛选+收起
        行距：行高 27 + 上下 11px ⇒ y 步进 38px

   ③「更多筛选」是唯一真按钮：iView primary small
        h:24 / pad:1px 7px 2px / bg rgb(45,140,240) / radius:3px / 内含 15px 搜索图标

   ⚠️ 全部用 `[data-theme="light"]` 限定：只有浅色主题走乐语原味，
      深色主题保留我们自己的 aurora 观感（老板 10-04 要的换肤不能丢）。
   ══════════════════════════════════════════════════════════════════════════ */

/* ---- 11b. iView / Ionicons 字体（乐语功能按钮那套图标）----
   ⚠️ 别和上面的 leyu-iconfont 搞混：乐语**混用两套字体**
     · 侧栏菜单     → 品牌 iconfont（.leyu-ic，191 个社交/物流图标）
     · 功能按钮图标 → iView 自带的 Ionicons（.ivu-ic，860 个通用图标）
     新增=md-add、导入=md-cloud-upload、导出=md-cloud-download、查重=ios-search…
     两套都照搬才叫 1:1；只搬一套，员工会觉得"图标换了"。 */
@font-face {
  font-family: 'leyu-ionicons';
  src: url('/fonts/leyu-ionicons.143146fa.woff2') format('woff2'),
       url('/fonts/leyu-ionicons.99ac3308.woff') format('woff'),
       url('/fonts/leyu-ionicons.d535a25a.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: block;
}
.ivu-ic {
  font-family: 'leyu-ionicons' !important;
  font-style: normal;
  font-weight: 400;
  font-variant: normal;
  text-transform: none;
  line-height: 1;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ---- 12. 表格上方「图标+文字」工具条（乐语 tool-item）---- */
/* 我们原有的 .card-head 是「信息 + 导出/刷新」两件事混排。
   照搬乐语的做法：工具条自成一排、在表格正上方、左对齐裸链接。 */
[data-theme="light"] .leyu-toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0 16px;
  height: 37px;
  margin: 0 0 2px;
  padding: 0;
  background: transparent;
  border: none;
}
[data-theme="light"] .leyu-tool {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 37px;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 0;
  color: #17233d;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
  transition: color .13s ease;
}
[data-theme="light"] .leyu-tool:hover { color: #2d8cf0; }
[data-theme="light"] .leyu-tool .leyu-tool-ic {
  font-size: 20px;
  line-height: 1;
  /* 图标自带颜色（照搬乐语：每个功能一个专属色） */
  color: inherit;
}
/* 乐语那一列图标色（实测取值） */
[data-theme="light"] .leyu-tool[data-tone="add"] .leyu-tool-ic { color: #19be6b; }   /* ＋ 新增 */
[data-theme="light"] .leyu-tool[data-tone="import"] .leyu-tool-ic { color: #5cadff; } /* ↑ 导入 */
[data-theme="light"] .leyu-tool[data-tone="export"] .leyu-tool-ic { color: #5cadff; } /* ↓ 导出 */
[data-theme="light"] .leyu-tool[data-tone="refresh"] .leyu-tool-ic { color: #515a6e; }
[data-theme="light"] .leyu-tool[data-tone="batch"] .leyu-tool-ic { color: #5cadff; }
[data-theme="light"] .leyu-tool[data-tone="setting"] .leyu-tool-ic { color: #515a6e; }
[data-theme="light"] .leyu-tool[data-tone="stat"] .leyu-tool-ic { color: #ff9900; }

/* ---- 13. 筛选区：标签 + 药丸（乐语 one_selectBox）---- */
[data-theme="light"] .leyu-filterbox {
  padding: 10px 0 0;
  border: none;
  background: transparent;
}
[data-theme="light"] .leyu-frow {
  display: flex;
  align-items: flex-start;
  gap: 0;
  min-height: 27px;
  margin-bottom: 11px;
}
[data-theme="light"] .leyu-frow:last-child { margin-bottom: 6px; }
[data-theme="light"] .leyu-flabel {
  flex: none;
  width: 100px;
  height: 27px;
  line-height: 27px;
  font-size: 14px;
  color: #17233d;
}
[data-theme="light"] .leyu-fopts {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 6px;
  /* 🚨 行高必须锁死 27px：药丸是 24px，但长列表退化成的 <select> 默认 32px，
     不压住的话整行会撑到 42px（实测过）——乐语每行都是齐刷刷的 27px。 */
  min-height: 27px;
  max-height: 27px;
  overflow: hidden;
}
/* 行内有下拉时（长列表退化）让它贴合 27px 行高 */
[data-theme="light"] .leyu-fopts .select {
  height: 27px;
  font-size: 12px;
  border-radius: 4px;
  border: 1px solid #dcdee2;
  background: #fff;
  color: #515a6e;
  padding: 0 6px;
}
/* 有换行的行（药丸多）允许撑高：给一个例外，靠 :has 判 */
[data-theme="light"] .leyu-frow:has(.leyu-pill) { max-height: none; }
[data-theme="light"] .leyu-frow:has(.leyu-pill) .leyu-fopts { max-height: none; overflow: visible; }
/* 药丸：乐语 h:24 pad:4px 6px radius:4px */
[data-theme="light"] .leyu-pill {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding: 4px 6px;
  border-radius: 4px;
  border: none;
  background: transparent;
  color: #515a6e;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color .13s ease, color .13s ease;
}
[data-theme="light"] .leyu-pill:hover { color: #188fff; }
/* 🚨 选中态 = Ant 蓝 #1890ff + 白字（**不是** iView 的 #2d8cf0） */
[data-theme="light"] .leyu-pill.on {
  background: #1890ff;
  color: #fff;
}
[data-theme="light"] .leyu-pill.on:hover { color: #fff; }

/* 「更多筛选」是唯一真按钮：iView primary small */
[data-theme="light"] .leyu-morebtn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 24px;
  padding: 1px 7px 2px;
  border-radius: 3px;
  border: 1px solid #2d8cf0;
  background: #2d8cf0;
  color: #fff;
  font-size: 12px;
  cursor: pointer;
  white-space: nowrap;
}
[data-theme="light"] .leyu-morebtn:hover { background: #57a3f3; border-color: #57a3f3; }
[data-theme="light"] .leyu-morebtn .leyu-ic { font-size: 15px; }

/* 行内标签（来源类型/等级那种）：乐语是彩色小标签 */
[data-theme="light"] .leyu-tag {
  display: inline-block;
  padding: 0 6px;
  border-radius: 3px;
  font-size: 12px;
  line-height: 20px;
}

/* ⚠️ 上面的 `.leyu-toolbar` / `.leyu-frow` 单元测试锚点：
   验收脚本 tools/_ui-probe-listpage.js 会量这几种元素的 computed style。 */

/* ══════════════════════════════════════════════════════════════════════════
   【乐语 1:1 复刻层 · 第 4 部分】工具条文字色 / 分页器 / 行尾操作 / 更多筛选
   ══════════════════════════════════════════════════════════════════════════

   第三次钻孔取样（data/.leyu-menu/page-order-final.json 的 pagerHtml、
   pill-customers-list.json 的 toolAdd / toolImport / moreFilter）推翻了三条：

   ① 工具项文字 **不是** #17233d 深灰，而是 **rgb(43,133,228) 蓝**（<span class="blue">）
      容器 .tool-item 是 rgb(23,35,61)，但子 span 覆盖成蓝。
   ② 分页器有**数字页码**（1 2 3 … 818）+ 「跳至 N 页」输入框，不是只有上下页。
   ③ 「更多筛选」**不在工具条里**，在**筛选区底部**，且是裸链接（非蓝色按钮）。

   顺带一样：乐语行尾有「操作」列，里面是 `详情` / `复制` 两个蓝链接。
*/

/* ---- 工具项文字：容器是深灰 #17233d，**内层 span 才是蓝**（乐语实测两层色不同） ----
   实测 toolAdd.parent = .tool-item color rgb(23,35,61)；
       toolAdd（<span class="blue">）= rgb(43,133,228) fw:700。
   所以容器保持 #17233d，只把 span 染蓝。 */
[data-theme="light"] .leyu-tool span { color: #2b85e4; font-weight: 700; }
[data-theme="light"] .leyu-tool:hover span { color: #2d8cf0; }

/* ---- 分页器：iView `.ivu-page` 原样结构 ---- */
[data-theme="light"] .ivu-page {
  display: flex;
  align-items: center;
  gap: 0;
  margin: 0;
  padding: 13px 0 0;
  list-style: none;
  font-size: 12px;
  color: #515a6e;
}
[data-theme="light"] .ivu-page-total { margin-right: 10px; color: #515a6e; font-size: 12px; }
[data-theme="light"] .ivu-page > li {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  height: 32px;
  margin-right: 4px;
  border: 1px solid #dcdee2;
  border-radius: 4px;
  background: #fff;
  cursor: pointer;
  transition: border-color .13s ease, color .13s ease;
  user-select: none;
}
[data-theme="light"] .ivu-page > li > a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: #515a6e;
  font-size: 12px;
  text-decoration: none;
}
[data-theme="light"] .ivu-page > li:hover { border-color: #2d8cf0; }
[data-theme="light"] .ivu-page > li:hover > a { color: #2d8cf0; }
/* 🚨 特异性坑：`[data-theme="light"] .ivu-page > li` 是 (0,2,1)，
   而 `[data-theme="light"] .ivu-page-item-active` 只有 (0,2,0) ⇒ **li 规则赢**，
   选中页码会显示成白底灰字（实测踩过）。必须把选择器写成同样带 `> li` 的形状。 */
[data-theme="light"] .ivu-page > li.ivu-page-item-active {
  border-color: #2d8cf0;
  background: #2d8cf0;
}
[data-theme="light"] .ivu-page > li.ivu-page-item-active > a,
[data-theme="light"] .ivu-page > li.ivu-page-item-active:hover > a { color: #fff; font-weight: 700; }
[data-theme="light"] .ivu-page > li.ivu-page-disabled {
  border-color: #e8eaec;
  background: #f7f7f7;
  cursor: not-allowed;
}
[data-theme="light"] .ivu-page > li.ivu-page-disabled > a,
[data-theme="light"] .ivu-page > li.ivu-page-disabled:hover > a { color: #c5c8ce; cursor: not-allowed; }
[data-theme="light"] .ivu-page > li.ivu-page-item-jump { border-color: transparent; background: transparent; cursor: default; }
[data-theme="light"] .ivu-page > li.ivu-page-item-jump > a { color: #808695; }
[data-theme="light"] .ivu-page-options {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: auto;
}
[data-theme="light"] .ivu-select-mini {
  height: 32px;
  padding: 0 24px 0 8px;
  border: 1px solid #dcdee2;
  border-radius: 4px;
  background: #fff;
  color: #515a6e;
  font-size: 12px;
  cursor: pointer;
}
[data-theme="light"] .ivu-page-options-elevator { color: #515a6e; font-size: 12px; }
[data-theme="light"] .ivu-page-options-elevator input {
  width: 48px;
  height: 32px;
  margin: 0 4px;
  padding: 0 6px;
  border: 1px solid #dcdee2;
  border-radius: 4px;
  background: #fff;
  color: #515a6e;
  font-size: 12px;
  text-align: center;
  outline: none;
}
[data-theme="light"] .ivu-page-options-elevator input:focus { border-color: #57a3f3; }

/* ---- 行尾「操作」列：详情 / 复制 ---- */
[data-theme="light"] th.th-ops { text-align: center; }
[data-theme="light"] td.td-ops {
  white-space: nowrap;
  text-align: center;
}
[data-theme="light"] .row-link {
  display: inline-block;
  margin: 0 5px;
  color: #2b85e4;
  font-size: 12px;
  cursor: pointer;
  text-decoration: none;
}
[data-theme="light"] .row-link:hover { color: #57a3f3; text-decoration: underline; }

/* ---- 「更多筛选」：筛选区底部的裸链接（不是按钮） ---- */
[data-theme="light"] .leyu-morewrap {
  width: 50%;
  margin-top: 2px;
}
[data-theme="light"] .leyu-morelink {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  cursor: pointer;
  user-select: none;
}
[data-theme="light"] .leyu-morelink .ivu-ic {
  font-size: 15px;
  color: #515a6e;
}
[data-theme="light"] .leyu-morelink span {
  color: #2b85e4;
  font-weight: 700;
  font-size: 14px;
}
[data-theme="light"] .leyu-morelink:hover span { color: #2d8cf0; }
/* 收起状态：隐藏「更多」那一批行（默认收起，和乐语一致） */
[data-theme="light"] .leyu-filterbox:not(.tb-more-open) .leyu-fextra { display: none; }

/* ---- 行首勾选列（乐语表头第一列，60px 宽） ---- */
[data-theme="light"] th.th-check,
[data-theme="light"] td.td-check {
  width: 60px;
  text-align: center;
  padding: 0;
}
[data-theme="light"] .ivu-check {
  width: 14px;
  height: 14px;
  cursor: pointer;
  accent-color: #2d8cf0;
  vertical-align: middle;
}
[data-theme="light"] .leyu-checkedtip {
  display: inline-flex;
  align-items: center;
  align-self: center;
  height: 22px;
  margin-left: 10px;
  padding: 0 8px;
  border-radius: 3px;
  background: #e6f7ff;
  border: 1px solid #bae7ff;
  color: #2b85e4;
  font-size: 12px;
}
[data-theme="dark"] th.th-check,
[data-theme="dark"] td.td-check { width: 60px; text-align: center; padding: 0; }
[data-theme="dark"] .ivu-check { width: 14px; height: 14px; cursor: pointer; accent-color: #5cadff; }
[data-theme="dark"] .leyu-checkedtip {
  display: inline-flex; align-items: center; align-self: center;
  height: 22px; margin-left: 10px; padding: 0 8px; border-radius: 3px;
  background: var(--fill-2); color: #5cadff; font-size: 12px;
}

/* 🚨 浅色（乐语皮）下，枚举**不能是胶囊块** —— 乐语表格里就是纯彩色文字。
   对照实测：乐语「有效」= `<span class="green">有效</span>`，
   色 rgb(25,190,107)、fw:600、**底色透明、无 padding、无圆角**。
   所以这里把 .tb-enum 的胶囊外观整体拆掉，只留彩色文字 + 字重。 */
[data-theme="light"] .tb-enum {
  display: inline;
  padding: 0;
  border: none;
  border-radius: 0;
  background: transparent;
  font-size: 12px;
  font-weight: 600;
  line-height: inherit;
  color: #515a6e;
}
[data-theme="light"] .tb-enum.do { background: transparent; border: none; color: #19be6b; }
[data-theme="light"] .tb-enum.info { background: transparent; border: none; color: #2b85e4; }
[data-theme="light"] .tb-enum.warn { background: transparent; border: none; color: #ff9900; }
[data-theme="light"] .tb-enum.danger { background: transparent; border: none; color: #ed4014; }
[data-theme="light"] .tb-enum.undo { background: transparent; border: none; color: #808695; }

/* ---- 行内状态文字色：**照抄乐语源码的全局颜色类**（不是自造标签） ----
   来源：data/.leyu-src/css/app.1789716340000.css 原文
     .blue,.primary{color:#2b85e4!important}
     .green{color:#19be6b!important}
     .red{color:#ed4014!important}
   🚨 重要：乐语表里的「有效」「已交」这些**不是带底色的标签块**，
      而是**纯彩色文字**（实测 valid: <span class="green" style="...">有效</span>
      = rgb(25,190,107) fw:600，底色透明、无 padding、无圆角）。
      我上一版做成了带底色的 `.leyu-tag` —— 那是**另一个系统**的样子。
   权重：乐语用 `!important`，我们也跟，否则被 table td 的 color 压掉。 */
[data-theme="light"] .crm-c-blue, [data-theme="light"] .crm-c-primary { color: #2b85e4 !important; }
[data-theme="light"] .crm-c-green { color: #19be6b !important; }
[data-theme="light"] .crm-c-red { color: #ed4014 !important; }
[data-theme="light"] .crm-c-orange { color: #ff9900 !important; }
[data-theme="light"] .crm-c-gray { color: #808695 !important; }
/* 表格里的彩色文字统一 fw:600（乐语实测） */
[data-theme="light"] table.tb td [class^="crm-c-"] { font-weight: 600; }
/* 姓名列 = 蓝色可点链接（乐语姓名列是蓝链接） */
[data-theme="light"] .crm-link {
  color: #2b85e4;
  cursor: pointer;
  text-decoration: none;
}
[data-theme="light"] .crm-link:hover { color: #57a3f3; text-decoration: underline; }

[data-theme="dark"] .crm-c-blue, [data-theme="dark"] .crm-c-primary { color: #5cadff !important; }
[data-theme="dark"] .crm-c-green { color: #19be6b !important; }
[data-theme="dark"] .crm-c-red { color: #ff7875 !important; }
[data-theme="dark"] .crm-c-orange { color: #ff9900 !important; }
[data-theme="dark"] .crm-c-gray { color: var(--text-3) !important; }
[data-theme="dark"] table.tb td [class^="crm-c-"] { font-weight: 600; }
[data-theme="dark"] .crm-link { color: #5cadff; cursor: pointer; text-decoration: none; }
[data-theme="dark"] .crm-link:hover { color: #8ac6ff; text-decoration: underline; }

/* 「列设置」的图标照乐语是 `ios-menu` + `transform: rotate(90deg)`（16px）
   —— 横排的「三横」转 90° 变成「三竖」，就是个表格列的意象 */
[data-theme="light"] .leyu-ic-rot90,
[data-theme="dark"] .leyu-ic-rot90 { transform: rotate(90deg); display: inline-block; }

/* ---- 列设置面板（乐语 colType）：勾选哪些列显示 ---- */
.leyu-colpanel {
  position: fixed;
  z-index: 1200;
  min-width: 210px;
  max-height: 62vh;
  overflow: auto;
  padding: 10px 12px;
  border-radius: 4px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.16);
}
[data-theme="light"] .leyu-colpanel { background: #fff; border: 1px solid #e8eaec; }
[data-theme="dark"] .leyu-colpanel { background: var(--fill-1); border: 1px solid var(--line); }
.leyu-colpanel .cp-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 8px; padding-bottom: 7px;
}
[data-theme="light"] .leyu-colpanel .cp-head { border-bottom: 1px solid #e8eaec; color: #17233d; }
[data-theme="dark"] .leyu-colpanel .cp-head { border-bottom: 1px solid var(--line); color: var(--text); }
.leyu-colpanel .cp-head b { font-size: 13px; }
.leyu-colpanel .cp-head a { font-size: 12px; cursor: pointer; color: #2b85e4; }
.leyu-colpanel label {
  display: flex; align-items: center; gap: 6px;
  padding: 4px 2px; font-size: 12px; cursor: pointer; border-radius: 3px;
}
[data-theme="light"] .leyu-colpanel label { color: #515a6e; }
[data-theme="light"] .leyu-colpanel label:hover { background: #f5f7f9; }
[data-theme="dark"] .leyu-colpanel label { color: var(--text-2); }
[data-theme="dark"] .leyu-colpanel label:hover { background: var(--fill-2); }
.leyu-colpanel .cp-empty { font-size: 12px; padding: 6px 2px; }
[data-theme="light"] .leyu-colpanel .cp-empty { color: #808695; }
[data-theme="dark"] .leyu-colpanel .cp-empty { color: var(--text-3); }

/* ---- 统计面板（乐语 统计/图表分析）---- */
.leyu-statpanel {
  position: fixed; z-index: 1200;
  min-width: 260px; max-height: 62vh; overflow: auto;
  padding: 10px 12px; border-radius: 4px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.16);
}
[data-theme="light"] .leyu-statpanel { background: #fff; border: 1px solid #e8eaec; }
[data-theme="dark"] .leyu-statpanel { background: var(--fill-1); border: 1px solid var(--line); }
.leyu-statpanel .sp-head { margin-bottom: 8px; padding-bottom: 7px; font-size: 13px; font-weight: 700; }
[data-theme="light"] .leyu-statpanel .sp-head { border-bottom: 1px solid #e8eaec; color: #17233d; }
[data-theme="dark"] .leyu-statpanel .sp-head { border-bottom: 1px solid var(--line); color: var(--text); }
.leyu-statpanel .sp-row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 14px; padding: 5px 0; font-size: 12px;
}
[data-theme="light"] .leyu-statpanel .sp-row { color: #515a6e; }
[data-theme="dark"] .leyu-statpanel .sp-row { color: var(--text-2); }
.leyu-statpanel .sp-row b { font-size: 13px; font-weight: 700; }
[data-theme="light"] .leyu-statpanel .sp-row b { color: #17233d; }
[data-theme="dark"] .leyu-statpanel .sp-row b { color: var(--text); }
.leyu-statpanel .sp-bar {
  height: 6px; border-radius: 3px; margin: 2px 0 6px;
  background: #2d8cf0;
}

/* ---- 暂未实现的占位按钮：点了给一句明确说明，不要静默无反应 ---- */
[data-theme="light"] .leyu-tool.leyu-tool-todo span { color: #808695; }
[data-theme="light"] .leyu-tool.leyu-tool-todo .leyu-tool-ic { color: #c5c8ce !important; }

/* ===================================================================
   乐语 1:1 复刻层 · 第 5 部分 —— 搜索行 / 已选条件 / 工具项(.tool-item)
   ===================================================================
   依据全部是乐语**源码与真机 DOM**，不是照截图猜：
     · 真机 DOM：data/.leyu-menu/page-order-final.json（订单页）
       搜索按钮  box x=1155 w=56 h=32 bg=rgb(45,140,240) radius="4px 0 0 4px"
       更多筛选  box x=1210 w=80 h=32 bg=rgb(255,255,255) mar="0 0 0 -1px" radius="0 4px 4px 0"
       搜索框本体 x=518 w=630 h=36 cls=ivu-input-large
       「已选：」+ 清除(ivu-btn-error small) + 查询(ivu-btn-primary small)
     · 源码 DOM：<div class="tool-item line line1 blod cursor"> 容器色 rgb(23,35,61)
                 内层 <span class="blue"> 才是 rgb(43,133,228)
   =================================================================== */

/* ---- 搜索行：搜索标签 + 大输入框 + 连体（搜索|更多筛选） ---- */
.leyu-searchrow { display: flex; align-items: center; gap: 0; margin: 0 0 10px; flex-wrap: wrap; }
.leyu-searchlab {
  flex: 0 0 auto; margin-right: 10px; font-size: 14px; font-weight: 400;
}
[data-theme="light"] .leyu-searchlab { color: #515a6e; }
[data-theme="dark"] .leyu-searchlab { color: var(--text-2); }

.leyu-input-large {
  flex: 1 1 320px; min-width: 220px; height: 36px; padding: 6px 10px;
  font-size: 14px; line-height: 1.5; border-radius: 4px;
  border: 1px solid #dcdee2; outline: none;
}
[data-theme="light"] .leyu-input-large { background: #fff; color: #515a6e; }
[data-theme="dark"] .leyu-input-large { background: var(--fill-1); color: var(--text); border-color: var(--line); }
.leyu-input-large:focus { border-color: #57a3f3; box-shadow: 0 0 0 2px rgba(45, 140, 240, .18); }

/* 连体对：左「搜索」主色 + 右「更多筛选」白底，中间 -1px 重叠（乐语真机 mar 就是这么写的）
   ⚠️ 乐语真机尺寸：搜索 w:56 h:32 pad "5px 15px 6px"；更多筛选 w:80 h:32。
      高度写 36 是为了和 ivu-input-large（h36）齐平 —— 乐语真机搜索框 h36 而按钮 h32，
      两者**确实不等高**（原文就是 x=1155 y=65 h=32 vs 输入框 y=63 h=36）。
      这里保留 36 让这一行视觉整齐（保真度取舍：形状/颜色/连体已 1:1，只对齐了行高）。 */
[data-theme="light"] .leyu-btn-search {
  flex: 0 0 auto; height: 36px; padding: 0 15px; font-size: 14px;
  border: 1px solid #2d8cf0; border-radius: 4px 0 0 4px;
  background: #2d8cf0; color: #fff; cursor: pointer;
}
[data-theme="light"] .leyu-btn-morefilter {
  flex: 0 0 auto; height: 36px; min-width: 80px; padding: 0 15px; font-size: 14px; margin-left: -1px;
  border: 1px solid #dcdee2; border-radius: 0 4px 4px 0;
  background: #fff; color: #515a6e; cursor: pointer;
}
[data-theme="light"] .leyu-btn-search:hover { background: #57a3f3; border-color: #57a3f3; }
[data-theme="light"] .leyu-btn-morefilter:hover { color: #2d8cf0; border-color: #57a3f3; }
[data-theme="dark"] .leyu-btn-search {
  flex: 0 0 auto; height: 36px; padding: 0 15px; font-size: 14px;
  border: 1px solid var(--accent, #2d8cf0); border-radius: 4px 0 0 4px;
  background: var(--accent, #2d8cf0); color: var(--on-accent, #fff); cursor: pointer;
}
[data-theme="dark"] .leyu-btn-morefilter {
  flex: 0 0 auto; height: 36px; padding: 0 15px; font-size: 14px; margin-left: -1px;
  border: 1px solid var(--line); border-radius: 0 4px 4px 0;
  background: var(--fill-1); color: var(--text-2); cursor: pointer;
}

/* ---- 已选条件行（乐语原文：「已选：xx × | 清除 | 查询」） ---- */
.leyu-chosen { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin: 0 0 10px; }
[data-theme="light"] .leyu-chosenlab { font-size: 12px; color: #808695; }
[data-theme="dark"] .leyu-chosenlab { font-size: 12px; color: var(--text-2); }
.leyu-chosenchip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 6px; font-size: 12px; border-radius: 3px;
}
[data-theme="light"] .leyu-chosenchip { background: #f0f7ff; color: #2b85e4; border: 1px solid #bcdcff; }
[data-theme="dark"] .leyu-chosenchip { background: var(--fill-2); color: var(--text-2); border: 1px solid var(--line); }
.leyu-chosenchip i { font-style: normal; cursor: pointer; opacity: .6; }
.leyu-chosenchip i:hover { opacity: 1; }
[data-theme="light"] .leyu-chosenchip i { color: #ed4014; }

/* 乐语小号按钮（清除=error 橙红 / 查询=primary 蓝），真机 h=24 pad=1px 7px 2px radius=3px */
[data-theme="light"] .ivu-btn-small {
  height: 24px; padding: 1px 7px 2px; font-size: 12px; border-radius: 3px;
  cursor: pointer; line-height: 1.5;
}
[data-theme="light"] .ivu-btn-error { background: #ed4014; border: 1px solid #ed4014; color: #fff; }
[data-theme="light"] .ivu-btn-error:hover { background: #f16643; border-color: #f16643; }
[data-theme="light"] .ivu-btn-primary.ivu-btn-small { background: #2d8cf0; border: 1px solid #2d8cf0; color: #fff; }
[data-theme="light"] .ivu-btn-primary.ivu-btn-small:hover { background: #57a3f3; border-color: #57a3f3; }
[data-theme="light"] .leyu-btn-clearsm { margin-left: 10px; }
[data-theme="light"] .leyu-btn-querysm { margin-left: 5px; }
[data-theme="dark"] .ivu-btn-small {
  height: 24px; padding: 1px 7px 2px; font-size: 12px; border-radius: 3px;
  cursor: pointer; line-height: 1.5; border: 1px solid var(--line);
  background: var(--fill-1); color: var(--text-2);
}
[data-theme="dark"] .ivu-btn-error { border-color: #ed4014; color: #ff7875; }
[data-theme="dark"] .leyu-btn-clearsm { margin-left: 10px; }
[data-theme="dark"] .leyu-btn-querysm { margin-left: 5px; }

/* ---- 工具项 .tool-item（乐语真实类名） ----
   ⚠️ 容器字色 rgb(23,35,61)，内层 span.blue 是 rgb(43,133,228) 蓝 —— **两层不同色**。
      整行 fw:700（乐语 .blod）；图标是 .green 包裹的 i，字号由内联 style 给。
      实测行高 37px、项间距 8px（pill-customers-list.json toolAdd: mar "0px 8px", parent h=37）。 */
.leyu-toolbar { display: flex; align-items: center; flex-wrap: wrap; gap: 0; margin: 0 0 12px; }
.tool-item {
  display: inline-flex; align-items: center; gap: 3px;
  height: 37px; margin: 0 8px; font-size: 12px; font-weight: 700;
  cursor: pointer; user-select: none;
}
[data-theme="light"] .tool-item { color: #17233d; }
[data-theme="dark"] .tool-item { color: var(--text); }
[data-theme="light"] .tool-item .blue { color: #2b85e4; }
[data-theme="dark"] .tool-item .blue { color: var(--text-2); }
[data-theme="light"] .tool-item:hover .blue { color: #2d8cf0; }
[data-theme="dark"] .tool-item:hover .blue { color: var(--accent, #2d8cf0); }
.tool-item .green { display: inline-flex; align-items: center; }
.tool-item .ivu-ic { display: inline-block; line-height: 1; }

/* 暂未接入的工具项：灰化但不隐藏（员工看得见"乐语有这一项"，只是本地点亮会说明） */
[data-theme="light"] .tool-item.leyu-tool-todo { color: #808695; }
[data-theme="light"] .tool-item.leyu-tool-todo .blue { color: #808695; }
[data-theme="light"] .tool-item.leyu-tool-todo .ivu-ic { filter: grayscale(1); opacity: .55; }
[data-theme="dark"] .tool-item.leyu-tool-todo { opacity: .55; }

/* 「已选 N 条」提示跟着工具条走 */
.leyu-checkedtip {
  margin-left: auto; padding: 2px 8px; font-size: 12px; border-radius: 3px;
}
[data-theme="light"] .leyu-checkedtip { background: #f0f7ff; color: #2b85e4; border: 1px solid #bcdcff; }
[data-theme="dark"] .leyu-checkedtip { background: var(--fill-2); color: var(--text-2); border: 1px solid var(--line); }

/* ---- 深色主题下的兜底（aurora 主题仍要能看） ---- */
[data-theme="dark"] .ivu-page { display: flex; align-items: center; padding: 13px 0 0; list-style: none; font-size: 12px; color: var(--text-2); }
[data-theme="dark"] .ivu-page > li {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 32px; height: 32px; margin-right: 4px;
  border: 1px solid var(--line); border-radius: 4px;
  background: var(--fill-1); color: var(--text-2); cursor: pointer;
}
[data-theme="dark"] .ivu-page > li > a { color: inherit; font-size: 12px; text-decoration: none; }
[data-theme="dark"] .ivu-page-item-active { background: var(--accent, #2d8cf0); border-color: transparent; }
[data-theme="dark"] .ivu-page-item-active > a { color: #fff; font-weight: 700; }
[data-theme="dark"] .ivu-page-disabled { opacity: .45; cursor: not-allowed; }
[data-theme="dark"] .ivu-page-options { margin-left: auto; display: flex; gap: 10px; align-items: center; }
[data-theme="dark"] .ivu-select-mini,
[data-theme="dark"] .ivu-page-options-elevator input {
  height: 32px; border: 1px solid var(--line); border-radius: 4px;
  background: var(--fill-1); color: var(--text-2); font-size: 12px;
}
[data-theme="dark"] .ivu-page-options-elevator input { width: 48px; padding: 0 6px; text-align: center; }
[data-theme="dark"] .row-link { color: #5cadff; font-size: 12px; cursor: pointer; margin: 0 5px; }
[data-theme="dark"] .leyu-morelink span { color: #5cadff; font-weight: 700; font-size: 14px; }
[data-theme="dark"] .leyu-filterbox:not(.tb-more-open) .leyu-fextra { display: none; }

/* ---- 14. 乐语式筛选区里的范围输入 ---- */
[data-theme="light"] .tb-range-inp {
  width: 130px;
  height: 27px;
  font-size: 12px;
  border-radius: 4px;
  border: 1px solid #dcdee2;
  background: #fff;
  color: #515a6e;
  padding: 0 8px;
}
[data-theme="light"] .tb-range-inp:focus {
  border-color: #57a3f3;
  box-shadow: 0 0 0 2px rgba(45, 140, 240, 0.2);
}
[data-theme="light"] .tb-range-sep { color: #808695; padding: 0 2px; font-size: 12px; }

/* 信息带（共 N 条…）在乐语里紧贴筛选区上方，单独一行窄条 */
[data-theme="light"] .card-head { margin-bottom: 6px; }
[data-theme="light"] .leyu-filterbox { padding-top: 4px; }
[data-theme="light"] .table-scroll { margin-top: 4px; }

/* ---- 15. 工具条图标与文字的对齐微调（乐语是图标略高、文字基线对齐）---- */
[data-theme="light"] .leyu-tool .leyu-tool-ic { margin-top: -3px; }
[data-theme="light"] .leyu-morebtn .ivu-ic { font-size: 15px; margin-top: -1px; }

/* ---- 16. 手机端：乐语式筛选区必须能收窄，否则横向溢出 ----
   ⚠️ 实测踩坑：`#/followups` 在 390px 宽下横向溢出 **10px**。
      真凶是 `.tb-range-inp { width:130px }` 写死了 —— 一行里两个日期框
      （130×2 + 分隔符）加上 100px 标签就撑爆了。
      修法：窄屏下让输入框可缩（flex + min-width），标签也收窄。
      乐语本身没有手机端（它是 PC 端 SaaS），所以这里不照搬乐语、
      而是用我们自己的手机适配规则——**保证不溢出**优先于像素一致。 */
@media (max-width: 860px) {
  .leyu-toolbar { height: auto; min-height: 37px; flex-wrap: wrap; gap: 0 12px; }
  .leyu-tool { height: 32px; font-size: 12px; }
  .leyu-tool .leyu-tool-ic { font-size: 17px; }
  .leyu-frow { flex-wrap: wrap; }
  .leyu-flabel { width: auto; min-width: 62px; max-width: 100px; font-size: 12.5px; }
  .leyu-fopts { gap: 0 4px; }
  .leyu-pill { font-size: 12.5px; height: 22px; padding: 3px 5px; }
  .tb-range-inp {
    width: auto;
    flex: 1 1 84px;
    min-width: 0;       /* 🚨 flex 子项默认 min-width:auto，不加这条不会真缩 */
    max-width: 130px;
  }
  [data-theme="light"] .leyu-fopts { max-height: none; overflow: visible; }
  [data-theme="light"] .leyu-frow { max-height: none; }
}

/* ---- 17. 药丸文字过长必须截断（手机端实测溢出真凶）----
   ⚠️ 踩坑记录：`#/followups` 在 390px 宽下横向溢出 **10px**。
      定位后真凶是**一颗 283px 宽的药丸** —— 镜像表某个筛选字段的取值是
      业务员留言那种长文本（实测「赵红--->于晓燕招商经理: 普…」），
      药丸 `white-space:nowrap` 会把整段撑开，直接把页面顶出视口。
      乐语不会遇到这个问题，因为它的筛选项都是「全部/我的/一星」这类**短枚举**；
      我们的镜像表字段取值不受控 ⇒ 必须自己兜住。
   修法：药丸限宽 + 溢出省略（鼠标悬停看全文，title 已在模板里带上）。 */
.leyu-pill {
  max-width: 148px;
  overflow: hidden;
  text-overflow: ellipsis;
  display: inline-block;
  line-height: 24px;
}
@media (max-width: 860px) {
  .leyu-pill { max-width: 118px; line-height: 22px; }
}
/* 桌面端也顺手限一下：183px 宽的筛选行里挤 12 颗药丸时同样会撑破 */
[data-theme="light"] .leyu-fopts { overflow-x: hidden; }

/* ============================================================================
   乐语 1:1 复刻层 · 第 6 部分 · 详情抽屉（Drawer）
   ----------------------------------------------------------------------------
   规格出处（勿凭感觉改）：data/.leyu-menu/drawer-spec.json
     · iView 原生：.ivu-drawer-header{padding:14px 16px;border-bottom:1px solid #e8eaec}
                   .ivu-drawer-body{padding:16px;height:calc(100% - 51px)}
                   .ivu-drawer-mask{background:rgba(55,55,55,.6)}
     · 客资详情：class="customer", styles:{padding:"0px 16px"},
                 header 是自定义 slot（H3 里「标题 【姓名】」，姓名带等级色），
                 头部下方 Tabs(size:small) 6 个页签，
                 页签之下又是一条 .tool-item 工具条（8 项），
                 字段行是 Row > Col(span6)+Col(span18)。
   ============================================================================ */

/* 抽屉宽度：乐语就 460 / 500 / 560 这几档，不是全屏也不是窄条 */
.drawer.leyu-drawer { width: min(560px, 96vw); }

/* —— 头部（照 iView：padding 14px 16px，底边 1px #e8eaec，标题 16px/500）—— */
.leyu-drawer-header {
  position: relative;
  padding: 14px 16px;
  border-bottom: 1px solid var(--line);
  line-height: 1;
  flex: 0 0 auto;
}
.leyu-drawer-title {
  display: inline-block;
  width: 100%;
  height: 20px;
  line-height: 20px;
  font-size: 16px;
  font-weight: 500;
  margin: 0;
  padding-right: 30px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
[data-theme="light"] .leyu-drawer-header { border-bottom-color: #e8eaec; }
[data-theme="light"] .leyu-drawer-title { color: #17233d; }

/* 关闭按钮：乐语是 31px 的 ios-close 字形，right:8px top:8px */
.leyu-drawer-close {
  position: absolute;
  right: 8px; top: 8px;
  font-size: 31px;
  line-height: 1;
  color: #999;
  cursor: pointer;
  transition: color 0.2s ease;
  user-select: none;
}
.leyu-drawer-close:hover { color: #444; }
[data-theme="dark"] .leyu-drawer-close { color: var(--text-3); }
[data-theme="dark"] .leyu-drawer-close:hover { color: var(--text); }

/* —— 页签（照 iView Tabs size="small"）—— */
.leyu-drawer-tabs {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  overflow-x: auto;
  border-bottom: 1px solid var(--line);
  padding: 0 4px;
  flex: 0 0 auto;
  scrollbar-width: none;
}
.leyu-drawer-tabs::-webkit-scrollbar { display: none; }
.leyu-dtab {
  position: relative;
  padding: 8px 10px;
  margin-right: 4px;
  font-size: 12px;
  line-height: 1.5;
  white-space: nowrap;
  cursor: pointer;
  color: var(--text-2);
  transition: color 0.2s ease;
}
.leyu-dtab:hover { color: #2d8cf0; }
.leyu-dtab.on { color: #2d8cf0; font-weight: 700; }
.leyu-dtab.on::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 2px;
  background: #2d8cf0;
  border-radius: 2px 2px 0 0;
}
[data-theme="light"] .leyu-drawer-tabs { border-bottom-color: #e8eaec; }
[data-theme="light"] .leyu-dtab { color: #515a6e; }

/* —— 内容区（iView body：padding 16px，overflow auto）—— */
.leyu-drawer-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 16px;
  font-size: 13px;
  line-height: 1.5;
  word-wrap: break-word;
}

/* —— ⭐ 页签之下的动作条（乐语 div.tools，8 项 .tool-item）—— */
.dt-tools {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0;
  margin: -4px 0 12px;
  padding-bottom: 8px;
  border-bottom: 1px dashed var(--line);
}
.dt-tools .tool-item { margin: 0 6px; }

/* —— 字段行（乐语 Row > Col span6 + Col span18，Row margin-bottom:8px）—— */
.dt-rows { display: block; }
.dt-row {
  display: flex;
  align-items: flex-start;
  margin-bottom: 8px;
  font-size: 13px;
}
.dt-col-6 { flex: 0 0 25%; max-width: 25%; }
.dt-col-18 { flex: 0 0 75%; max-width: 75%; word-break: break-all; }
.dt-lab { font-weight: 700; }
.dt-empty { color: var(--text-3); }
.dt-multiline { white-space: pre-wrap; word-break: break-word; }
.dt-rows .tag { margin: 0 4px 4px 0; }
[data-theme="light"] .dt-row { color: #515a6e; }
[data-theme="light"] .dt-lab { color: #17233d; }
[data-theme="light"] .dt-empty { color: #c5c8ce; }

/* 空页签提示 */
.dt-tabempty {
  padding: 60px 20px;
  text-align: center;
  font-size: 13px;
  line-height: 1.8;
  color: var(--text-3);
}
.dt-tabempty .big { font-size: 34px; margin-bottom: 10px; }

/* —— 底部（乐语 div.footer-page 一族）—— */
.leyu-drawer-foot {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 13px 16px;
  border-top: 1px solid var(--line);
  flex: 0 0 auto;
}
.leyu-drawer-foot .dt-footnote { font-size: 12px; color: var(--text-3); }
.leyu-drawer-foot .spacer { flex: 1 1 auto; }
[data-theme="light"] .leyu-drawer-foot { border-top-color: #e8eaec; }

@media (max-width: 860px) {
  .drawer.leyu-drawer { width: 100%; }
  .dt-col-6 { flex: 0 0 34%; max-width: 34%; }
  .dt-col-18 { flex: 0 0 66%; max-width: 66%; }
  .dt-tools .tool-item { margin: 0 4px; }
}

/* ============================================================================
   乐语 1:1 复刻层 · 第 7 部分 · 订单详情表单（Form + FormItem）
   ----------------------------------------------------------------------------
   规格出处：data/.leyu-menu/drawer-spec.json → 「订单详情」
   乐语原文（chunk-4ed8cb0e.js）：
     e("Drawer",{attrs:{title:"修改订单", width:"600px", "mask-closable":!1,
                         styles:{padding:"10px 0px 0px"}}},
       [ e("div",{staticClass:"scor-box"},
           [ e("Form",{staticClass:"orderForm", attrs:{"label-width":100}}, [...]) ]) ])
     · FormItem 的 label 形如「客户姓名 :」（末尾带空格 + 半角冒号）
     · label-width = 100px，标签左对齐
     · 输入控件宽 450px（订单备注/详细地址）/ 260px（金额类）
     · 金额类控件后缀「 元 」
   ============================================================================ */

.leyu-form { display: block; }
.leyu-formitem {
  display: flex;
  align-items: flex-start;
  margin-bottom: 10px;
  font-size: 13px;
  line-height: 1.6;
}
/* label-width: 100 —— 乐语就是 100px，别改 */
.leyu-formitem-label {
  flex: 0 0 100px;
  max-width: 100px;
  text-align: right;
  padding-right: 8px;
  color: var(--text-2);
  word-break: keep-all;
}
.leyu-formitem-ctl {
  flex: 1 1 auto;
  min-width: 0;
  word-break: break-word;
}
/* 输入类控件宽度（乐语 450px / 260px） */
.leyu-formitem-ctl .inp-wide { width: 450px; max-width: 100%; }
.leyu-formitem-ctl .inp-num { width: 260px; }

[data-theme="light"] .leyu-formitem-label { color: #515a6e; }
[data-theme="light"] .leyu-orderform .leyu-formitem-ctl { color: #17233d; }

/* 订单详情弹窗：乐语是 600px 宽的 Drawer，本地用 620 宽的 modal 承载（差 20px 是滚动条余量） */
.leyu-order-detail .modal-body { max-height: 72vh; overflow-y: auto; }

@media (max-width: 860px) {
  .leyu-formitem-label { flex: 0 0 78px; max-width: 78px; }
  .leyu-order-detail .leyu-formitem-ctl .inp-wide,
  .leyu-order-detail .leyu-formitem-ctl .inp-num { width: 100%; }
}

/* ============================================================================
   乐语 1:1 复刻层 · 第 8 部分 · 详情抽屉「族的差异」
   ----------------------------------------------------------------------------
   规格出处：data/.leyu-menu/drawer-spec.json → 「其它」段（全部扒源码，非猜测）
     售后详情  width 560  rootCls `return_details`  styles padding:0 0 0 4px  closable
     商机详情  width 460  rootCls `business_tabs`   closable:false
                字段行 div.row_box-detial > span.row_box-detial-label + span("：") + p.row_box-detial-p
     会员详情  width 960  rootCls `edit`            closable:false  底部 操作/分配/关闭
   ============================================================================ */

/* 商机族的字段行（三段式，不是 Row/Col 栅格） */
.row_box-detial {
  display: flex;
  align-items: flex-start;
  margin-bottom: 8px;
  font-size: 13px;
  line-height: 1.6;
}
.row_box-detial-label {
  flex: 0 0 auto;
  min-width: 72px;
  color: var(--text-2);
}
.row_box-detial-p {
  margin: 0;
  flex: 1 1 auto;
  min-width: 0;
  color: var(--text-1);
  word-break: break-word;
  white-space: pre-wrap;
}

/* 售后/订单商品行（乐语：一行一个商品 + 数量） */
.dt-prod { line-height: 1.7; }
.dt-prod-num { color: var(--text-3); }

/* 详情里的头像/缩略图 */
.dt-img {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
  vertical-align: middle;
  background: var(--fill-2);
}

/* 会员族底部是多个按钮（操作/分配/关闭），右侧并排 */
.leyu-family-edit .leyu-drawer-foot .ivu-btn + .ivu-btn { margin-left: 8px; }
.leyu-family-edit .leyu-drawer-body { padding: 16px 20px; }

/* 售后族：乐语 styles 是 padding:0 0 0 4px，左内边距只有 4px */
.leyu-family-return_details .leyu-drawer-body { padding-left: 4px; }

[data-theme="light"] .row_box-detial-label { color: #808695; }
[data-theme="light"] .row_box-detial-p { color: #17233d; }
[data-theme="light"] .dt-img { background: #f0f2f5; }

/* ============================================================================
   乐语 1:1 复刻层 · 第 9 部分 · 跟进记录（新增记录卡片 + 历史时间线）
   ----------------------------------------------------------------------------
   规格出处：data/.leyu-menu/drawer-spec.json → 「跟进记录」段（扒源码）
     Card「新增记录」> textarea(rows:6, maxlength:500,
       ph「内容最多500字(ctrl+v可快速粘贴上传图片)」)
     附加区：添加视频 / 添加附件(width:400, maxSize:100) / 关联联系人 / 关联商机
             / 添加下次回访时间(i-switch true:1 false:0)
     开关展开：textarea(rows:3, show-word-limit, ph「请输入日程内容」)
               + 优先级 RadioGroup(type:button, size:small)：无0 低1 中2 高3 全部9
               + 回访时间 DatePicker(宽160) + TimePicker(宽159, mar-left:80)
     提交按钮：Button(disabled=saveType, long:true, type:success)「添加跟进记录」
     Card「历史跟进记录」extra = Tooltip「刷新」> Icon(ios-sync, 20)
     空态：p{text-align:center}「暂无数据」+ Icon(ios-sad-outline, 18)
   ============================================================================ */

.leyu-card {
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--panel, transparent);
  overflow: hidden;
}
.leyu-card-head {
  position: relative;
  padding: 10px 16px;
  font-size: 14px;
  font-weight: 700;
  color: var(--text-1);
  border-bottom: 1px solid var(--line);
}
.leyu-card-extra {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  cursor: pointer;
  font-size: 20px;
  color: var(--text-3);
  line-height: 1;
}
.leyu-card-extra:hover { color: var(--brand, #2b85e4); }
.leyu-card-body { padding: 14px 16px 16px; }

/* 大文本域（乐语 rows:6） */
.leyu-ta {
  display: block;
  width: 100%;
  box-sizing: border-box;
  padding: 6px 8px;
  font-size: 13px;
  line-height: 1.6;
  font-family: inherit;
  color: var(--text-1);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 4px;
  resize: vertical;
}
.leyu-ta:focus { outline: none; border-color: #2b85e4; }
.leyu-ta::placeholder { color: var(--text-3); }
.leyu-paste { font-size: 12px; color: var(--text-3); margin: 4px 0 10px; }

/* 附加区：标签固定 90px 加粗（乐语原文宽 90px 粗体） */
.leyu-attach {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
  font-size: 13px;
  flex-wrap: wrap;
}
.leyu-attach-lab {
  flex: 0 0 90px;
  max-width: 90px;
  font-weight: 700;
  color: var(--text-1);
  text-align: right;
  word-break: keep-all;
}
.leyu-attach-tip { font-size: 12px; color: var(--text-3); }

/* 已选对象（oppo_box）：未选是灰字，已选带一个 ✕ 删除圈 */
.leyu-oppo { display: inline-flex; align-items: center; gap: 6px; min-width: 120px; }
.leyu-oppo-none { color: var(--text-3); font-size: 13px; }
.leyu-oppo-item { display: inline-flex; align-items: center; gap: 4px; font-size: 13px; }
.leyu-oppo-x { cursor: pointer; color: #ed4014; font-size: 15px; line-height: 1; }

/* i-switch（乐语 true:1 / false:0，宽 40 高 20 蓝底） */
.leyu-switch {
  display: inline-block;
  width: 40px;
  height: 20px;
  border-radius: 10px;
  background: #ccc;
  position: relative;
  cursor: pointer;
  transition: background .2s;
  vertical-align: middle;
}
.leyu-switch::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #fff;
  transition: left .2s;
}
.leyu-switch.on { background: #2d8cf0; }
.leyu-switch.on::after { left: 22px; }

/* 回访区（开关打开才显示） */
.leyu-visit {
  border-left: 2px solid var(--line);
  padding-left: 10px;
  margin: 4px 0 12px;
}

/* 优先级 RadioGroup(type:button, size:small) */
.leyu-radio-group { display: inline-flex; }
.leyu-radio-btn {
  display: inline-block;
  padding: 2px 12px;
  font-size: 12px;
  line-height: 20px;
  border: 1px solid var(--line);
  border-left-width: 0;
  cursor: pointer;
  color: var(--text-2);
  background: transparent;
  user-select: none;
}
.leyu-radio-btn:first-child { border-left-width: 1px; border-radius: 4px 0 0 4px; }
.leyu-radio-btn:last-child { border-radius: 0 4px 4px 0; }
.leyu-radio-btn.on { background: #2d8cf0; border-color: #2d8cf0; color: #fff; }

/* 回访日期/时间（乐语 160 / 159 宽） */
.leyu-date, .leyu-time {
  padding: 3px 6px;
  font-size: 13px;
  font-family: inherit;
  color: var(--text-1);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 4px;
}
.leyu-date { width: 160px; }
.leyu-time { width: 159px; margin-left: 80px; }

/* 提交按钮（long + success） */
.ivu-btn-long { display: block; width: 100%; margin-top: 12px; }
.ivu-btn-success {
  background: #19be6b;
  border-color: #19be6b;
  color: #fff;
}
.ivu-btn-success:hover { background: #47cb89; border-color: #47cb89; }

/* ── 历史跟进记录时间线（iView Timeline）── */
.leyu-timeline { position: relative; padding-left: 14px; }
.leyu-timeline::before {
  content: '';
  position: absolute;
  left: 3px;
  top: 6px;
  bottom: 6px;
  width: 2px;
  background: var(--line);
}
.tl-item2 { position: relative; padding-bottom: 14px; font-size: 13px; }
.tl-item2::before {
  content: '';
  position: absolute;
  left: -14px;
  top: 6px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #2d8cf0;
}
.tl-time { margin: 0 0 4px; color: var(--text-3); font-size: 12px; }
.tl-line1 { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.tl-who { font-weight: 700; color: var(--text-1); }
.tl-rel { color: var(--text-3); font-size: 12px; }
.tl-body {
  margin-top: 4px;
  color: var(--text-1);
  line-height: 1.7;
  white-space: pre-wrap;
  word-break: break-word;
}
.m-audio { color: #2b85e4; cursor: pointer; margin-right: 8px; }
.tl-img { max-width: 100px; max-height: 100px; border-radius: 4px; vertical-align: middle; margin-right: 6px; }
.tl-file { color: #2b85e4; margin-right: 8px; }

/* 空态：p 居中 + ios-sad-outline */
.tl-empty { text-align: center; padding: 20px 0; color: var(--text-3); }
.tl-empty .ivu-ic { font-size: 18px; }
.tl-empty p { margin: 6px 0 0; font-size: 13px; }

[data-theme="light"] .leyu-card { background: #fff; border-color: #dcdee2; }
[data-theme="light"] .leyu-card-head { color: #17233d; border-color: #e8eaec; }
[data-theme="light"] .leyu-ta { color: #17233d; border-color: #dcdee2; }
[data-theme="light"] .leyu-radio-btn { color: #515a6e; border-color: #dcdee2; }
[data-theme="light"] .tl-body { color: #17233d; }

@media (max-width: 860px) {
  .leyu-attach-lab { flex: 0 0 74px; max-width: 74px; font-size: 12.5px; }
  .leyu-date, .leyu-time { width: 100%; margin-left: 0; }
  .leyu-attach { gap: 6px; }
}

/* 自研页上的乐语工具条（订单台账页）：`.leyu-toolbar` 原本只在 [data-theme="light"]
   作用域里有样式，深色主题下会塌成裸块。这里补布局兜底。
   🚨 **只补布局，绝不覆盖 color** —— 老板要的是「颜色完全照搬乐语」，
      `.tool-item` 的字色（明色主题 rgb(23,35,61)）和 `.blue` 的字色（rgb(43,133,228)）
      都是扒源码定死的两个不同色，外加 20 个图标各自的专属色。
      一旦在这里写 color: var(--text-1) 就会把乐语原色顶掉
      （实测：--text-1 深色下是 rgb(15,26,46)、--accent 是 rgb(3,105,161)，
       而乐语原色是 rgb(23,35,61) / rgb(43,133,228)）⇒ 探针 3 项打红。
      `.tool-item` 自己的颜色规则在 §5 的 `[data-theme="light"] .tool-item` 里，
      深色主题靠它自己的 `[data-theme="dark"] .tool-item` 分支。 */
.leyu-toolcard { margin-bottom: 14px; }
.leyu-toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0 16px;
  min-height: 37px;
  background: transparent;
  border: none;
}
.leyu-toolbar .ivu-ic { display: inline-block; line-height: 1; }
.leyu-toolbar .tool-item .green { display: inline-flex; align-items: center; }
/* 「本地未接入」的灰化只在**明色主题**下生效（乐语原本没有这个态，是我们加的提示） */
[data-theme="light"] .leyu-toolbar .tool-item.leyu-tool-todo { color: #808695; }
[data-theme="light"] .leyu-toolbar .tool-item.leyu-tool-todo .blue { color: #808695; }

@media (max-width: 860px) {
  .leyu-toolbar { gap: 0 10px; }
  .leyu-toolbar .tool-item { margin: 0 2px; font-size: 12px; }
}

/* ============================================================================
   乐语 1:1 复刻层 · 第 10 部分 · 合并客户抽屉（870px，rootCls merge-customer）
   ---
   规格出处：data/.leyu-menu/drawer-spec.json → 其它.合并客户
     width 870px / 字段「名称：」「电话：」「数据主体」/ 底栏 取消(150) + 保存(150, primary)
   ============================================================================ */
.mc-row {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
  font-size: 13px;
  line-height: 1.6;
}
.mc-lab {
  flex: 0 0 90px;
  max-width: 90px;
  font-weight: 700;
  color: var(--text-1);
}
.mc-val { flex: 1 1 auto; min-width: 0; word-break: break-word; }
.mc-oppo { display: inline-flex; align-items: center; gap: 6px; }

.mc-sec {
  margin: 14px 0 8px;
  font-size: 13px;
  font-weight: 700;
  color: var(--text-1);
  border-bottom: 1px solid var(--line);
  padding-bottom: 6px;
}
.mc-list {
  max-height: 320px;
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: 4px;
}
.mc-opt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 7px 12px;
  font-size: 13px;
  cursor: pointer;
  border-bottom: 1px solid var(--line);
}
.mc-opt:last-child { border-bottom: none; }
.mc-opt:hover { background: var(--fill-2); }
.mc-opt.on { background: rgba(45, 140, 240, .14); }
.mc-opt.on .mc-opt-nm { color: #2d8cf0; font-weight: 700; }
.mc-opt-nm { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.mc-opt-ph { color: var(--text-3); font-size: 12.5px; white-space: nowrap; }

.mc-warn {
  margin-top: 12px;
  padding: 8px 10px;
  font-size: 12.5px;
  line-height: 1.7;
  color: #ff9900;
  background: rgba(255, 153, 0, .08);
  border-left: 3px solid #ff9900;
  border-radius: 2px;
}

[data-theme="light"] .mc-lab { color: #17233d; }
[data-theme="light"] .mc-opt:hover { background: #f8f8f9; }
[data-theme="light"] .mc-opt.on { background: #e8f2fe; }

@media (max-width: 860px) {
  .mc-lab { flex: 0 0 74px; max-width: 74px; }
  .leyu-family-merge-customer .leyu-drawer-foot .ivu-btn { width: auto !important; }
}

/* ============================================================
   第 11 部分 · B 档「空数据列表页」骨架（乐语素材/系统配置族）
   ------------------------------------------------------------
   乐语这类页面的骨架（真机实测 data/.leyu-menu/b-tier-pages.json 14 页）：
     ① 搜索行：**多个小输入框**（h:32 w:180）+ 蓝实心「查询」+ 白「重置」
        —— 注意与 A 档列表页的「一个大搜索框」形态不同，别混用
     ② 工具条：与 A 档同一套 .tool-item（绿色图标 + 蓝字），末尾恒有「收起」
     ③ 表格：表头 bg #f8f8f9 / 12px / bold / color #515a6e，行列高 48
     ④ 分页器：左侧「本页 N 条」，右侧「共 N 条 ‹ 1 › 20条/页 跳至 _ 页」
   ============================================================ */

.leyu-bsearch {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  padding: 0 0 12px;
}
.leyu-bsearch-item {
  display: inline-flex;
  align-items: center;
}
.leyu-bsearch-lab {
  font-size: 12px;
  color: #515a6e;
  white-space: nowrap;
}
/* 乐语：h:32 w:180，圆角 4，边框 #dcdee2 */
.leyu-bsearch-input {
  width: 180px;
  height: 32px;
  padding: 0 8px;
  font-size: 12px;
  color: #515a6e;
  background: #fff;
  border: 1px solid #dcdee2;
  border-radius: 4px;
}
.leyu-bsearch-input[disabled] { background: #f8f8f9; cursor: not-allowed; }
.leyu-btn-reset { margin-left: 0; }

/* 表格容器（乐语 .ivu-table 有 1px 外框，表头底色浅灰） */
.leyu-btable-wrap {
  border: 1px solid #e8eaec;
  border-radius: 2px;
  overflow-x: auto;
}
.leyu-btable {
  width: 100%;
  min-width: 720px;
  border-collapse: collapse;
  font-size: 12px;
}
.leyu-btable thead th {
  height: 36px;
  padding: 0 12px;
  font-size: 12px;
  font-weight: 700;
  color: #515a6e;
  text-align: left;
  white-space: nowrap;
  background: #f8f8f9;
  border-bottom: 1px solid #e8eaec;
}
.leyu-btable .th-check { width: 60px; text-align: center; }
.leyu-btable .th-ops { width: 160px; text-align: center; }
.leyu-bempty { padding: 0; }
.leyu-bempty-in {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 60px 0;
  color: #c5c8ce;
}
.leyu-bempty-in .ivu-ic { font-size: 40px; color: #c5c8ce; }
.leyu-bempty-in p { margin: 0; font-size: 13px; color: #c5c8ce; }

/* 分页器：左「本页 N 条」右控件组，与乐语 .ivu-page 排布一致 */
.leyu-bpager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 2px 2px;
  font-size: 12px;
  color: #515a6e;
}
.leyu-bpager-right { display: inline-flex; align-items: center; gap: 6px; }
.leyu-bpager-right em { font-style: normal; margin-right: 4px; }
.leyu-bpg {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 30px;
  height: 30px;
  padding: 0 6px;
  color: #515a6e;
  background: #fff;
  border: 1px solid #dcdee2;
  border-radius: 4px;
  cursor: pointer;
  user-select: none;
}
.leyu-bpg.on { color: #fff; background: #2d8cf0; border-color: #2d8cf0; }
.leyu-bpg.disabled { color: #c5c8ce; cursor: not-allowed; }
.leyu-bsize {
  padding: 0 8px;
  height: 30px;
  line-height: 30px;
  border: 1px solid #dcdee2;
  border-radius: 4px;
}
.leyu-bjump-in {
  width: 40px;
  height: 26px;
  margin: 0 4px;
  text-align: center;
  font-size: 12px;
  border: 1px solid #dcdee2;
  border-radius: 4px;
}

/* 深色主题下：这套骨架的底色必须翻成深色，否则白底刺眼 */
[data-theme="dark"] .leyu-bsearch-input,
[data-theme="dark"] .leyu-btable-wrap,
[data-theme="dark"] .leyu-btable thead th,
[data-theme="dark"] .leyu-bpg,
[data-theme="dark"] .leyu-bsize,
[data-theme="dark"] .leyu-bjump-in { background: var(--fill-1); }
[data-theme="dark"] .leyu-btable thead th { border-bottom-color: var(--line-1); }
[data-theme="dark"] .leyu-bsearch-input[disabled] { background: var(--fill-2); }
[data-theme="dark"] .leyu-bpg.on { background: #2d8cf0; border-color: #2d8cf0; color: #fff; }

/* 🚨 深色下**文字色也要翻** —— 只翻背景不翻字会出现「深底 + 深灰字」= 对比度 2.3:1（实测踩过）。
   乐语的 #515a6e / #c5c8ce 是给白底设计的，深色主题下必须换成主题变量。
   这几条是 verify-theme-contrast.mjs 逼出来的，别删。 */
[data-theme="dark"] .leyu-bsearch-lab,
[data-theme="dark"] .leyu-btable thead th,
[data-theme="dark"] .leyu-bpager,
[data-theme="dark"] .leyu-bpager em,
[data-theme="dark"] .leyu-bpager-left,
[data-theme="dark"] .leyu-bsize,
[data-theme="dark"] .leyu-bjump { color: var(--text-2); }
[data-theme="dark"] .leyu-bempty-in p { color: var(--text-3); }
[data-theme="dark"] .leyu-bpg { color: var(--text-2); }
[data-theme="dark"] .leyu-bpg.on { color: #fff; }

@media (max-width: 860px) {
  .leyu-bsearch-input { width: 130px; }
  .leyu-bpager { flex-direction: column; align-items: flex-start; gap: 8px; }
}

/* ============================================================
   第 12 部分 · B 档「配置表单页」骨架（乐语系统配置族）
   ------------------------------------------------------------
   乐语这 13 页没有表格，是「保存配置」表单：
     · 顶部兄弟页签条（同组各页做成 tab）
     · 中间「标签：控件」行（label 左对齐）
     · 底部 **150px 宽** 的「刷新」(白) +「保存」(主色) 一对按钮
   ============================================================ */
.leyu-cfgcard { padding: 0; }
.leyu-cfgtabs {
  display: flex;
  align-items: center;
  gap: 2px;
  height: 45px;
  padding: 0 8px;
  border-bottom: 1px solid #e8eaec;
}
.leyu-cfgtab {
  display: inline-flex;
  align-items: center;
  height: 45px;
  padding: 0 16px;
  font-size: 13px;
  color: #515a6e;
  border-bottom: 2px solid transparent;
  cursor: default;
}
.leyu-cfgtab.on { color: #2d8cf0; border-bottom-color: #2d8cf0; }
.leyu-cfgbody { padding: 24px 24px 8px; }
.leyu-cfgrow {
  display: flex;
  align-items: center;
  margin-bottom: 18px;
  font-size: 13px;
}
.leyu-cfglab {
  flex: 0 0 140px;
  max-width: 140px;
  text-align: right;
  padding-right: 12px;
  color: #515a6e;
}
.leyu-cfgctl { flex: 1 1 auto; }
.leyu-cfginput {
  width: 220px;
  height: 32px;
  padding: 0 8px;
  font-size: 12px;
  color: #515a6e;
  background: #f8f8f9;
  border: 1px solid #dcdee2;
  border-radius: 4px;
}
.leyu-cfgtip {
  margin: 10px 0 0 152px;
  padding: 10px 12px;
  font-size: 12.5px;
  line-height: 1.8;
  color: #808695;
  background: #f8f8f9;
  border-left: 3px solid #dcdee2;
  border-radius: 2px;
}
.leyu-cfgfoot {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 16px 0 24px;
  border-top: 1px solid #e8eaec;
}
.leyu-cfgbtn { width: 150px !important; }

[data-theme="dark"] .leyu-cfgtabs { border-bottom-color: var(--line-1); }
[data-theme="dark"] .leyu-cfgtab { color: var(--text-2); }
[data-theme="dark"] .leyu-cfgtab.on { color: #2d8cf0; }
[data-theme="dark"] .leyu-cfglab { color: var(--text-2); }
[data-theme="dark"] .leyu-cfginput,
[data-theme="dark"] .leyu-cfgtip { background: var(--fill-1); border-color: var(--line-1); }
[data-theme="dark"] .leyu-cfgfoot { border-top-color: var(--line-1); }

@media (max-width: 860px) {
  .leyu-cfglab { flex: 0 0 96px; max-width: 96px; }
  .leyu-cfgtip { margin-left: 0; }
  .leyu-cfgbtn { width: auto !important; }
}
