/* ============================================================================
   星呼 · 电销 CRM —— 云端界面样式（亮色 · 企业级 CRM 通行色调）
   ----------------------------------------------------------------------------
   设计系统只有一套：颜色、间距、字号、圆角、断点全部在下面 :root 与注释里定义，
   组件区不许出现"随手写"的色值。

   ★ 为什么是亮色（2026-09-24 定的，别凭感觉改回深色）
     电销 CRM 是坐席每天盯 8 小时的录入型工具，不是展示型大屏。市面上的同类产品
     一律用亮色，配色高度一致，我们照抄这套共识即可：
       · Ant Design v5（国内企业级 UI 的事实标准）
         主色 #1677FF / 页面底 #F5F5F5 / 卡片 #FFFFFF / 边框 #D9D9D9
         文字按不透明度分级 rgba(0,0,0,.88 / .65 / .45 / .25)
       · Element Plus：主色 #409EFF
       · Salesforce Lightning：#0176D3 亮色界面；HubSpot：亮色 + 橙
       · 纷享销客 / 销售易 / 销氪：亮色 + 蓝主色
     共同点就三条：**浅灰画布 + 纯白卡片 + 一个饱和蓝做强调**。深色只留给
     「数据大屏」那种挂墙展示的场景（.screen，那个确实是深色更对）。

   ★ 兼容约束（改这个文件前必读）：
     app.js 里有 52 处内联样式写着 var(--muted) / var(--red) / var(--green) 之类，
     所以**旧变量名一个都不能删**，只能改它们的值。

   ★ 断点（只有四档，别再加中间档）：
     ≥ 900px   左侧固定导航栏
     < 900px   导航收成抽屉（顶栏出现汉堡按钮）
     < 768px   手机：边距收紧、栅格降列、表格横向滚动、弹窗/抽屉铺满
     < 480px   超窄：按钮整行、键盘收紧
   ============================================================================ */

:root {
  /* ---------- 底色与面板 ---------- */
  --bg: #F5F7FA;                              /* 页面底：极浅冷灰（Ant #F5F5F5 的微冷变体） */
  --card: #FFFFFF;                            /* 卡片/顶栏/侧栏：纯白 */
  --card-solid: #FFFFFF;                      /* 需要不透明时的面板（吸顶表头等） */
  --sidebar: #FFFFFF;
  --sidebar-active: #E6F4FF;                  /* 侧栏选中底：主色浅底 */
  --border: #E5E7EB;                          /* 细线、卡片描边 */
  --border-strong: #D9D9D9;                   /* 输入框描边、需要看得见的边 */

  /* ---------- 文字：按不透明度分级（市面通行做法，别用四个不同的灰） ---------- */
  --text: #1F2329;                            /* ≈ rgba(0,0,0,.88) 正文与标题 */
  --muted: #5A6270;                           /* ≈ .65 次要信息 */
  --faint: #8A919E;                           /* ≈ .45 占位、辅助 */

  /* ---------- 强调与语义色 ---------- */
  --primary: #1677FF;                         /* 唯一强调色：蓝（Ant Design 主色） */
  --primary-hover: #4096FF;
  --primary-soft: #E6F4FF;                    /* 主色浅底（选中态、标签） */
  --primary-ink: #FFFFFF;                     /* 压在主色实底上的文字色 */
  --green: #16A34A;                           /* 成功/接通 */
  --green-soft: #ECFDF3;
  --red: #DC2626;                             /* 失败/挂断 */
  --red-soft: #FEF2F2;
  --orange: #D97706;                          /* 待办/未接通（比 #FAAD14 深，当文字才看得清） */
  --orange-soft: #FFF7ED;
  --blue: #4F46E5;                            /* 中性分类徽章（紫，和主蓝区分开） */
  --blue-soft: #EEF2FF;

  /* ---------- 形状与阴影 ---------- */
  --radius: 10px;                             /* 卡片 */
  --radius-sm: 6px;                           /* 按钮/输入框（Ant 基准 6px） */
  --shadow: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 6px -1px rgba(0, 0, 0, .03), 0 2px 4px rgba(0, 0, 0, .02);
  --shadow-lg: 0 6px 16px rgba(0, 0, 0, .08), 0 3px 6px -4px rgba(0, 0, 0, .12);
  --ring: 0 0 0 2px rgba(22, 119, 255, .16);  /* 聚焦光圈 */

  /* ---------- 间距刻度（4 的倍数，别写 5/7/9/13）---------- */
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 20px; --sp-6: 24px; --sp-8: 32px;

  /* ---------- 布局尺寸（窄屏会覆盖）---------- */
  --sidebar-w: 216px;
  --topbar-h: 56px;
  --content-max: 1680px;
  --content-pad: 20px;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
  background: var(--bg);
  color: var(--text);
  font-size: 14px;
  line-height: 1.6;                 /* 中文行高给足，1.0 会挤成一坨 */
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
}
a { color: var(--primary); text-decoration: none; }
a:hover { color: var(--primary-hover); }
button { font-family: inherit; }
/* 数字一律等宽对齐：表格里的数字列不对齐是最容易被看出来的廉价感 */
.num, .stat .value, .cb-timer, .dial-input, .dialer-num .phone, .pagination, .scr-tb td {
  font-variant-numeric: tabular-nums;
}
.mono, code {
  font-family: ui-monospace, SFMono-Regular, Consolas, "Courier New", monospace;
}

/* ============================================================================
   登录页
   ============================================================================ */
.login-wrap {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: var(--sp-6) var(--sp-4);
  background:
    radial-gradient(760px 420px at 50% -12%, rgba(22, 119, 255, .10) 0%, transparent 60%),
    var(--bg);
}
.login-card {
  width: 100%; max-width: 400px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 14px; padding: 36px 32px 28px;
  box-shadow: var(--shadow-lg);
}
.login-brand { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-1); }
.logo-mark {
  width: 42px; height: 42px; border-radius: 10px; flex-shrink: 0;
  background: linear-gradient(135deg, #1677FF, #4096FF);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 19px;
  box-shadow: 0 2px 8px rgba(22, 119, 255, .28);
}
.login-brand h1 { font-size: 20px; letter-spacing: .3px; color: var(--text); }
.login-sub { color: var(--muted); margin-bottom: var(--sp-6); font-size: 13px; }
.login-tip {
  margin-top: var(--sp-5); padding: var(--sp-3);
  background: var(--primary-soft); border: 1px solid #BAE0FF;
  border-radius: var(--radius-sm); color: #0958D9; font-size: 12.5px; line-height: 1.75;
}
.login-tip b { cursor: pointer; color: var(--primary); }

/* ============================================================================
   布局骨架
   ============================================================================ */
.layout { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--sidebar-w); flex-shrink: 0;
  background: var(--sidebar);
  border-right: 1px solid var(--border);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh;
}
.sidebar .brand {
  display: flex; align-items: center; gap: 10px;
  padding: var(--sp-4);
  border-bottom: 1px solid var(--border);
}
.sidebar .brand .logo-mark { width: 30px; height: 30px; font-size: 14px; border-radius: 8px; box-shadow: none; }
.sidebar .brand b { font-size: 15px; letter-spacing: .3px; white-space: nowrap; color: var(--text); }
.sidebar nav { flex: 1; padding: var(--sp-3) var(--sp-2); overflow-y: auto; }
.nav-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px; border-radius: var(--radius-sm);
  color: var(--muted); cursor: pointer; margin-bottom: 2px;
  font-size: 13.5px; user-select: none;
  transition: background .14s, color .14s;
}
.nav-item:hover { color: var(--text); background: #F2F4F7; }
/* 选中态：主色浅底 + 主色文字 + 左侧一根指示条 */
.nav-item.active {
  color: var(--primary); background: var(--sidebar-active); font-weight: 600;
  position: relative;
}
.nav-item.active::before {
  content: ""; position: absolute; left: -8px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 18px; border-radius: 0 3px 3px 0; background: var(--primary);
}
.nav-item .ico { width: 18px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.sidebar .user-box {
  padding: var(--sp-3); border-top: 1px solid var(--border);
  display: flex; align-items: center; gap: 10px;
}
.avatar {
  width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0;
  background: linear-gradient(135deg, #1677FF, #4096FF);
  color: #fff; font-weight: 600;
  display: flex; align-items: center; justify-content: center; font-size: 13px;
}
.sidebar .user-box .meta { flex: 1; min-width: 0; }
.sidebar .user-box .name { color: var(--text); font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar .user-box .role { font-size: 11.5px; color: var(--faint); }
.sidebar .user-box .logout { color: var(--faint); cursor: pointer; font-size: 12px; flex-shrink: 0; }
.sidebar .user-box .logout:hover { color: var(--red); }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
  height: var(--topbar-h); flex-shrink: 0;
  background: var(--card);
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 0 var(--content-pad);
  position: sticky; top: 0; z-index: 40;
}
.topbar h2 { font-size: 16px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar .spacer { flex: 1; }
.topbar .date { color: var(--faint); font-size: 12.5px; white-space: nowrap; }
/* 顶栏里的手机连接状态。文案可能很长（"手机未连接 · 打开星呼助手并保持后台运行"），
   窄屏上要能截断，不能把顶栏撑破。 */
.phone-chip { display: flex; align-items: center; min-width: 0; }
.phone-chip .badge { max-width: 42vw; overflow: hidden; text-overflow: ellipsis; }

/* 汉堡按钮：只在窄屏出现（见断点区） */
.nav-toggle {
  display: none; align-items: center; justify-content: center;
  width: 34px; height: 34px; flex-shrink: 0;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--card); color: var(--text);
  cursor: pointer; padding: 0;
}
.nav-toggle:hover { border-color: var(--primary); color: var(--primary); }
.nav-toggle svg { display: block; }
/* 抽屉遮罩：只在窄屏且展开时可见 */
.nav-scrim {
  display: none; position: fixed; inset: 0; z-index: 110;
  background: rgba(0, 0, 0, .35);
}

.content {
  padding: var(--content-pad) var(--content-pad) var(--sp-8);
  max-width: var(--content-max); width: 100%;
}

/* ============================================================================
   通用组件
   ============================================================================ */
.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.card-pad { padding: var(--sp-5); }
/* 卡片标题：常规字重加粗即可，不搞装饰（市面 CRM 都这么处理） */
.card h3 {
  font-size: 14.5px; font-weight: 600; margin-bottom: var(--sp-4);
  color: var(--text); line-height: 1.4;
}
.grid { display: grid; gap: var(--sp-4); }
/* 栅格/弹性子项默认 min-width:auto —— 里面放个 input 或长数字就能把整列顶宽、
   在手机上撑出横向滚动条。统一允许收缩，内容该截断的截断、该滚的滚。 */
.grid > *, .stat-row > *, .dialer > *, .form-row > *, .toolbar > * { min-width: 0; }
/* 栅格变体：原来这些是写在 app.js 的内联 style 里的（style="grid-template-columns:1fr 1fr"），
   窄屏不会折行 —— 手机上一栏只剩几十像素。改成类，交给下面的断点统一降列。 */
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-split { grid-template-columns: 1.4fr minmax(0, 1fr); }
.grid-cards { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }
.stat-row.cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.stat-row.cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }

/* 统计卡：数值是屏幕上最大的东西 */
.stat-row { grid-template-columns: repeat(5, minmax(0, 1fr)); margin-bottom: var(--sp-4); }
.stat { padding: var(--sp-4) var(--sp-5); }
.stat .label { color: var(--muted); font-size: 12.5px; margin-bottom: 6px; }
.stat .value { font-size: clamp(20px, 1.7vw, 26px); font-weight: 700; letter-spacing: -.2px; line-height: 1.2; color: var(--text); }
.stat .unit { font-size: 12px; color: var(--muted); font-weight: 400; margin-left: 4px; }
.stat .accent { color: var(--primary); }

.toolbar { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-3); flex-wrap: wrap; }
.tabs {
  display: inline-flex; background: #F2F4F7;
  border-radius: var(--radius-sm); padding: 3px;
}
.tab {
  padding: 5px 14px; border-radius: 4px; cursor: pointer;
  font-size: 13px; color: var(--muted); user-select: none; white-space: nowrap;
  transition: background .14s, color .14s;
}
.tab:hover { color: var(--text); }
.tab.active { background: var(--card); color: var(--text); font-weight: 600; box-shadow: 0 1px 3px rgba(0, 0, 0, .08); }

/* ---------- 按钮：三种变体，不再多 ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  border: 1px solid var(--border-strong); background: var(--card);
  color: var(--text); border-radius: var(--radius-sm);
  padding: 6px 14px; font-size: 13px; cursor: pointer; user-select: none;
  white-space: nowrap; min-height: 32px;
  transition: background .14s, border-color .14s, color .14s;
}
.btn:hover { border-color: var(--primary); color: var(--primary); }
.btn:focus-visible { outline: none; box-shadow: var(--ring); }
.btn.primary { background: var(--primary); border-color: var(--primary); color: #fff; font-weight: 500; }
.btn.primary:hover { background: var(--primary-hover); border-color: var(--primary-hover); color: #fff; }
.btn.danger { color: var(--red); border-color: #FCA5A5; background: var(--card); }
.btn.danger:hover { background: var(--red-soft); border-color: var(--red); color: var(--red); }
.btn.sm { padding: 3px 10px; font-size: 12px; border-radius: 5px; min-height: 26px; }
.btn.lg { padding: 9px 22px; font-size: 14.5px; border-radius: 8px; min-height: 40px; }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn:disabled:hover { border-color: var(--border-strong); color: var(--text); }
.btn.link { border: none; background: none; color: var(--primary); padding: 4px 6px; min-height: 0; }
.btn.link:hover { background: none; color: var(--primary-hover); text-decoration: underline; }

/* ---------- 表单 ---------- */
.input, select.input, textarea.input {
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  padding: 6px 11px; font-size: 13px; font-family: inherit;
  background: var(--card); color: var(--text);
  outline: none; min-width: 0; min-height: 32px;
  transition: border-color .14s, box-shadow .14s;
}
.input::placeholder { color: var(--faint); }
.input:hover { border-color: var(--primary-hover); }
.input:focus { border-color: var(--primary); box-shadow: var(--ring); }
select.input option { background: var(--card); color: var(--text); }
textarea.input { resize: vertical; }
.field { margin-bottom: var(--sp-3); }
.field label { display: block; font-size: 12.5px; color: var(--muted); margin-bottom: 5px; }
.field .input { width: 100%; }
.form-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--sp-3); }

/* ---------- 表格 ---------- */
.tb-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.tb { width: 100%; border-collapse: collapse; font-size: 13px; }
.tb th {
  text-align: left; font-weight: 500; color: var(--muted); font-size: 12.5px;
  padding: 10px 14px; border-bottom: 1px solid var(--border);
  background: #FAFBFC; white-space: nowrap;
}
.tb td { padding: 11px 14px; border-bottom: 1px solid #F0F2F5; vertical-align: middle; }
/* 窄屏时列一多，浏览器会把中文挤成一列一个字（"系统管理员"竖着排）。
   所以主表列不逐字换行、放不下就让表格自己横向滚动；
   抽屉里的 mini-table 列少，保持原来的自动换行。 */
.tb:not(.mini-table) td { white-space: nowrap; }
.tb-wrap > .tb { min-width: 720px; }
.tb-wrap.wide > .tb { min-width: 1060px; }
.cut { display: inline-block; max-width: 210px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; }
.tb tr:last-child td { border-bottom: none; }
.tb tbody tr:hover { background: #F7F9FC; }
.tb .actions { white-space: nowrap; text-align: right; }
.mini-table td { padding: 7px 10px !important; font-size: 12.5px; }
.mini-table th { padding: 7px 10px; font-size: 12px; background: transparent; }
/* 横向滚动时给一个"右边还有内容"的提示：右缘渐隐 */
.tb-wrap.scrollable { position: relative; }
.tb-wrap.scrollable::after {
  content: ""; position: absolute; top: 0; right: 0; bottom: 0; width: 24px; pointer-events: none;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .9));
}

/* ---------- 徽章 ---------- */
.badge {
  display: inline-block; padding: 1px 9px; border-radius: 999px;
  font-size: 11.5px; font-weight: 500; white-space: nowrap;
  border: 1px solid transparent; line-height: 1.7;
}
.badge.gray { background: #F2F4F7; color: var(--muted); border-color: #E5E7EB; }
.badge.blue { background: var(--blue-soft); color: var(--blue); border-color: #C7D2FE; }
.badge.green { background: var(--green-soft); color: var(--green); border-color: #A7F3D0; }
.badge.red { background: var(--red-soft); color: var(--red); border-color: #FECACA; }
.badge.orange { background: var(--orange-soft); color: var(--orange); border-color: #FED7AA; }
.badge.indigo { background: var(--primary-soft); color: #0958D9; border-color: #BAE0FF; }

/* 拨打过的换一种颜色：绿=打通过，橙=打过没接通，无色=还没打过。
   颜色之外还带文字（未接通 / 未拨打），不只靠颜色区分。 */
.dialed-yes { color: var(--green); font-weight: 600; }
.dialed-try { color: var(--orange); font-weight: 600; }
.dialed-none { color: var(--faint); }

.pagination {
  display: flex; align-items: center; gap: var(--sp-2); justify-content: flex-end;
  padding: var(--sp-3) var(--sp-4); color: var(--muted); font-size: 12.5px; flex-wrap: wrap;
}
.pagination .btn { padding: 3px 10px; }
/* 空状态：绝不留一张什么都没有的表格 —— 那是"没做完"最明显的信号 */
.empty { text-align: center; color: var(--muted); padding: 46px var(--sp-4); font-size: 13px; }
.empty .big { font-size: 32px; margin-bottom: var(--sp-2); opacity: .35; }

/* ============================================================================
   弹窗 / 抽屉 / 提示
   ============================================================================ */
.overlay {
  position: fixed; inset: 0; background: rgba(0, 0, 0, .35); z-index: 100;
  display: flex; align-items: flex-start; justify-content: center;
  padding: 8vh 16px 16px;
}
.modal {
  background: var(--card);
  border-radius: 12px; width: 480px; max-width: 100%; max-height: 82vh; overflow: auto;
  box-shadow: 0 12px 40px rgba(0, 0, 0, .16); animation: pop .16s ease;
}
.modal.wide { width: 660px; }
@keyframes pop { from { transform: translateY(8px); opacity: 0; } }
.modal .m-head {
  display: flex; align-items: center; padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 2;
  background: var(--card);
}
.modal .m-head b { font-size: 15px; }
.modal .m-close { margin-left: auto; cursor: pointer; color: var(--faint); font-size: 20px; line-height: 1; padding: 0 4px; }
.modal .m-close:hover { color: var(--text); }
.modal .m-body { padding: var(--sp-5); }
.modal .m-foot {
  padding: var(--sp-3) var(--sp-5); border-top: 1px solid var(--border);
  display: flex; justify-content: flex-end; gap: var(--sp-2);
  position: sticky; bottom: 0; background: var(--card);
}

.drawer-overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, .35); z-index: 90; }
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: 560px; max-width: 94vw; z-index: 95;
  background: var(--card); border-left: 1px solid var(--border);
  box-shadow: -6px 0 24px rgba(0, 0, 0, .1);
  display: flex; flex-direction: column; animation: slide .18s ease;
}
@keyframes slide { from { transform: translateX(30px); opacity: .4; } }
.drawer .d-head {
  padding: var(--sp-4) var(--sp-5); border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: var(--sp-3); flex-shrink: 0;
}
.drawer .d-head b { font-size: 15.5px; }
.drawer .d-body { flex: 1; overflow-y: auto; padding: var(--sp-5); }
.drawer .d-close { margin-left: auto; cursor: pointer; color: var(--faint); font-size: 22px; line-height: 1; padding: 0 4px; }
.drawer .d-close:hover { color: var(--text); }

#toast-root {
  position: fixed; top: 18px; left: 50%; transform: translateX(-50%); z-index: 300;
  display: flex; flex-direction: column; gap: var(--sp-2); align-items: center;
  pointer-events: none; width: max-content; max-width: 92vw;
}
.toast {
  background: var(--card); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 8px 16px; font-size: 13px; box-shadow: var(--shadow-lg);
  animation: pop .18s ease; max-width: 92vw;
}
.toast.err { background: var(--red-soft); border-color: #FECACA; color: #B91C1C; }
.toast.ok { background: var(--green-soft); border-color: #A7F3D0; color: #15803D; }

/* ============================================================================
   呼叫条（通话中常驻右下角）
   ============================================================================ */
#callbar { position: fixed; right: 24px; bottom: 24px; z-index: 200; width: 300px; max-width: calc(100vw - 32px); }
.callbar {
  background: var(--card); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: var(--shadow-lg); overflow: hidden;
}
.callbar .cb-top { padding: var(--sp-3) var(--sp-4) 10px; display: flex; align-items: center; gap: 10px; }
.callbar .cb-num { font-size: 16.5px; font-weight: 700; letter-spacing: .3px; }
.callbar .cb-state { font-size: 12px; color: var(--muted); }
.callbar .cb-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--orange); animation: blink 1s infinite; flex-shrink: 0; }
.callbar.talking .cb-dot { background: var(--green); }
@keyframes blink { 50% { opacity: .25; } }
.callbar .cb-timer { font-variant-numeric: tabular-nums; color: var(--primary); font-weight: 600; margin-left: auto; }
.callbar .cb-actions { display: flex; gap: var(--sp-2); padding: 0 var(--sp-4) var(--sp-3); }
.callbar .cb-actions .btn { flex: 1; }
.pulse { box-shadow: 0 0 0 0 rgba(22, 163, 74, .35); animation: pulse 1.6s infinite; }
@keyframes pulse { to { box-shadow: 0 0 0 12px rgba(22, 163, 74, 0); } }

/* ============================================================================
   拨号台
   ============================================================================ */
.dialer { display: grid; grid-template-columns: 360px minmax(0, 1fr); gap: var(--sp-4); align-items: start; }
/* 工作台右栏：当前通话在上、今日拨打在下。今日拨打自己撑满剩余高度，不再写死条数。 */
.dl-right { display: flex; flex-direction: column; gap: var(--sp-4); min-width: 0; }
.dialer-num { text-align: center; padding: var(--sp-6) var(--sp-5) var(--sp-5); }
/* 左栏"按名单逐通外呼"里的号码卡：不要把 padding 再叠一层 */
.dialer-num.dialer-inline { padding: 0; margin-bottom: 4px; }
.dialer-num.dialer-inline .empty { padding: 18px 8px; }
.dialer-num .phone {
  font-size: clamp(24px, 2.4vw, 30px); font-weight: 800; letter-spacing: 1px;
  margin: 6px 0 2px; word-break: break-all;
}
.dialer-num .hint { color: var(--muted); font-size: 12.5px; }
.dialer-btns { display: flex; gap: var(--sp-2); justify-content: center; margin-top: var(--sp-4); flex-wrap: wrap; }
.dialer-info h4 { font-size: 13px; color: var(--muted); margin: var(--sp-4) 0 var(--sp-2); font-weight: 500; }
.dial-input-row { display: flex; gap: var(--sp-2); margin: var(--sp-3) 0; }
.dial-input-row > * { min-width: 0; }
/* ---------- 当前通话 ---------- */
.cur-call { min-height: 196px; }
.cur-call .cc-head { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.cur-call .cc-timer { font-variant-numeric: tabular-nums; font-size: 19px; font-weight: 700; color: var(--primary); }
.cur-call .cc-idle { color: var(--muted); font-size: 13px; line-height: 1.9; }
.cur-call .cc-busy { color: var(--orange); }
.cur-call .cc-kv { grid-template-columns: 96px minmax(0, 1fr); }
.cur-call .cc-num { font-size: 17px; font-weight: 700; letter-spacing: .5px; }
.cur-call .cc-actions { display: flex; gap: var(--sp-2); margin-top: var(--sp-4); }
.cur-call .cc-more { margin-top: var(--sp-3); border-top: 1px solid var(--border); padding-top: 10px; }
.cur-call .cc-more summary { color: var(--muted); font-size: 12.5px; cursor: pointer; }
/* ---------- 今日拨打 ---------- */
.today-calls { display: flex; flex-direction: column; padding: var(--sp-4) var(--sp-4) var(--sp-3); }
.today-calls .tc-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.today-calls .tc-sub { color: var(--muted); font-size: 12.5px; }
/* 固定可用高度 + 滚动：高度跟着视口走，换个显示器不会只剩一半能用 */
.today-calls .tc-scroll { overflow: auto; height: clamp(300px, calc(100vh - 430px), 780px); margin: 0 calc(-1 * var(--sp-2)); }
.today-calls .tc-foot { padding-top: 10px; display: flex; align-items: center; gap: 10px; font-size: 12.5px; }
.today-calls .tc-tb { min-width: 660px; }
.today-calls .tc-tb thead th {
  position: sticky; top: 0; z-index: 2; background: var(--card-solid);
  box-shadow: inset 0 -1px 0 var(--border);
}
.today-calls .tc-tb td, .today-calls .tc-tb th { white-space: nowrap; padding: 7px 9px; font-size: 13px; }
/* 客户名限宽省略：把宽度让给「外呼/接听时长」和「跟进」按钮，主操作不能被挤出可视区 */
.today-calls .tc-tb td:nth-child(2) .cut { max-width: 170px; }
.today-calls .tc-tb tr.tc-todo td { background: var(--orange-soft); }
/* 工作台在 1440 及以下时收起「公司」列（数据还在，展开靠 title）——见 .tc-company */
@media (max-width: 1500px) {
  .today-calls .tc-company { display: none; }
}
/* ---------- 通话记录：时长筛选条 ---------- */
.dur-bar { flex-wrap: wrap; }
.dur-bar .dur-label { color: var(--muted); font-size: 13px; margin-right: -2px; }
.dur-bar .dur-in { width: 86px; }
.dur-bar .dur-quicks { display: flex; gap: 6px; align-items: center; color: var(--muted); font-size: 13px; }
.dur-bar .dur-quicks .tab { cursor: pointer; }
.dial-input {
  flex: 1 1 0; width: 100%; min-width: 0;
  font-size: 21px; font-weight: 700; letter-spacing: 1px; text-align: center;
  height: 44px; min-height: 44px; color: var(--text);
}
.keypad { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-2); margin-bottom: var(--sp-1); }
.kp {
  padding: 11px 0; font-size: 18px; font-weight: 700;
  border: 1px solid var(--border); background: #FAFBFC;
  border-radius: 8px; cursor: pointer; color: var(--text); user-select: none;
  font-variant-numeric: tabular-nums;
  transition: background .12s, border-color .12s, color .12s;
}
.kp:hover { background: var(--primary-soft); border-color: var(--primary); color: var(--primary); }
.kp:active { background: #BAE0FF; }
.kp.minor { font-size: 13px; font-weight: 500; color: var(--muted); }
.kv { display: grid; grid-template-columns: 76px minmax(0, 1fr); gap: 6px 10px; font-size: 13px; }
.kv .k { color: var(--muted); }
.timeline { border-left: 2px solid var(--border); margin-left: 6px; padding-left: var(--sp-3); }
.tl-item { position: relative; padding-bottom: var(--sp-3); }
.tl-item::before {
  content: ""; position: absolute; left: -20px; top: 5px; width: 8px; height: 8px;
  border-radius: 50%; background: var(--primary); border: 2px solid var(--card);
}
.tl-item .t { color: var(--faint); font-size: 11.5px; }

/* ============================================================================
   图表
   ============================================================================ */
.bars { display: flex; align-items: flex-end; gap: 10px; height: 160px; padding: var(--sp-2) var(--sp-1) 0; }
.bar-col { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 6px; height: 100%; justify-content: flex-end; }
.bar-stack {
  width: 26px; max-width: 100%; border-radius: 4px 4px 0 0;
  background: var(--primary-soft); position: relative;
  display: flex; flex-direction: column-reverse; overflow: hidden;
}
.bar-in { background: var(--primary); width: 100%; }
.bar-x { font-size: 11px; color: var(--faint); }
.bar-n { font-size: 11.5px; color: var(--muted); }
.dist-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; font-size: 12.5px; }
.dist-row .dl { width: 84px; color: var(--muted); flex-shrink: 0; }
.dist-row .db { flex: 1; min-width: 0; height: 8px; background: #F2F4F7; border-radius: 4px; overflow: hidden; }
.dist-row .di { height: 100%; border-radius: 4px; background: var(--primary); }
.dist-row .dn { width: 34px; text-align: right; font-weight: 600; flex-shrink: 0; }
.legend { display: flex; gap: var(--sp-3); font-size: 12px; color: var(--muted); flex-wrap: wrap; }
.legend i { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 5px; }

.progress { height: 8px; background: #F2F4F7; border-radius: 4px; overflow: hidden; }
.progress i { display: block; height: 100%; background: var(--primary); border-radius: 4px; transition: width .3s; }

/* 录音播放器：宽度写死。注意不能加 max-width:100%——表格自动布局下
   它会把这一列压成几十像素，播放器缩成一个点（之前就是这么坏的）。 */
.audio-play { width: 200px; min-width: 170px; height: 30px; }
.inline-form { display: flex; gap: var(--sp-2); margin-top: 10px; }
.inline-form .input { flex: 1; min-width: 0; }

/* ============================================================================
   数据大屏
   全屏挂墙展示，**唯一保留深色的地方**：投影/大屏环境下浅色刺眼且对比度不足，
   市面上的数据大屏也都是深色。配色仍是同一族蓝，只是压暗。
   ============================================================================ */
.screen {
  position: fixed; inset: 0; z-index: 80;
  background:
    radial-gradient(1200px 600px at 20% -10%, rgba(22, 119, 255, .16) 0%, transparent 55%),
    linear-gradient(180deg, #0B1220, #070B14);
  color: #E8EEF9; padding: 18px 22px 22px; overflow: auto;
  font-variant-numeric: tabular-nums;
}
.scr-head { display: flex; align-items: center; gap: var(--sp-4); padding-bottom: var(--sp-3); border-bottom: 1px solid rgba(120, 170, 255, .18); margin-bottom: var(--sp-4); flex-wrap: wrap; }
.scr-title { font-size: 22px; font-weight: 700; letter-spacing: 2px; color: #EAF3FF; }
.scr-stamp { font-size: 12.5px; color: #8FA2C4; }
.scr-clock { margin-left: auto; font-size: 15px; color: #BCD3F7; font-family: ui-monospace, Consolas, monospace; }
.scr-exit {
  background: rgba(120, 170, 255, .14); color: #CFE0FF; border: 1px solid rgba(120, 170, 255, .3);
  border-radius: var(--radius-sm); padding: 6px 14px; cursor: pointer; font-size: 12.5px;
}
.scr-exit:hover { background: rgba(120, 170, 255, .26); }
.scr-stats { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 14px; margin-bottom: var(--sp-4); }
.scr-stat {
  position: relative; overflow: hidden;
  background: rgba(22, 119, 255, .10);
  border: 1px solid rgba(120, 170, 255, .18); border-radius: 8px; padding: 14px 16px;
}
.scr-stat::before { content: ''; position: absolute; left: 0; top: 0; width: 3px; height: 100%; background: #4096FF; }
.scr-stat.good::before { background: #22D3A7; }
.scr-stat.warn::before { background: #FBBF24; }
.scr-stat .k { font-size: 12.5px; color: #8FA2C4; margin-bottom: var(--sp-2); }
.scr-stat .v { font-size: 30px; font-weight: 700; line-height: 1; color: #EAF3FF; }
.scr-stat.good .v { color: #22D3A7; }
.scr-stat.warn .v { color: #FBBF24; }
.scr-stat .v span { font-size: 12.5px; font-weight: 400; color: #8FA2C4; margin-left: 4px; }
.scr-grid { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 1fr); gap: 14px; }
.scr-panel {
  position: relative; background: rgba(15, 25, 45, .72); border: 1px solid rgba(120, 170, 255, .18);
  border-radius: 8px; padding: 14px 16px;
}
.scr-panel.wide { grid-column: span 2; }
.scr-panel h4 {
  font-size: 13.5px; font-weight: 600; color: #BCD3F7; margin: 0 0 var(--sp-3);
  padding-left: 9px; border-left: 3px solid #4096FF;
}
.scr-legend { display: flex; gap: 14px; font-size: 12px; color: #8FA2C4; margin-bottom: 6px; }
.scr-legend i { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 5px; }
.scr-panel .bars { height: 190px; }
.scr-panel .bar-x { font-size: 11px; color: #7D8FB3; }
.scr-dist, .scr-rank { display: flex; align-items: center; gap: 10px; margin-bottom: 9px; font-size: 12.5px; }
.scr-dist .lbl, .scr-rank .nm { width: 52px; color: #BCD3F7; flex: none; }
.scr-rank .nm { width: 68px; }
.scr-dist .track, .scr-rank .track { flex: 1; min-width: 0; height: 9px; border-radius: 5px; background: rgba(120, 170, 255, .14); overflow: hidden; }
.scr-dist .track i, .scr-rank .track i { display: block; height: 100%; border-radius: 5px; }
.scr-dist b, .scr-rank b { width: 72px; text-align: right; color: #EAF3FF; flex: none; }
.scr-rank b span { color: #7D8FB3; font-weight: 400; }
.scr-rank .no {
  width: 20px; height: 20px; line-height: 20px; text-align: center; border-radius: 5px;
  background: rgba(120, 170, 255, .14); color: #8FA2C4; font-size: 11px; flex: none;
}
.scr-rank .no.top { background: linear-gradient(180deg, #4096FF, #22D3A7); color: #06121C; font-weight: 700; }
.scr-tb { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.scr-tb th { color: #8FA2C4; font-weight: 500; text-align: left; padding: 7px 10px; border-bottom: 1px solid rgba(120, 170, 255, .16); font-size: 12px; }
.scr-tb td { padding: 7px 10px; border-bottom: 1px solid rgba(120, 170, 255, .08); color: #DBE7FB; }
.scr-tb .mono { font-family: ui-monospace, Consolas, monospace; }
.scr-tb .pill { display: inline-block; border-radius: 5px; padding: 1px 7px; font-size: 11.5px; }
.scr-tb .pill.ok { background: rgba(34, 211, 167, .16); color: #22D3A7; }
.scr-tb .pill.no { background: rgba(148, 163, 184, .16); color: #A7B6CF; }
.scr-empty { color: #7D8FB3; font-size: 13px; padding: 14px 0; }
@media (max-width: 1200px) {
  .scr-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .scr-grid { grid-template-columns: minmax(0, 1fr); }
  .scr-panel.wide { grid-column: span 1; }
}

/* 大屏响应式：整体随视口缩放，保证一屏放下、不出现滚动条（覆盖上面的固定像素） */
.screen {
  height: 100vh; overflow: hidden; display: flex; flex-direction: column;
  gap: clamp(8px, 1.1vh, 14px); padding: clamp(10px, 1.8vh, 20px) clamp(12px, 1.6vw, 24px);
}
.scr-head { padding-bottom: clamp(6px, 1vh, 12px); margin-bottom: 0; gap: clamp(8px, 1vw, 16px); }
.scr-title { font-size: clamp(15px, 1.55vw, 23px); letter-spacing: clamp(1px, .15vw, 2px); white-space: nowrap; }
.scr-stamp { font-size: clamp(11px, .82vw, 13px); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.scr-clock { font-size: clamp(12px, .95vw, 15px); white-space: nowrap; }
.scr-exit { padding: clamp(4px, .5vh, 7px) clamp(9px, .8vw, 15px); font-size: clamp(11px, .78vw, 12.5px); white-space: nowrap; }
.scr-stats { grid-template-columns: repeat(6, minmax(0, 1fr)); gap: clamp(8px, 1vw, 14px); margin-bottom: 0; }
.scr-stat { padding: clamp(9px, 1.3vh, 16px) clamp(11px, 1.2vw, 18px); }
.scr-stat .k { font-size: clamp(11px, .8vw, 12.5px); margin-bottom: clamp(4px, .7vh, 8px); }
.scr-stat .v { font-size: clamp(17px, 2.05vw, 32px); }
.scr-stat .v span { font-size: clamp(10px, .75vw, 12.5px); }
.scr-grid { flex: 1; min-height: 0; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(8px, 1vw, 14px); }
.scr-panel { min-height: 0; display: flex; flex-direction: column; overflow: hidden; padding: clamp(10px, 1.4vh, 16px) clamp(12px, 1.2vw, 18px); }
.scr-panel h4 { font-size: clamp(11.5px, .88vw, 13.5px); margin-bottom: clamp(6px, .9vh, 12px); }
.scr-legend { font-size: clamp(10.5px, .75vw, 12px); margin-bottom: clamp(2px, .4vh, 6px); }
.scr-panel .bars { flex: 1; min-height: 0; height: auto; gap: clamp(4px, .6vw, 10px); }
.scr-panel .bar-n { font-size: clamp(10px, .72vw, 12px); color: #8FA2C4; }
.scr-panel .bar-x { font-size: clamp(9.5px, .66vw, 11px); }
.scr-panel .bar-stack { width: clamp(12px, 1.5vw, 26px); background: rgba(64, 150, 255, .22); }
.scr-panel .bar-in { background: #4096FF; }
.scr-dist, .scr-rank { gap: clamp(5px, .6vw, 10px); margin-bottom: clamp(4px, .7vh, 9px); font-size: clamp(10.5px, .78vw, 12.5px); }
.scr-dist .lbl, .scr-rank .nm { width: clamp(34px, 3.4vw, 54px); }
.scr-dist .track, .scr-rank .track { height: clamp(6px, .75vh, 9px); }
.scr-dist b, .scr-rank b { width: clamp(46px, 4.4vw, 74px); }
.scr-tb { font-size: clamp(10.5px, .78vw, 12.5px); }
.scr-tb th { padding: clamp(4px, .6vh, 7px) clamp(6px, .7vw, 10px); font-size: clamp(10px, .72vw, 12px); }
.scr-tb td { padding: clamp(4px, .6vh, 7px) clamp(6px, .7vw, 10px); }
.scr-tb .pill { font-size: clamp(10px, .7vw, 11.5px); }
@media (max-width: 1100px) {
  .scr-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-rows: 1fr 1fr; }
  .scr-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-rows: 1fr 1fr; }
  .scr-panel.wide { grid-column: span 2; }
}
@media (max-height: 720px) {
  .scr-stat .v { font-size: clamp(15px, 1.7vw, 24px); }
  .scr-panel h4 { font-size: clamp(11px, .8vw, 12.5px); }
  .scr-tb th, .scr-tb td { padding: 3px 6px; }
}

/* ============================================================================
   客户资料截图 / 看图灯箱
   ============================================================================ */
.media-grid { display: flex; flex-wrap: wrap; gap: 10px; }
.media-thumb {
  width: auto; max-width: 150px; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: #FAFBFC;
  cursor: zoom-in; transition: transform .12s, border-color .12s;
}
.media-thumb:hover { transform: scale(1.04); border-color: var(--primary); }
.media-strip { display: flex; gap: var(--sp-2); overflow-x: auto; padding-bottom: var(--sp-1); }
.media-strip .media-thumb { height: 96px; flex: none; }
.media-more { white-space: nowrap; }

.lightbox { position: fixed; inset: 0; z-index: 120; background: rgba(0, 0, 0, .9); display: flex; align-items: center; justify-content: center; }
.lb-img { max-width: 92vw; max-height: 86vh; border-radius: 6px; box-shadow: 0 8px 60px rgba(0, 0, 0, .6); }
.lb-top {
  position: absolute; top: 0; left: 0; right: 0; display: flex; align-items: center; gap: 14px;
  padding: var(--sp-3) 18px; color: #E8EEF9; font-size: 13px;
  background: linear-gradient(180deg, rgba(0, 0, 0, .6), transparent);
}
.lb-top span:first-child { font-weight: 600; }
.lb-hint { color: #A9B6CC; font-size: 11.5px; margin-left: auto; margin-right: 14px; }
.lb-close { cursor: pointer; font-size: 26px; line-height: 1; color: #E8EEF9; padding: 0 4px; }
.lb-nav {
  position: fixed; top: 50%; transform: translateY(-50%); width: 52px; height: 52px; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .2); background: rgba(255, 255, 255, .14); color: #fff; font-size: 26px; cursor: pointer;
}
.lb-nav:hover { background: rgba(255, 255, 255, .26); }
.lb-nav.prev { left: 18px; } .lb-nav.next { right: 18px; }
.lb-nav:disabled { opacity: .25; cursor: default; }

/* ============================================================================
   标签彩色小片 + 弹出面板（区域/标签筛选）
   ============================================================================ */
.chip { display: inline-block; padding: 1px 9px; border-radius: 999px; font-size: 11.5px; line-height: 1.7; margin: 1px 4px 1px 0; color: #fff; font-weight: 500; white-space: nowrap; }
.popwrap { position: relative; display: inline-flex; min-width: 0; }
.popwrap > * { min-width: 0; }
.pop {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 60;
  background: var(--card); border: 1px solid var(--border);
  border-radius: 8px; box-shadow: var(--shadow-lg);
  padding: 8px 10px; min-width: 190px; max-height: 300px; overflow: auto;
}
.pop label { display: flex; align-items: center; gap: 7px; padding: 5px 4px; cursor: pointer; font-size: 13px; border-radius: 4px; }
.pop label:hover { background: #F2F4F7; }

/* 代码片段（系统设置里的接口说明）。
   里面是一整串没有空格的 JSON，默认不换行会把整页顶宽（实测撑到 840px），
   所以强制允许在任意字符处断行。
   注意：这里**不要**给 .code 加 display:inline-block —— 那会让它变成原子盒，
   长 JSON 反而没法在行内折行，又会撑宽页面。让它保持 inline 就好。 */
.code, code {
  background: #F2F4F7; color: #0958D9;
  padding: 2px 6px; border-radius: 4px; font-size: 12.5px;
  border: 1px solid var(--border);
  overflow-wrap: anywhere; word-break: break-word;
  max-width: 100%;
}

/* 日期输入 */
input[type=date].input { padding: 6px 9px; }

/* ============================================================================
   自适应：这是本次重做的重点。
   原来只有零散的 max-width 规则，侧栏在手机上会占掉半个屏幕。
   ============================================================================ */

/* 宽屏：把内容放宽一点，别在 2K 屏上留一大片空 */
@media (min-width: 1700px) { :root { --content-max: 1800px; } }

/* 平板横屏 / 小笔记本：两栏布局改一栏。
   统计行**保持原列数紧凑铺满**——降列（3 列）会让 5 张卡变成 3+2、右侧空一截，
   那是仪表盘最扎眼的"没对齐"；列数不变只把卡收紧凑，任何宽度都是整齐一行。 */
@media (max-width: 1280px) {
  .stat-row { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .stat-row.cols-6 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .stat { padding: var(--sp-3) var(--sp-4); }
  .stat .value { font-size: clamp(17px, 1.5vw, 22px); }
  .grid-2, .grid-split { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 1100px) {
  .dialer { grid-template-columns: minmax(0, 1fr); }
  /* 窗口窄的时候把播放器和长文本再收一点，少滚一点 */
  .audio-play { width: 160px; min-width: 140px; }
  .cut { max-width: 170px; }
}

/* ---------- 导航断点：900px 以下收成抽屉 ---------- */
@media (max-width: 900px) {
  :root { --content-pad: 16px; }
  .nav-toggle { display: inline-flex; }
  /* 抽屉与遮罩都从顶栏下沿开始，而不是盖住顶栏。
     原因：抽屉的 z-index 必须高于遮罩，若它盖住顶栏，就把顶栏里的汉堡按钮一起盖住了 ——
     用户打开菜单后点不到那个按钮，只能点遮罩关闭（实测过，确实点不到）。
     让出顶栏高度，汉堡始终可点，收/开都顺手。 */
  .sidebar {
    position: fixed; top: var(--topbar-h); left: 0; bottom: 0; height: auto;
    width: 260px; max-width: 84vw; z-index: 120;
    transform: translateX(-102%); transition: transform .22s ease;
    box-shadow: 6px 0 24px rgba(0, 0, 0, .12);
    border-right: 1px solid var(--border);
  }
  .layout.nav-open .sidebar { transform: none; }
  .layout.nav-open .nav-scrim { display: block; }
  .nav-scrim { top: var(--topbar-h); }
  /* 手机上呼叫条是铺满底部的（z-index 200），会把抽屉最下面的「退出」盖住。
     窄屏把它压到遮罩之下：抽屉打开时遮住它，平时仍浮在内容之上。 */
  #callbar { z-index: 85; }
  /* 抽屉里导航项要大一点，手指点得中 */
  .nav-item { padding: 12px; font-size: 14.5px; }
  .sidebar .user-box { padding: var(--sp-4) var(--sp-3); }
}

/* ---------- 手机：768px 以下 ---------- */
@media (max-width: 768px) {
  :root { --content-pad: 12px; --topbar-h: 52px; }
  body { font-size: 13.5px; }
  .topbar { gap: var(--sp-2); }
  .topbar h2 { font-size: 15.5px; }
  .topbar .date { display: none; }          /* 日期在手机上没用，让位给状态 */
  .phone-chip .badge { max-width: 46vw; font-size: 11px; padding: 1px 8px; }
  .card-pad { padding: var(--sp-4); }
  .card h3 { font-size: 14px; margin-bottom: var(--sp-3); }
  .stat-row, .stat-row.cols-6, .stat-row.cols-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stat { padding: var(--sp-3) var(--sp-4); }
  .grid { gap: var(--sp-3); }
  /* 表单一行一项：两列在手机上输入框会窄到没法用 */
  .form-row { grid-template-columns: minmax(0, 1fr); }
  /* 弹窗铺满，别留一条缝 */
  .overlay { padding: 0; align-items: stretch; }
  .modal, .modal.wide { width: 100%; max-width: 100%; max-height: 100vh; height: 100%; border-radius: 0; }
  .drawer { width: 100%; max-width: 100%; border-left: none; }
  .drawer .d-body { padding: var(--sp-4); }
  /* 呼叫条铺到底，并让开底部安全区 */
  #callbar { right: 0; left: 0; bottom: 0; width: 100%; max-width: 100%; padding: 0 10px 10px; }
  .callbar { border-radius: 12px 12px 0 0; }
  /* 表格：靠横向滚动，但把首列钉住，滚到右边还知道在看谁 */
  .tb-wrap > .tb { min-width: 640px; }
  .tb-wrap.wide > .tb { min-width: 900px; }
  .tb:not(.mini-table) th:first-child,
  .tb:not(.mini-table) td:first-child {
    position: sticky; left: 0; z-index: 1;
    background: var(--card);
    box-shadow: 1px 0 0 var(--border);
  }
  .tb:not(.mini-table) th:first-child { background: #FAFBFC; }
  .tb th, .tb td { padding: 9px 12px; }
  .cut { max-width: 130px; }
  /* 仪表盘那两张小表（待办跟进/最近通话）的首列在 app.js 里写死了 120px/110px，
     inline style 优先级高于样式表，所以这里必须 !important 才能让首列自适应。
     不放开的话手机上内容列只剩几十像素，中文竖着一列一个字。 */
  .mini-table td:first-child { width: auto !important; min-width: 84px; padding-right: 8px !important; }
  .mini-table td { padding: 7px 8px !important; }
  /* 区域级联的市/区县/镇三个下拉在 app.js 里写死了 min-width:96px/110px，
     三个并排就是 300px+，手机上必然撑破。这里允许它们收缩并两两同行。 */
  .toolbar select.input { min-width: 0 !important; flex: 1 1 40%; }
  /* 区域级联那三个下拉外面套着 .popwrap（inline-flex 外壳），
     只放开 select 还不够 —— 外壳自己也会顶宽，得让它独占一行、里面平分。 */
  .toolbar .popwrap { flex: 1 1 100%; }
  .toolbar .popwrap > select.input { flex: 1 1 30%; min-width: 0 !important; }
  /* 弹出的筛选面板是绝对定位，贴左边展开时在窄屏会伸出右边界，改成贴右 */
  .pop { left: auto; right: 0; min-width: 0; width: min(280px, 82vw); max-width: calc(100vw - 24px); }
  .pagination { justify-content: center; }
  .dialer-num { padding: var(--sp-5) var(--sp-4) var(--sp-4); }
  .dialer-num .phone { font-size: 26px; }
  .kv { grid-template-columns: 68px minmax(0, 1fr); }
  .lb-nav { width: 42px; height: 42px; font-size: 22px; }
  .lb-nav.prev { left: 8px; } .lb-nav.next { right: 8px; }
}

/* ---------- 超窄：480px 以下 ---------- */
@media (max-width: 480px) {
  .toolbar { gap: 6px; }
  /* 只让文本输入占满一行；下拉和按钮两两同行，否则筛选栏能铺四行 */
  .toolbar input.input { flex: 1 1 100%; }
  .toolbar select.input { flex: 1 1 130px; }
  .toolbar .btn { flex: 0 1 auto; }
  .btn { padding: 7px 12px; }
  .btn.lg { width: 100%; }
  .tabs { width: 100%; }
  .tab { flex: 1; text-align: center; padding: 6px 8px; }
  .dialer-btns { flex-direction: column; }
  .dialer-btns .btn { width: 100%; }
  .keypad { gap: 6px; }
  .kp { padding: 10px 0; font-size: 17px; }
  .modal .m-body, .modal .m-head, .modal .m-foot { padding-left: var(--sp-4); padding-right: var(--sp-4); }
  .modal .m-foot { flex-direction: column-reverse; }
  .modal .m-foot .btn { width: 100%; }
}

/* 横屏手机：顶栏和统计卡再压一压，别让内容区只剩一条 */
@media (max-height: 520px) and (orientation: landscape) {
  :root { --topbar-h: 46px; }
  .stat-row, .stat-row.cols-6, .stat-row.cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* 打印：白底黑字，别打出灰底卡片 */
@media print {
  body { background: #fff; color: #000; }
  .sidebar, .topbar, #callbar, #toast-root, .nav-toggle { display: none !important; }
  .card { border: 1px solid #ddd; box-shadow: none; background: #fff; }
}

/* ---------- 客户列表意向/状态就地编辑 ---------- */
.level-cell,.status-cell{display:inline-block;padding:2px 4px;border-radius:6px}
.level-cell.editable,.status-cell.editable{cursor:pointer}
.level-cell.editable:hover,.status-cell.editable:hover{outline:1px dashed var(--primary)}
.level-quick{width:170px;padding:2px 6px;font-size:12.5px}
.status-quick{width:110px;padding:2px 6px;font-size:12.5px}

/* ============================================================================
   CRM V2（Phase 1）—— 新增页面与区块
   ----------------------------------------------------------------------------
   只有一套设计系统：下面全部复用上面 :root 的色值/间距/圆角，不新增"随手写"的色值。
   命名空间按功能分块：wait-（待接入横幅）· range-（日期区间）· cal-（日历）·
   tl-（时间线）· ds-（客户详情信息条）· mk-（我的标记）· meta-（客户列表第二行）。
   ============================================================================ */

/* ---------- 待接入横幅：CRM Core 接口还没上线时，页面上必须一眼看得见 ----------
   用橙色（待办色）而不是红色：这不是错误，是"尚未施工"，红色会让人以为系统坏了。 */
.wait-banner {
  background: var(--orange-soft); border: 1px solid #FED7AA; border-radius: var(--radius);
  padding: var(--sp-3) var(--sp-4); margin-bottom: var(--sp-4);
}
.wait-banner .wb-head { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: 6px; font-size: 13px; }
.wait-banner .wb-tag {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; font-weight: 600;
  background: var(--orange); color: #fff; padding: 1px 8px; border-radius: 999px; letter-spacing: .2px;
}
.wait-banner .wb-body { font-size: 12.5px; color: var(--muted); line-height: 1.7; }
.wait-banner .wb-paths { display: inline-flex; flex-wrap: wrap; gap: 4px; margin-left: 4px; }
.wait-banner .wb-extra { margin-top: 6px; color: var(--text); }
.wait-banner code { background: rgba(217, 119, 6, .1); color: #B45309; padding: 1px 5px; border-radius: 4px; font-size: 11.5px; }

/* ---------- 通用小字与"待接入"占位 ----------
   需求 §3 明确：公司不存在时不显示"暂无公司"、不显示"-"。缺值一律留空，
   确实需要交代的用 .na-note 说明依赖哪个接口。 */
.hint { color: var(--muted); font-size: 12.5px; line-height: 1.7; }
.hint-inline { color: var(--faint); font-size: 12px; margin-top: 4px; display: block; }
.na-note { color: var(--faint); font-size: 12px; }
.tiny-code { font-size: 11.5px; }
.sub-phone { color: var(--faint); font-size: 11.5px; margin-top: 2px; }
.tbl-note { color: var(--faint); font-size: 12px; margin-top: var(--sp-3); }
.stat-note { color: var(--faint); font-size: 11.5px; margin-top: 2px; }
.cut2 { display: inline-block; max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chk-line { display: flex; align-items: center; gap: var(--sp-2); font-size: 13px; margin: var(--sp-3) 0 var(--sp-2); cursor: pointer; }
.chk-line input { width: 15px; height: 15px; }
/* 勾选"创建下一次跟进"后展开的区块：左侧一根竖线表示从属关系 */
.sub-block { border-left: 2px solid var(--primary-soft); padding-left: var(--sp-4); margin-bottom: var(--sp-2); }
.wait-note { color: var(--faint); font-size: 12px; margin-top: var(--sp-3); border-top: 1px dashed var(--border); padding-top: var(--sp-3); }

/* ---------- 日期区间：开始日期 ～ 结束日期 永远可见，快捷按钮只是快捷设置（需求 §11） ---------- */
.range-bar { row-gap: var(--sp-2); }
/* 快捷按钮组自己会换行，但作为 flex 子项默认按内容撑宽：在抽屉那种 ~500px 的窄容器里
   会把整行顶出边界（实测"自定义日期"被右缘裁掉）。min-width:0 让它成为可收缩的子项，
   它才会在自己内部折行。 */
.range-quick { display: inline-flex; gap: 4px; flex-wrap: wrap; min-width: 0; }
.range-sep { color: var(--muted); font-size: 12.5px; white-space: nowrap; }
.range-date { width: 148px; min-width: 0; }
.range-note { color: var(--faint); font-size: 12px; }
/* 抽屉/弹窗里空间更紧：快捷按钮独占一行，两个日期框平分下一行（开始日期～结束日期 仍成对出现） */
.drawer .range-bar, .modal .range-bar { display: flex; flex-wrap: wrap; }
.drawer .range-quick, .modal .range-quick { flex: 1 1 100%; }
.drawer .range-date, .modal .range-date { flex: 1 1 120px; width: auto; }
.cal-range-label { color: var(--muted); font-size: 12.5px; margin-bottom: var(--sp-3); }

/* ---------- 跟进日历 ---------- */
.cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; }
.cal-dow { background: #FAFBFC; color: var(--muted); font-size: 12px; text-align: center; padding: 7px 0; }
.cal-cell { background: var(--card); min-height: 96px; padding: 6px 7px; cursor: pointer; }
.cal-cell:hover { background: var(--primary-soft); }
.cal-cell.out { background: #FCFCFD; }
.cal-cell.out .cal-num { color: var(--faint); opacity: .55; }
.cal-cell.today { box-shadow: inset 0 0 0 2px var(--primary); }
.cal-num { font-size: 12.5px; color: var(--text); font-weight: 600; margin-bottom: 4px; }
.cal-items { display: flex; flex-direction: column; gap: 2px; }
.cal-item { font-size: 11.5px; line-height: 1.5; border-radius: 4px; padding: 1px 4px; background: var(--primary-soft); color: #0958D9; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.cal-item.done { background: var(--green-soft); color: var(--green); text-decoration: line-through; opacity: .8; }
.cal-item .ci-t { font-variant-numeric: tabular-nums; opacity: .8; margin-right: 3px; }
.cal-more { font-size: 11px; color: var(--faint); padding-left: 4px; }
.cal-day-head { font-size: 13.5px; font-weight: 600; margin-bottom: var(--sp-3); }
.cal-week { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--sp-2); }
.cal-wcol { min-width: 0; background: #FAFBFC; border: 1px solid var(--border); border-radius: var(--radius-sm); padding: var(--sp-2); }
.cal-whead { display: flex; align-items: center; gap: 5px; font-size: 12px; color: var(--muted); margin-bottom: 6px; }
.cal-whead b { color: var(--text); font-size: 12.5px; }
.cal-whead.today { color: var(--primary); }
.cal-whead.today b { color: var(--primary); }
.cal-cnt { margin-left: auto; background: var(--primary-soft); color: #0958D9; border-radius: 999px; padding: 0 6px; font-size: 11px; }
.cal-witem { background: var(--card); border: 1px solid var(--border); border-radius: 4px; padding: 3px 5px; font-size: 11.5px; margin-bottom: 3px; cursor: pointer; overflow: hidden; }
.cal-witem:hover { border-color: var(--primary); }
.cal-witem .cw-t { font-variant-numeric: tabular-nums; color: var(--muted); margin-right: 4px; }
.cal-wempty { color: var(--faint); font-size: 11.5px; text-align: center; padding: 6px 0; }

/* ---------- 客户时间线（需求 §5）----------
   左侧一条竖轨 + 圆点，与抽屉里原有的 .tl-item 语言一致，只是信息更结构化。 */
.tl-list { position: relative; }
.tl-day { font-size: 12px; color: var(--faint); font-weight: 600; margin: var(--sp-4) 0 var(--sp-2); }
.tl-day:first-child { margin-top: 0; }
.tl-row { display: flex; gap: var(--sp-3); padding-bottom: var(--sp-3); }
.tl-rail { position: relative; width: 12px; flex-shrink: 0; display: flex; justify-content: center; }
.tl-rail::before { content: ""; position: absolute; top: 6px; bottom: -14px; width: 1px; background: var(--border); }
.tl-row:last-child .tl-rail::before { display: none; }
.tl-rail i { position: relative; width: 8px; height: 8px; border-radius: 50%; background: var(--primary); margin-top: 5px; box-shadow: 0 0 0 3px var(--primary-soft); }
.tl-body { flex: 1; min-width: 0; }
.tl-head { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 12.5px; }
.tl-time { color: var(--muted); font-variant-numeric: tabular-nums; }
.tl-actor { color: var(--faint); font-size: 12px; margin-left: auto; }
.tl-title { font-size: 13px; margin-top: 3px; }
.tl-sub { color: var(--muted); font-size: 12.5px; margin-top: 3px; }
.tl-feedback { font-size: 13px; margin-top: 4px; padding: 5px 9px; background: #FAFBFC; border-radius: var(--radius-sm); border-left: 2px solid var(--border-strong); }
.tl-stage-move { font-size: 13px; margin-top: 3px; font-weight: 600; }
.tl-arrow { color: var(--primary); margin: 0 4px; }

/* ---------- 客户详情：新增信息条（需求 §4）---------- */
.detail-strip { border: 1px solid var(--border); border-radius: var(--radius); background: #FAFBFC; padding: var(--sp-3) var(--sp-4); margin-bottom: var(--sp-4); }
.ds-row { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; padding: 5px 0; font-size: 13px; }
.ds-row + .ds-row { border-top: 1px dashed var(--border); }
.ds-row-top { align-items: flex-start; }
.ds-k { color: var(--muted); font-size: 12.5px; width: 84px; flex-shrink: 0; }
.ds-v { flex: 1; min-width: 0; display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.ds-text { display: block; }
.ds-time { font-variant-numeric: tabular-nums; }

/* ---------- 我的标记（需求 §8）----------
   ★ 必须和"企业标签"一眼看出不是一类东西：
     企业标签 = 实色圆角片（.chip，公司级、团队共享）
     我的标记 = 暖色浅底 + 虚线边框 + ▣ 前缀（坐席个人私有）
   所以这里刻意不用 .chip 的实色填充。 */
.mk-block { display: inline-flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.mk-chip {
  display: inline-flex; align-items: center; gap: 4px;
  background: #FFFBEB; border: 1px dashed #FBBF24; color: #92400E;
  border-radius: var(--radius-sm); padding: 1px 7px; font-size: 12px; line-height: 1.7;
}
.mk-ico { font-size: 10px; opacity: .85; }
.mk-del { cursor: pointer; color: var(--faint); font-size: 14px; line-height: 1; padding: 0 1px; }
.mk-del:hover { color: var(--red); }
.mk-add { border-style: dashed; }
.mk-empty { color: var(--faint); font-size: 12px; }

/* ---------- 客户列表：新增字段的第二行（需求 §3）----------
   主表列宽一个像素都没动，五项新信息压成一条紧凑信息行，避免"列一多表就不可用"。 */
.row-meta td { padding: 0 14px 9px !important; border-bottom: 1px solid #F0F2F5; }
.tb:not(.mini-table) .row-meta td { white-space: normal; }
.tb tbody tr.row-meta:hover { background: transparent; }
.meta-line { display: flex; flex-wrap: wrap; gap: 4px var(--sp-4); font-size: 12px; }
.meta-item { display: inline-flex; align-items: center; gap: 5px; min-width: 0; }
.mi-k { color: var(--faint); flex-shrink: 0; }
.mi-v { color: var(--muted); }
td.cell-company { font-size: 12.5px; }
td.cell-fb { max-width: 240px; }
/* 今日工作/长期跟进的操作列要放 4 个按钮（拨打/查看客户/完成/延期）。
   .tb .actions 原本是 nowrap，表格横向滚动时"延期"会被右缘裁掉看不见，
   所以这里允许它换行：按钮组内部 flex-wrap，行高不够就折到第二行。 */
.tb td.actions { white-space: normal; }
.crm-acts { display: inline-flex; flex-wrap: wrap; gap: 4px; justify-content: flex-end; align-items: center; }

/* 带表格的弹窗（当天计划列表 / 阶段变化历史）要更宽：
   .modal.wide 只有 660px，减掉内边距剩 620px，装不下 7 列（时间/客户/负责人/方式/目的/
   优先级/状态）—— 最后一列"状态"会被挤到可视区外，看着像没这一列。 */
.modal.wide-tb { width: 880px; }
/* 再给这类表格收紧内边距 + 只让客户名换行，保证 7 列都落在可视宽度内 */
.wide-tb .plan-tb { min-width: 0; }
.wide-tb .plan-tb th, .wide-tb .plan-tb td { padding: 7px 9px; }
.wide-tb .plan-tb td { white-space: normal; }
.wide-tb .plan-tb td:nth-child(2) { max-width: 240px; }

/* ---------- 客户搜索下拉（新建计划弹窗里选客户，走现有 /api/customers 的真实数据）---------- */
.cust-suggest {
  position: absolute; z-index: 60; left: 0; right: 0; top: 100%; margin-top: 2px;
  background: var(--card); border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg); max-height: 240px; overflow-y: auto;
}
.cs-item { display: flex; align-items: center; gap: var(--sp-2); padding: 7px 10px; cursor: pointer; font-size: 13px; }
.cs-item:hover { background: var(--primary-soft); }
.cs-phone { color: var(--faint); font-size: 12px; margin-left: auto; font-variant-numeric: tabular-nums; }
.cs-empty { padding: 10px; color: var(--faint); font-size: 12.5px; }

/* ---------- 窄屏：只做"能用"的收敛，不为移动端重写整套 CSS（需求 §12）---------- */
@media (max-width: 900px) {
  .cal-cell { min-height: 72px; padding: 4px; }
  .cal-week { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ds-k { width: 68px; }
  .range-date { width: 128px; }
}
@media (max-width: 480px) {
  .cal-item .ci-n { display: none; }          /* 超窄只留时间点，客户名靠点击弹层看 */
  .cal-cell { min-height: 58px; }
  .ds-k { width: 100%; }
  .tl-actor { margin-left: 0; }
}

/* ---- 品牌图形 logo（2026-09-29）：替换原文字徽标 .logo-mark ---- */
.logo-img {
  width: 42px; height: 42px; border-radius: 10px; flex-shrink: 0;
  display: block;
  box-shadow: 0 2px 8px rgba(37, 99, 235, .28);
}
.sidebar .brand .logo-img { width: 30px; height: 30px; border-radius: 8px; box-shadow: none; }
