/* ==========================================================================
   电信支局工作台 · 设计系统
   统一：配色 / 间距 / 字号 / 圆角 / 阴影 / 表格样式
   适配：1366×768、1440×900、1600×900、1920×1080 常见桌面分辨率
   ========================================================================== */
:root{
  /* —— 品牌与语义色（全局唯一出处，禁止在组件里硬编码颜色） —— */
  --brand:#1655c8;  --brand-hi:#0f47ad;  --brand-soft:#eaf1fe;
  /* V27：微信品牌绿。只作「行动色」用 —— 主按钮 / 选中态 / 底部 Tab 选中，
     信息色仍走 --brand（蓝），两者分工明确，避免全站变成一个颜色。 */
  --wx-green:#07C160;
  --ok:#12a05c;     --ok-soft:#e7f7ef;
  --warn:#976b30;   --warn-soft:#e0d0b8;
  --danger:#b95850; --danger-soft:#dfbcb9;
  --purple:#7b69c4; --purple-soft:#c1b7e1;
  --teal:#0d9488;   --teal-soft:#e4f6f4;
  --gray:#94a3b8;   --gray-soft:#f1f5f9;

  /* —— 中性色（V27 微信风：背景更接微信底色 / 分割线更清晰 / 文字三档灰阶） —— */
  --bg:#ededed;
  --panel:#ffffff;
  --line:#e5e5e5;
  --line-soft:#f0f0f0;
  --t1:#191919;
  --t2:#5c5c5c;
  --t3:#6f6f6f;           /* V34：#888 在白底约 3.5:1 不达 AA；调深到约 5.1:1 */
  --t-disabled:#a6a6a6;   /* V34：禁用态文字色（WCAG 对禁用控件不强制，仅用于真禁用） */
  /* V28（UI 规范统一）：补齐以下颜色令牌，消灭组件里的散落硬编码 —— */
  --t-white:#fff;            /* 彩色底上的文字（按钮/Tab 角标） */
  --t-mute:#767676;          /* V34：#7a7a7a 白底 4.0:1 不到 AA；调深到 4.54:1。
                               用于法律脚注 / 时间戳等比 --t3 更弱的文字。
                               （旧注释写「比 t3 更弱」但原值 #7a7a7a 比旧 t3 #888 更深，
                                 本来就自相矛盾；t3 加深到 #6f6f6f 后两者顺序才对上。） */
  --bg-soft:#f5f5f5;         /* 比 bg 更白的浅灰底：选中行、备用底 */
  --bg-card:#f7f9fc;         /* 卡片内浅色分区底 */
  --bg-tint:#fbfcfe;         /* 极浅冷白：面板头 / 工具栏 / 弹窗底 */
  --bg-hover:#f4f7fc;        /* 悬停底（导航项 / 表格行） */
  --bg-stripe:#fcfdfe;       /* 表格斑马纹（比 tint 再浅一档） */
  --bg-bar:#f2f5f9;          /* 进度条 / 图表条底槽 */
  --bg-disabled:#f2f4f7;     /* 禁用控件底 */
  --bg-note:#f7f9fd;         /* 提示块 / 只读表单底 */
  --line-strong:#d8e0ec;     /* 比 line 更重的边框：输入框/上传区描边 */
  --line-dash:#c8d3e4;       /* 虚线描边（导入拖拽区） */
  --warn-line:#d2c1a6;       /* 警示块的描边（琥珀） */
  --warn-line-soft:#e1d0b7;  /* 警示高亮底（表格命中行） */
  --green-hi:#06ad56;        /* 微信绿按下/悬停加深一档 */
  --warn-text:#976316;       /* 警示底上的文字（深琥珀） */
  --warn-text-2:#9d6721;     /* 警示文字备选档 */
  --ok-text:#0b7a49;         /* 成功底上的深绿文字 */
  --danger-text:#af3d35;     /* 危险底上的深红文字 */
  --wechat-red:#ce4141;
  /* 图形点缀档：比实底更亮更柔，只给色条 / 图表条 / 图例点用。
     实底那几档仍留给「配白字」的角标与危险按钮 —— 那里必须够深才看得清。 */
  --cinnabar-mid:#b79089;
  --danger-mid:#bf908d;
  --warn-mid:#af8751;
  --purple-mid:#8f83bf;
  --wechat-red-mid:#cb8888;
      /* 微信红：未读角标、错误提示底 */
  --brand-deep:#12305c;      /* 品牌深蓝：登录标题 */
  --scrim:rgba(15,23,42,.42);/* 弹窗遮罩 */
  --brand-grad:linear-gradient(135deg,var(--brand),#0b3a91);  /* 品牌渐变（顶栏 logo / 主按钮强调） */
  --brand-grad-lg:linear-gradient(135deg,#2E86F7,#0A2F8F);    /* 登录页专用：更亮的天翼蓝渐变 */

  /* —— 字号（V16 微信规范：正文 15 / 辅助 13 / 小字 12 / 标题 17 / 大标题 22 / 数字 28） ——
     V28（UI 规范统一）：补齐两档 ——  --fs-2xs 极微标（徽标角标）/ --fs-16 iOS 表单防缩放 */
  --fs-2xs:11px;
  --fs-xs:12px;
  --fs-sm:12px;
  --fs-md:15px;
  --fs-16:16px;   /* 输入框专用：iOS Safari 聚焦时 <16px 会自动放大页面 */
  --fs-lg:17px;
  --fs-xl:24px;
  --fs-num:28px;
  /* V28：大数字档（用于首页 KPI 之外的小统计大数，介于 lg 与 num 之间） */
  --fs-num-sm:24px;
  /* V34：补齐数字档 —— 手机首屏 KPI 原硬编码 26px、折叠区统计大数原硬编码 20px，
     曾经被就近收敛到 24px / 18px，等于悄悄改了字号，这里补档把原值放回去。 */
  --fs-num-lg:26px;
  --fs-num-xs:20px;

  /* —— 字重（V28 新增：以前全站散落 400/500/600/650/680/700 六种，此处收敛为四档） —— */
  --fw-normal:400;   /* 常规正文 */
  --fw-medium:500;   /* 次级强调（表格首列、Tab 未选中加粗） */
  --fw-bold:600;     /* 标题 / 主按钮 / 选中态 */
  --fw-black:700;    /* 极强调（角标数字、必填星号） */

  /* —— 行高（V28 新增：以前散落 1~1.9 十二种，此处收敛为四档） —— */
  --lh-none:1;       /* 纯图标行 / 关闭按钮 */
  --lh-tight:1.25;   /* 大标题、卡片标题等紧凑排版 */
  --lh-normal:1.6;   /* 正文默认 */
  --lh-loose:1.75;   /* 说明文字、多行提示等需要呼吸感的段落 */
  --lh:var(--lh-normal);   /* 兼容旧引用 --lh 的写法 */

  /* —— V34 排版统一：字体族 token（此前只在 body 写死一串，等宽另写一份）——
     只用系统字体栈，不引入任何外部字体 / CDN。 */
  --ff-sans:-apple-system,BlinkMacSystemFont,"PingFang SC","Helvetica Neue","Microsoft YaHei",sans-serif;
  /* Consolas 不能省：Windows 桌面机没有 SF Mono / Menlo，
     少了它会掉到很难看的回退等宽字体。 */
  --ff-mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;

  /* —— V34 语义字号：原有 9 档阶梯保留不动（--fs-md 等仍在用），这里只加别名 ——
     「读的文字」走 --fs-body（16px，桌面 + 移动都不小于 16）；
     --fs-md(15px) 仍是数据表格 / 紧凑控件专用，不动。 */
  --fs-body:15px;     /* 正文：页面正文、表单、说明文字 */
  --fs-h1:24px;       /* 页面主标题（= --fs-xl） */
  --fs-h2:17px;       /* 区块标题 */
  --fs-h3:17px;       /* 面板 / 弹窗标题（= --fs-lg） */
  --fs-h4:15px;       /* 小组标题（= --fs-body） */
  --fs-h5:15px;       /* 次要标题（= --fs-md） */
  --fs-h6:12px;       /* 最小标题（= --fs-sm） */
  --fs-caption:12px;  /* 辅助说明（= --fs-sm） */
  --fs-label:12px;    /* 表单标签 / 表格头（= --fs-sm） */
  --fs-btn:15px;      /* 按钮（= --fs-md） */

  /* —— V34 字间距 token：收掉散落的 .2px / 1.2px / -.2px / -.6px ——
     注意：-.2px（大标题）与 -.6px（大数字）是两个**不同的**既有值，
     曾经被合并成一个 --ls-tight:-.4px，等于悄悄改了两个地方的渲染 ——
     这里拆成两个令牌各还各的值，不再合并。 */
  --ls-num:-.6px;     /* 大数字：tabular-nums 收紧（原 .kpi-value -.6px） */
  --ls-title:-.2px;   /* 大标题（原 .page-head h1 -.2px） */
  --ls-normal:0;
  --ls-wide:.2px;     /* 按钮 / Tab / 品牌名 */
  --ls-caps:1.2px;    /* 小标签 / 全大写分组名 */

  /* —— V34 语义描边色：收掉散落的硬编码边框色 —— */
  --line-ok:#bfe6d3;          /* 成功块描边（导入统计 ok） */
  --line-bad:#d7b9b6;         /* 失败块描边（导入统计 bad） */
  --line-warn-strong:#d1c2a8; /* 命中行的警示描边（重点跟进项） */
  --login-brand:#2E86F7;      /* 登录页输入聚焦描边（与 --brand-grad-lg 同色系） */
  --login-ring:rgba(46,134,247,.13);  /* 登录页输入聚焦外发光 */

  /* —— 间距（V16：统一 4 的倍数，主档 16，留白更足） —— */
  --sp-1:4px;  --sp-2:8px;  --sp-3:12px;
  --sp-4:16px; --sp-5:20px; --sp-6:24px; --sp-7:32px;
  /* V28：半档与极小档（图标间距、行内 gap 用；旧代码里的 6px / 10px / 14px 硬编码收敛到这里） */
  --sp-0:0;    --sp-half:2px; --sp-1h:6px;  --sp-2h:10px; --sp-3h:14px;
  /* V28：表单/徽章内边距专用档（3/5/7/9/13px 这类非 4 倍数，单独成档避免取整失真） */
  --sp-pad-a:3px; --sp-pad-b:5px; --sp-pad-c:7px; --sp-pad-d:9px; --sp-pad-e:13px;
  /* V28：弹窗遮罩 / 轻提示底色（半透明层，独立于实色令牌） */
  --overlay-toast:rgba(0,0,0,.8);
  --overlay-toast-bad:rgba(0,0,0,.86);
  --focus-ring:rgba(22,85,200,.10);

  /* —— 圆角（V27 微信偏方：控件 6 / 卡片 8 / 弹窗 12） —— */
  --r-sm:8px; --r:8px; --r-lg:12px;

  /* —— 阴影（更轻更精致） —— */
  --sh-1:0 1px 2px rgba(16,24,40,.04), 0 2px 6px rgba(16,24,40,.04);
  --sh-2:0 4px 16px rgba(16,24,40,.08);
  --sh-3:0 12px 32px rgba(16,24,40,.12);

  /* —— 尺寸：控件高度全站统一（V27 提到 44px，微信触控标准） —— */
  --ctl-h:44px;
  --topbar-h:56px;
  --side-w:216px;
  /* 移动端底部 Tab 栏高度（含安全区），供 .content 补下内边距用 */
  --tabbar-h:50px;
}

*{box-sizing:border-box}
html,body{height:100%}
body{
  margin:0; background:var(--bg); color:var(--t1);
  font-family:var(--ff-sans);
  font-size:var(--fs-body); line-height:var(--lh); -webkit-font-smoothing:antialiased;
}
h1,h2,h3,p{margin:0}
svg{display:block}

/* 滚动条统一 */
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-thumb{background:var(--line-strong);border-radius:var(--r);border:2px solid transparent;background-clip:content-box}
::-webkit-scrollbar-thumb:hover{background:var(--line-strong);background-clip:content-box}
::-webkit-scrollbar-track{background:transparent}

/* ============================ 顶栏 ============================ */
.topbar{
  height:var(--topbar-h); background:var(--panel); border-bottom:1px solid var(--line);
  display:flex; align-items:center; gap:var(--sp-5); padding:0 var(--sp-5);
  position:sticky; top:0; z-index:40;
  box-shadow:0 1px 0 rgba(16,24,40,.02), 0 2px 6px rgba(16,24,40,.03);
}
.brand{display:flex; align-items:center; gap:var(--sp-2h); flex-shrink:0}
.logo{
  width:30px; height:30px; border-radius:var(--r); color:var(--t-white); font-size:var(--fs-sm); font-weight:var(--fw-black);
  background:var(--brand-grad);
  display:flex; align-items:center; justify-content:center;
}
.brand-txt{display:flex; flex-direction:column; line-height:var(--lh-tight)}
.brand-txt b{font-size:var(--fs-h3); font-weight:var(--fw-bold); letter-spacing:var(--ls-wide)}
.brand-txt span{font-size:var(--fs-xs); color:var(--t3)}

.topbar-mid{flex:1; display:flex; justify-content:center; min-width:0}
.gsearch{
  display:flex; align-items:center; gap:var(--sp-2); width:100%; max-width:520px;
  background:var(--bg-card); border:1px solid var(--line); border-radius:var(--r);
  padding:0 var(--sp-2) 0 var(--sp-3); height:34px; transition:.15s;
}
.gsearch:focus-within{border-color:var(--brand); background:var(--panel); box-shadow:0 0 0 3px var(--focus-ring)}
.gsearch svg{width:15px; height:15px; color:var(--t3); flex-shrink:0}
.gsearch input{flex:1; border:none; background:none; outline:none; font-size:var(--fs-sm); color:var(--t1); min-width:0}
.gsearch input::placeholder{color:var(--t3)}
.gsearch select{
  border:none; border-left:1px solid var(--line); background:none; outline:none; cursor:pointer;
  font-size:var(--fs-sm); color:var(--t2); padding:0 var(--sp-2); height:22px; font-family:inherit;
}

.topbar-right{display:flex; align-items:center; gap:var(--sp-4); flex-shrink:0}
.dsrc{
  display:flex; align-items:center; gap:var(--sp-1h); font-size:var(--fs-xs); color:var(--t2);
  background:var(--bg-card); border:1px solid var(--line); border-radius:var(--r-lg); padding:var(--sp-1) 11px; cursor:default;
}
.dot-ok{width:6px; height:6px; border-radius:50%; background:var(--ok); flex-shrink:0}
.today{font-size:12px; color:var(--t3); white-space:nowrap; font-weight:400}
.me{display:flex; align-items:center; gap:var(--sp-2)}
.me span{font-size:var(--fs-sm); color:var(--t2); font-weight:var(--fw-medium)}
.avatar{
  width:28px; height:28px; border-radius:50%; background:var(--brand-soft); color:var(--brand);
  display:flex; align-items:center; justify-content:center; font-size:var(--fs-sm); font-weight:var(--fw-bold);
}

/* ============================ 布局 ============================ */
.layout{display:flex; height:calc(100vh - var(--topbar-h))}
.sidebar{
  width:var(--side-w); flex-shrink:0; background:var(--panel); border-right:1px solid var(--line);
  display:flex; flex-direction:column; overflow:hidden;
}
.nav{flex:1; overflow-y:auto; padding:var(--sp-3) var(--sp-2)}
.nav-group{
  font-size:11px; color:var(--t3); letter-spacing:.55px;
  padding:var(--sp-4) var(--sp-3) var(--sp-1); font-weight:600;
}
.nav-group:first-child{padding-top:var(--sp-2)}
.nav-item{
  display:flex; align-items:center; gap:var(--sp-2h); padding:var(--sp-2) var(--sp-3);
  border-radius:var(--r-sm); cursor:pointer; color:var(--t2);
  font-size:15px; margin-bottom:var(--sp-half); transition:background .15s,color .15s;
  position:relative; user-select:none; font-weight:500}
.nav-item svg{width:16px; height:16px; flex-shrink:0; opacity:.7}
.nav-item:hover{background:var(--bg-hover); color:var(--t1)}
.nav-item.on{background:var(--brand-soft); color:var(--brand); font-weight:var(--fw-bold)}
.nav-item.on svg{opacity:1}
.nav-item.on::before{
  content:""; position:absolute; left:-8px; top:50%; transform:translateY(-50%);
  width:3px; height:16px; border-radius:0 3px 3px 0; background:var(--brand);
}
.nav-badge{
  margin-left:auto; font-size:11px; color:var(--t3); font-weight:600;
  font-variant-numeric:tabular-nums;
}
.nav-item.on .nav-badge{color:var(--brand)}

.side-foot{padding:var(--sp-3); border-top:1px solid var(--line-soft)}
.side-card{background:var(--bg-card); border:1px solid var(--line); border-radius:var(--r-sm); padding:var(--sp-3)}
.side-card-t{font-size:var(--fs-xs); color:var(--t3); font-weight:var(--fw-bold); margin-bottom:var(--sp-1)}
.side-card-p{font-size:var(--fs-xs); color:var(--t2); word-break:break-all; line-height:var(--lh-normal)}

.content{
  flex:1; overflow:auto; padding:var(--sp-6);
  min-width:0;
}
.content-inner{max-width:1680px; margin:0 auto}

/* 会话到期提醒条（2026-09-15）：只在快到期时出现，不打扰日常操作 */
.sessbar{
  display:flex; align-items:center; gap:var(--sp-2);
  padding:var(--sp-2h) var(--sp-4); margin-bottom:var(--sp-4);
  background:var(--warn-soft); border:1px solid var(--warn-line); border-radius:var(--r);
  color:var(--warn-text); font-size:var(--fs-sm);
}
.sessbar::before{
  content:''; width:6px; height:6px; border-radius:50%;
  background:var(--warn); flex:none;
}

/* ============================ 页头 ============================ */
.page-head{
  display:flex; align-items:flex-end; justify-content:space-between;
  gap:var(--sp-4); margin-bottom:var(--sp-5); flex-wrap:wrap;
}
.page-head h1{font-size:24px; font-weight:700; letter-spacing:-.4px; line-height:1.15}
.page-head .ph-sub{font-size:var(--fs-sm); color:var(--t3); margin-top:var(--sp-1)}
.page-head .ph-ops{display:flex; gap:var(--sp-2); align-items:center}

/* ============================ 卡片 ============================ */
.panel{
  background:var(--panel); border:1px solid var(--line); border-radius:8px;
  box-shadow:var(--sh-1); margin-bottom:var(--sp-5); overflow:hidden; border-color:var(--line-soft)}
.panel-h{
  padding:var(--sp-4) var(--sp-5); font-size:17px; font-weight:600;
  border-bottom:1px solid var(--line-soft);
  display:flex; align-items:center; gap:var(--sp-3); min-height:52px; line-height:1.25; letter-spacing:0}
.panel-h .sub{font-size:12px; color:var(--t3); font-weight:400}
.panel-h .grow{flex:1}
.panel-b{padding:var(--sp-5)}
.toolbar{
  display:flex; flex-wrap:wrap; gap:var(--sp-2); align-items:center;
  padding:var(--sp-3) var(--sp-5); border-bottom:1px solid var(--line-soft); background:var(--bg-tint);
}

/* —— 筛选增强（2026-09-15）—— */
/* 日期区间：起止两个日期框，中间一个「至」 */
.drange{
  display:inline-flex; align-items:center; gap:var(--sp-1h);
  padding:var(--sp-pad-a) var(--sp-2) var(--sp-pad-a) var(--sp-2h); border:1px solid var(--line); border-radius:var(--r-sm);
  background:var(--bg); font-size:var(--fs-sm); color:var(--t3);
}
.drange i{font-style:normal; white-space:nowrap}
.drange b{font-weight:var(--fw-normal); color:var(--t3)}
.drange .input.sm{border:none; padding:var(--sp-half) 0; min-width:126px; background:transparent}
/* 多选标签行（营维包区这类）：点一下选中，再点一下取消 */
/* —— 筛选折叠容器 ——
   宽屏：display:contents —— 让里面的筛选控件直接当工具栏的 flex 子元素排，和原来一模一样；
   窄屏（≤768px）：整块收起，只留一个「筛选」开关，见下方媒体查询。 */
.fbar-wrap{display:contents}
.fbar-t{display:none}
.fchip-row{
  display:flex; flex-wrap:wrap; align-items:center; gap:var(--sp-1h);
  padding:var(--sp-2) var(--sp-5); border-bottom:1px solid var(--line-soft); background:var(--bg-tint);
}
.fchip-k{font-size:var(--fs-sm); color:var(--t3); margin-right:var(--sp-half); flex:none}
.fchip{
  font:inherit; font-size:var(--fs-sm); cursor:pointer; white-space:nowrap;
  padding:var(--sp-pad-b) var(--sp-3); border-radius:var(--r-lg); border:1px solid var(--line);
  background:var(--bg); color:var(--t2); transition:all .12s;
}
.fchip:hover{border-color:var(--brand); color:var(--brand)}
.fchip.on{background:var(--brand); border-color:var(--brand); color:var(--t-white); font-weight:var(--fw-medium)}
.fchip.clear{border-style:dashed; color:var(--t3)}

/* 栅格：按分辨率自适应 */
.grid{display:grid; gap:var(--sp-5); margin-bottom:var(--sp-5)}
.g2{grid-template-columns:repeat(2,minmax(0,1fr))}
.g3{grid-template-columns:repeat(3,minmax(0,1fr))}
.g4{grid-template-columns:repeat(4,minmax(0,1fr))}
@media(max-width:1560px){ .g4{grid-template-columns:repeat(2,minmax(0,1fr))} }
@media(max-width:1400px){ .g3{grid-template-columns:repeat(2,minmax(0,1fr))} }
@media(max-width:1100px){ .g2,.g3,.g4{grid-template-columns:minmax(0,1fr)} }

/* ============================ KPI ============================ */
.kpi{
  background:var(--panel); border:1px solid var(--line); border-radius:8px;
  padding:var(--sp-4) var(--sp-5); box-shadow:var(--sh-1);
  display:flex; align-items:center; gap:var(--sp-4); position:relative; overflow:hidden;
  cursor:pointer; transition:transform .18s ease, box-shadow .18s ease; border-color:var(--line-soft)}
.kpi:hover{transform:translateY(-1px); box-shadow:var(--sh-2)}
.kpi::before{content:""; position:absolute; left:0; top:0; bottom:0; width:3px; background:var(--c,var(--gray))}
.kpi-ic{
  width:42px; height:42px; border-radius:var(--r); flex-shrink:0;
  background:var(--c-soft,var(--gray-soft)); color:var(--c,var(--gray));
  display:flex; align-items:center; justify-content:center;
}
.kpi-ic svg{width:20px; height:20px}
.kpi-body{flex:1; min-width:0}
.kpi-label{font-size:12px; color:var(--t3); font-weight:500; letter-spacing:.4px}
.kpi-value{font-size:34px; font-weight:700; line-height:1.05; margin-top:var(--sp-half); letter-spacing:var(--ls-num); font-variant-numeric:tabular-nums}
.kpi-sub{font-size:12px; color:var(--t3); margin-top:var(--sp-half); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; font-weight:400}
.kpi-sub b{color:var(--t2); font-weight:var(--fw-bold)}
.c-blue{--c:var(--brand);--c-soft:var(--brand-soft)}
.c-green{--c:var(--ok);--c-soft:var(--ok-soft)}
.c-red{--c:var(--danger);--c-soft:var(--danger-soft)}
.c-orange{--c:var(--warn);--c-soft:var(--warn-soft)}
.c-purple{--c:var(--purple);--c-soft:var(--purple-soft)}
.c-teal{--c:var(--teal);--c-soft:var(--teal-soft)}
.c-gray{--c:var(--gray);--c-soft:var(--gray-soft)}

/* ============================ 图表 ============================ */
.chart-row{display:flex; align-items:center; gap:var(--sp-3); margin-bottom:var(--sp-3)}
.chart-row:last-child{margin-bottom:0}
.chart-row .lb{width:78px; font-size:var(--fs-sm); color:var(--t2); flex-shrink:0; text-align:right;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.chart-row .bar{flex:1; height:20px; background:var(--bg-bar); border-radius:var(--r-sm); overflow:hidden}
.chart-row .bar i{display:block; height:100%; border-radius:var(--r-sm); transition:width .6s cubic-bezier(.3,1,.4,1)}
.chart-row .vl{width:96px; font-size:var(--fs-sm); color:var(--t2); flex-shrink:0; font-variant-numeric:tabular-nums; text-align:right}
.donut-wrap{display:flex; align-items:center; gap:var(--sp-6); flex-wrap:wrap; border-color:var(--line-soft); border-radius:8px}
.donut{position:relative; width:112px; height:112px; flex-shrink:0}
.donut svg{transform:rotate(-90deg)}
.donut .dt{position:absolute; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center}
.donut .dt b{font-size:var(--fs-num); font-weight:var(--fw-bold); font-variant-numeric:tabular-nums}
.donut .dt span{font-size:var(--fs-xs); color:var(--t3)}
.legend{display:flex; flex-direction:column; gap:var(--sp-2); font-size:12px; font-weight:400}
.legend div{display:flex; align-items:center; gap:var(--sp-2); color:var(--t2)}
.legend i{width:9px; height:9px; border-radius:2px; flex-shrink:0}

/* ============================ 表格 ============================ */
.tb-scroll{overflow:auto; max-height:calc(100vh - 300px); min-height:120px}
.tb{width:100%; border-collapse:separate; border-spacing:0; font-size:15px; white-space:nowrap; word-break:keep-all; overflow-wrap:normal; font-weight:400; line-height:1.5; border:1px solid var(--line-soft); border-radius:8px}
.tb th{
  background:var(--bg-tint); padding:6px 10px; text-align:left; color:var(--t3);
  font-weight:500; font-size:12px; border-bottom:1px solid var(--line);
  position:sticky; top:0; z-index:2; white-space:nowrap; letter-spacing:.4px; border-right:none; border-top:none}
/* 各模块列表一律不换行（2026-09-23）：一行一条，超出省略号截断，
   完整内容点「详情」看。max-width 收窄让长内容更早截断。 */
.tb td{
  padding:5px 10px; border-bottom:1px solid var(--line-soft);
  vertical-align:middle; height:36px; max-width:180px; overflow:hidden; text-overflow:ellipsis; font-size:15px; font-weight:400; line-height:1.5; color:var(--t1); border-right:none; border-top:none}
.tb tbody tr{transition:background .12s}
.tb tbody{background:var(--bg-card)}
/* 行底（2026-09-23）：暖纸底透上来会发「卡其」，丑。
   表格统一铺干净白，斑马纹用中性冷灰一档，不再带黄。 */
.tb tbody tr{background:#fff}
.tb tbody tr:nth-child(even){background:#f7f8fa}
.tb tbody tr:hover{background:#eef4fb}
.tb tbody tr:last-child td{border-bottom:none}
.tb .num{text-align:right; font-variant-numeric:tabular-nums}
/* 时间戳：禁止折行 —— 以前 `2026-09-22T17:59:23` 会在 T 处断成两行，把整行撑高 */
.tb .ts, .tb td .ts{white-space:nowrap; font-variant-numeric:tabular-nums}
/* 空值占位符：淡灰短横，比纯空白整齐，也不会被误认成数据 */
.tb .nil{color:var(--t3); opacity:.55}
.tb .mid{text-align:center}
.sortable{cursor:pointer; user-select:none}
.sortable:hover{color:var(--brand)}
.ellipsis{max-width:180px; overflow:hidden; text-overflow:ellipsis}
.ops{text-align:right; width:1%; white-space:nowrap}
/* 操作按钮横排：以前在窄列里会竖着堆 4 个（详情/闭环/编辑/删除），把行高顶到 4 倍。
   ⚠ 不能吃 .tb td 的 overflow:hidden + max-width:180px —— 那套是给长文本截断用的，
   套到按钮上会把操作列**整排裁掉**（2026-09-23 网页端看不到操作按钮的元凶）。 */
.ops{display:flex; flex-wrap:nowrap; justify-content:flex-end; gap:4px;
  overflow:visible !important; max-width:none !important;
  min-width:230px !important; width:auto !important}
.ops .btn{flex:0 0 auto}
.ops .btn+.btn{margin-left:0}
/* 筛选区下拉给最小宽度，「闭环状态（全部）」这类长标签别被切成两半 */
.tb-tools select, .tb-tools .input, .tools select{min-width:132px}
.empty{padding:var(--sp-7) var(--sp-5); text-align:center; color:var(--t3); font-size:12px; font-weight:400}
.empty svg{width:40px; height:40px; opacity:.28; margin:0 auto var(--sp-3)}
.empty div{font-size:var(--fs-body)}
.err{color:var(--danger)} .ok{color:var(--ok)} .muted{color:var(--t3)}

.pager{
  display:flex; align-items:center; gap:var(--sp-3); padding:var(--sp-3) var(--sp-5);
  border-top:1px solid var(--line-soft); color:var(--t3); font-size:12px; background:var(--bg-tint); font-weight:400}
.pager .grow{flex:1}
.pager .pg-info{font-variant-numeric:tabular-nums}

/* ============================ 控件 ============================
   V28（UI 规范统一）按钮族：三档尺寸（sm 28 / 默认 --ctl-h 44 / lg 46），
   统一圆角 --r-sm、统一字重 --fw-bold、统一过渡 .15s；
   状态齐全：hover（描边转品牌色）/ active（按压 + 底色）/ disabled（降透明 + 禁指针）。
   所有颜色、尺寸、间距一律走变量，禁止再写裸值。 */
.btn{
  border:1px solid var(--line); background:var(--panel); color:var(--t2);
  height:var(--ctl-h); padding:0 var(--sp-4); border-radius:8px; cursor:pointer;
  font-size:15px; font-weight:500; font-family:inherit; transition:.15s;
  display:inline-flex; align-items:center; justify-content:center;
  gap:var(--sp-1h); line-height:var(--lh-normal); white-space:nowrap; letter-spacing:.1px}
.btn:hover{border-color:var(--brand); color:var(--brand); background:var(--bg-tint)}
/* V27：主按钮改用微信绿（行动色），与「信息色」蓝区分开 —— 一支按钮一眼看出是「主操作」 */
.btn.primary{background:var(--wx-green); border-color:transparent; color:var(--t-white); font-weight:var(--fw-bold); box-shadow:0 2px 6px rgba(7,193,96,.22); border-radius:8px}
.btn.primary:hover{background:var(--green-hi); border-color:transparent; color:var(--t-white); box-shadow:0 3px 10px rgba(7,193,96,.28)}
.btn.danger:hover{border-color:var(--danger); color:var(--danger); background:var(--panel)}
.btn.sm{height:30px; padding:0 var(--sp-3); font-size:12px; border-radius:8px; font-weight:500}
.btn.lg{height:46px; padding:0 var(--sp-5); font-size:15px; border-radius:8px}
/* 禁用态：三档统一（含主按钮）—— 降透明 + 禁指针 + 取消按压动画 */
.btn[disabled],.btn[disabled]:hover,.btn.primary[disabled],.btn.primary[disabled]:hover{
  opacity:.42; cursor:not-allowed; box-shadow:none;
}
.btn[disabled]:hover{border-color:var(--line); color:var(--t2); background:var(--panel)}
.btn.primary[disabled]:hover{border-color:var(--wx-green); color:var(--t-white); background:var(--wx-green)}
/* 按下反馈：手机/鼠标按下时轻微缩一下，操作更有手感（2026-09-15 V10 UI 统一） */
.btn:not([disabled]):active{transform:scale(.965)}
/* V27：按下态底色加深（微信风按压反馈，弥补手机上 :hover 摸不到） */
.btn:not([disabled]):active{background:var(--line-soft)}
.btn.primary:not([disabled]):active{background:var(--green-hi)}
.btn-ghost:active{background:var(--line-soft)}
.btn svg{width:14px; height:14px}

/* ============================================================
   V16 按钮式单选组：短枚举（2~4 项）用它替代下拉，点一下就选
   选中态 = 品牌浅底 + 品牌描边 + 加粗；整组禁用时变灰
   ============================================================ */
.rbtn-group{display:flex; flex-wrap:wrap; gap:var(--sp-2)}
.rbtn{
  height:var(--ctl-h); padding:0 var(--sp-4);
  border:1px solid var(--line); border-radius:8px;
  background:var(--panel); color:var(--t2);
  font-size:15px; font-family:inherit; cursor:pointer;
  transition:.15s; white-space:nowrap;
  display:inline-flex; align-items:center; justify-content:center; font-weight:500}
.rbtn:hover{border-color:var(--brand); color:var(--brand)}
.rbtn:not([disabled]):active{transform:scale(.97)}
.rbtn.on{
  background:var(--brand-soft); border-color:var(--brand);
  color:var(--brand); font-weight:var(--fw-bold);
}
.rbtn[disabled]{opacity:.4; cursor:not-allowed}
/* 联动禁用：整组变灰且不可点（syncForm 给 .rbtn-group 加 .dis） */
.rbtn-group.dis .rbtn{
  opacity:.45; cursor:not-allowed; background:var(--line-soft);
  border-color:var(--line); color:var(--t3);
}
.rbtn-group.dis .rbtn:hover{border-color:var(--line); color:var(--t3)}

.input{
  border:1px solid var(--line); border-radius:var(--r-sm); padding:0 var(--sp-3);
  height:var(--ctl-h); font-size:15px; width:100%;
  background:var(--panel); color:var(--t1);
  font-family:inherit; transition:.15s; font-weight:400; line-height:1.4}
/* 多行文本不套固定高度，交给 rows 决定 */
textarea.input{height:auto; padding:var(--sp-2) var(--sp-3); line-height:var(--lh-normal); resize:vertical}
.input:focus{outline:none; border-color:var(--brand); box-shadow:0 0 0 3px var(--focus-ring)}
.input.sm{width:auto; min-width:120px; padding:var(--sp-1h) var(--sp-3)}
.input::placeholder{color:var(--t3)}
select.input{
  appearance:none; cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%238b97ad' fill='none' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 10px center; padding-right:28px;
}
textarea.input{resize:vertical; min-height:64px; line-height:var(--lh-normal)}
/* 多值标签输入 */
.tag-input{
  border:1px solid var(--line); border-radius:var(--r-sm); padding:var(--sp-1) var(--sp-3);
  min-height:var(--ctl-h); width:100%; background:var(--panel); color:var(--t1);
  display:flex; flex-wrap:wrap; gap:var(--sp-1h); align-items:center; cursor:text;
  transition:.15s;
}
.tag-input:focus-within{outline:none; border-color:var(--brand); box-shadow:0 0 0 3px var(--focus-ring)}
.ti-tag{
  display:inline-flex; align-items:center; gap:var(--sp-1); padding:var(--sp-half) var(--sp-2);
  background:var(--brand-soft); color:var(--brand); border-radius:var(--r-lg);
  font-size:var(--fs-sm); line-height:var(--lh-normal);
}
.ti-tag i{font-style:normal; cursor:pointer; color:var(--brand-hi); font-weight:var(--fw-black)}
.ti-in{border:none; background:transparent; outline:none; flex:1; min-width:80px; font-size:var(--fs-body); color:var(--t1); height:28px}
.ti-in::placeholder{color:var(--t3)}
.chk{display:inline-flex; align-items:center; gap:var(--sp-1h); font-size:var(--fs-sm); color:var(--t2); cursor:pointer}
.chk input{accent-color:var(--brand); width:15px; height:15px; cursor:pointer; margin:0}
.hint{color:var(--t3); font-size:12px; line-height:var(--lh-loose); font-weight:400}
.hint-box{
  background:var(--bg-note); border:1px solid var(--line); border-left:3px solid var(--brand);
  border-radius:8px; padding:var(--sp-3) var(--sp-4); color:var(--t2); font-size:var(--fs-sm); line-height:var(--lh-loose); border-color:var(--line-soft)}
.hint-box + .hint-box{margin-top:var(--sp-2)}
.hint-box.ok-line{border-left-color:var(--ok); background:var(--ok-soft)}
.hint-box.err-line{border-left-color:var(--danger); background:var(--danger-soft)}
.warn-line{margin-top:var(--sp-1h); color:var(--warn-text-2)}

/* 禁用的表单项（联动置灰） */
.input:disabled, .input[readonly]{
  background:var(--bg-disabled); color:var(--t-disabled); cursor:not-allowed;
}
/* 重点跟进项：天翼 + 续约，整行高亮 */
.tb tbody tr.row-focus{background:var(--warn-soft) !important}
.tb tbody tr.row-focus:hover{background:var(--warn-line-soft) !important}
.tb tbody tr.row-focus td:first-child{box-shadow:inset 3px 0 0 var(--warn)}

/* ============================ 标签 ============================ */
.tag{
  display:inline-block; padding:var(--sp-half) var(--sp-pad-d); border-radius:var(--r-lg); font-size:12px;
  background:var(--gray-soft); color:var(--t2); white-space:nowrap; font-weight:500; line-height:1.5; letter-spacing:.3px}
.tag.t-red{background:var(--danger-soft); color:var(--danger)}
.tag.t-green{background:var(--ok-soft); color:var(--ok)}
.tag.t-blue{background:var(--brand-soft); color:var(--brand)}
.tag.t-orange{background:var(--warn-soft); color:var(--warn-text-2)}
.tag.t-purple{background:var(--purple-soft); color:var(--purple)}
.tag.t-teal{background:var(--teal-soft); color:var(--teal)}
.tag.t-gray{background:var(--gray-soft); color:var(--gray)}
/* 已驳回：跟「待处理」的淡红区分开，实心红 —— 一眼看出是被打回的 */
.tag.t-reject{background:var(--danger); color:var(--t-white)}

/* ---- 商机「闭环」四值的底色（2026-09-23）----
   下拉选项以前一律系统灰，四个状态看着一样、也分不出轻重。
   现在按语义上底色（和 .tag 的 t-teal / t-green / t-orange / t-red 同一套），
   展开下拉时每项就是一块彩色底，选中值在收起状态也有色。 */
select option[value="跟踪中"]{background:var(--teal-soft);  color:var(--teal)}
select option[value="办理"]{background:var(--ok-soft);      color:var(--ok)}
select option[value="已甩单"]{background:var(--warn-soft);    color:var(--warn-text-2)}
select option[value="未办理"]{background:var(--danger-soft);  color:var(--danger)}
/* 收起状态下选中项跟着变色：用 :has() 直接命中「哪个选项被选中」，不用动 JS。
   （Chrome 105+ / Safari 15.4+ / Firefox 121+ 支持；不支持的浏览器就是普通灰底，不影响功能） */
select:has(option[value="跟踪中"]:checked) {background:var(--teal-soft);   color:var(--teal)}
select:has(option[value="办理"]:checked)   {background:var(--ok-soft);     color:var(--ok)}
select:has(option[value="已甩单"]:checked) {background:var(--warn-soft);   color:var(--warn-text-2)}
select:has(option[value="未办理"]:checked) {background:var(--danger-soft); color:var(--danger)}

/* ---- 闭环信息块（详情页 / 闭环弹窗里展示闭环人、时间、备注）---- */
.close-box{
  border:1px solid var(--line); border-radius:var(--r); background:var(--bg-soft);
  padding:var(--sp-3) var(--sp-4); margin-top:var(--sp-3);
}
.close-box .cb-t{font-size:var(--fs-sm); font-weight:var(--fw-bold); color:var(--t1); margin-bottom:var(--sp-1h)}
.close-box .cb-r{display:flex; gap:var(--sp-2h); font-size:var(--fs-sm); padding:var(--sp-pad-a) 0}
.close-box .cb-k{width:70px; flex:none; color:var(--t3)}
.close-box .cb-v{flex:1; color:var(--t1); word-break:break-all; white-space:pre-wrap}

/* —— 详情弹窗的字段网格（原来只有结构没有样式，补上）—— */
/* 详情弹窗（2026-09-23 收紧）：手机上点进详情要滑很久，做三件事 ——
   ① 保持两列（手机也两列），字段高度直接减半
   ② 行内边距/字号收紧，值一律单行省略号（完整值鼠标悬停 title 看）
   ③ 空字段默认折叠（.det-empty），底部「展开其余 N 项」再看 */
.detail-grid{
  display:grid; grid-template-columns:repeat(2,minmax(0,1fr));
  gap:0 var(--sp-4);
}
.det-row{
  display:flex; align-items:baseline; gap:var(--sp-2);
  padding:5px 0; border-bottom:1px dashed var(--line-soft);
  font-size:var(--fs-sm); min-width:0;
}
.det-k{flex:0 0 64px; color:var(--t3); font-size:11px; font-weight:400; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.det-v{flex:1; min-width:0; color:var(--t1); white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.detail-grid:not(.show-empty) .det-empty{display:none}

/* ============================ 表单 ============================ */
.form-grid{display:grid; grid-template-columns:1fr 1fr; gap:var(--sp-4)}
.fld.full{grid-column:1/3}
.fld label{display:block; font-size:var(--fs-label); color:var(--t2); margin-bottom:5px; font-weight:var(--fw-medium)}
.fld label .req{color:var(--danger); margin-left:var(--sp-half)}
.sec-title{
  grid-column:1/3; font-size:15px; color:var(--brand); font-weight:600;
  border-top:1px solid var(--line-soft); margin-top:var(--sp-2); padding-top:var(--sp-4); letter-spacing:0}
.sec-title:first-child{border-top:none; margin-top:0; padding-top:0}

/* ============================ 弹窗 ============================ */
.mask{
  position:fixed; inset:0; background:var(--scrim); backdrop-filter:blur(2px);
  display:flex; align-items:center; justify-content:center; z-index:60; animation:fade .18s;
}
@keyframes fade{from{opacity:0}to{opacity:1}}
@keyframes pop{from{opacity:0;transform:translateY(12px) scale(.98)}to{opacity:1;transform:none}}
.modal{
  background:var(--panel); border-radius:var(--r-lg); width:800px; max-width:94vw; max-height:88vh;
  display:flex; flex-direction:column; box-shadow:var(--sh-3); animation:pop .2s;
}
.modal-head{
  padding:var(--sp-4) var(--sp-5); border-bottom:1px solid var(--line-soft);
  font-weight:600; font-size:17px; display:flex; justify-content:space-between; align-items:center; line-height:1.25; letter-spacing:0}
.modal-body{padding:var(--sp-5); overflow:auto}
.modal-foot{
  padding:var(--sp-3) var(--sp-5); border-top:1px solid var(--line-soft);
  display:flex; gap:var(--sp-2); justify-content:flex-end; background:var(--bg-tint);
}
.x{background:none; border:none; font-size:var(--fs-xl); color:var(--t3); cursor:pointer; line-height:var(--lh-none); padding:0 var(--sp-1)}
.x:hover{color:var(--t1)}

/* ============================ 页签 ============================ */
.tabs{display:flex; gap:var(--sp-1); padding:0 var(--sp-5); border-bottom:1px solid var(--line-soft); background:var(--bg-tint)}
.tab{
  padding:var(--sp-3) var(--sp-4); cursor:pointer; color:var(--t3); font-size:15px;
  border-bottom:2px solid transparent; margin-bottom:-1px; transition:.15s; user-select:none; font-weight:600; border-bottom-color:var(--line-soft) }
.tab:hover{color:var(--t2)}
.tab.on{color:var(--brand-deep); font-weight:var(--fw-bold); border-bottom-color:var(--cinnabar)}
.tab .n{font-size:var(--fs-xs); color:var(--t3); margin-left:5px; font-variant-numeric:tabular-nums}
.tab.on .n{color:var(--brand)}

/* ============================ 导入页 ============================ */
.step{display:flex; gap:var(--sp-4); padding:var(--sp-5); border-bottom:1px solid var(--line-soft); border-color:var(--line-soft); border-radius:8px}
.step:last-child{border-bottom:none}
.step-n{
  width:24px; height:24px; border-radius:50%; background:var(--brand-soft); color:var(--brand);
  display:flex; align-items:center; justify-content:center; font-size:var(--fs-sm); font-weight:var(--fw-bold); flex-shrink:0;
}
.step-b{flex:1; min-width:0}
.step-t{font-weight:600; font-size:15px; margin-bottom:var(--sp-1); letter-spacing:0}
.step-d{color:var(--t3); font-size:var(--fs-sm); margin-bottom:var(--sp-3); line-height:var(--lh-loose)}
.step-d b{color:var(--t2)}
.res-box{
  background:var(--bg-note); border:1px solid var(--line); border-radius:var(--r-sm);
  padding:var(--sp-3) var(--sp-4); font-size:var(--fs-sm); line-height:var(--lh-loose); margin-top:var(--sp-3);
  font-family:var(--ff-mono); white-space:pre-wrap; max-height:280px; overflow:auto;
}

/* ============================ toast ============================ */
/* V27 微信风：深色半透明圆角胶囊，居中 —— 成功/失败都用同一底色，
   靠一个左侧色点区分，避免整条亮红亮绿在深色底上太刺眼。 */
.toast{
  position:fixed; left:50%; top:50%; transform:translate(-50%,-50%) scale(.96);
  padding:var(--sp-3) var(--sp-5); border-radius:var(--r); font-size:var(--fs-body);
  background:var(--overlay-toast); color:var(--t-white); max-width:78vw; text-align:center;
  opacity:0; pointer-events:none; transition:.22s cubic-bezier(.3,1,.4,1);
  z-index:99; box-shadow:var(--sh-3);
}
.toast.show{opacity:1; transform:translate(-50%,-50%) scale(1)}
.toast.bad{background:var(--overlay-toast-bad)}
.toast.bad::before{content:''; display:inline-block; width:6px; height:6px; border-radius:50%;
  background:var(--danger); margin-right:var(--sp-2); vertical-align:middle}

/* ===== 登录页 ===== */
#loginwrap{position:fixed;inset:0;z-index:200;display:flex;align-items:center;justify-content:center;
  background:linear-gradient(150deg,#eaf1fb 0%,#f7f9fc 55%,#eef3fa 100%);}
/* V10（2026-09-15）：登录页字号/圆角全部并入设计变量体系（此前是一套 19/15/14/13/12 + 9px 圆角的硬编码）。
   输入框提到 15px：手机上聚焦不再触发 iOS 自动放大（<16px 会缩放页面），桌面上也更易读。 */
.login-card{width:340px;background:var(--panel);border-radius:var(--r-lg);padding:var(--sp-7) 30px var(--sp-6);
  box-shadow:0 18px 50px rgba(20,45,90,.14);text-align:center;}
.login-logo{width:56px;height:56px;margin:0 auto var(--sp-3h);border-radius:var(--r-lg);color:var(--t-white);font-size:var(--fs-num);font-weight:var(--fw-black);
  display:flex;align-items:center;justify-content:center;background:var(--brand-grad-lg);}
.login-t{font-size:var(--fs-xl);font-weight:var(--fw-black);color:var(--brand-deep);margin-bottom:var(--sp-1)}
.login-s{font-size:var(--fs-body);color:var(--t3);margin-bottom:22px}
.login-input{width:100%;height:44px;margin-bottom:var(--sp-3);padding:0 var(--sp-pad-e);font-size:var(--fs-lg);
  border:1px solid var(--line-strong);border-radius:0;outline:none;box-sizing:border-box;transition:.15s}
.login-input:focus{border-color:var(--login-brand);box-shadow:0 0 0 3px var(--login-ring)}
.login-btn{width:100%;height:44px;border:0;border-radius:var(--r);color:var(--t-white);font-size:var(--fs-lg);font-weight:var(--fw-bold);cursor:pointer;
  background:var(--brand-grad-lg);transition:.15s}
.login-btn:hover{filter:brightness(1.07)}
.login-btn:active{transform:scale(.985)}
.login-err{min-height:18px;margin-top:var(--sp-2h);font-size:var(--fs-body);color:var(--danger)}
.login-tip{margin-top:var(--sp-1h);font-size:var(--fs-sm);color:var(--t3)}

/* 顶栏小按钮（改密码 / 退出） */
.btn-ghost{
  padding:6px 10px;
  font-size:12px;
  color:var(--t2);
  background:transparent;
  border:1px solid transparent;
  border-radius:8px;
  cursor:pointer;
  white-space:nowrap;
  transition:.15s; border-color:transparent; font-weight:500}
.btn-ghost:hover{border-color:transparent; color:var(--brand)}
.btn-ghost:active{transform:scale(.965)}
.btn-ghost:hover{color:var(--brand); border-color:transparent; background:var(--brand-soft)}

/* ==========================================================================
   顶部加载条（请求超过 220ms 才显示，不闪屏）
   ========================================================================== */
.loading{
  position:fixed; left:0; top:0; width:100%; height:2.5px; z-index:120;
  pointer-events:none; opacity:0; transition:opacity .2s; overflow:hidden;
}
.loading.show{opacity:1}
.loading.show::after{
  content:""; position:absolute; top:0; height:100%; width:36%; border-radius:0 3px 3px 0;
  background:linear-gradient(90deg,var(--brand),#6fb3ff);
  animation:ldslide 1s linear infinite;
}
@keyframes ldslide{0%{left:-38%}100%{left:100%}}

/* ==========================================================================
   移动端 / 平板适配（2026-09-15）
   断点：900px = 外壳（顶栏两行 + 侧栏转横向条）
        768px = 内容（表格转卡片 + 表单单列 + 弹窗底部升起）
        480px = 手机小屏（卡片字段改为上下排 + 底部按钮铺满）
   ========================================================================== */
@media (max-width:900px){
  html,body{height:auto}
  body{overflow-x:hidden}

  /* —— 顶栏：两行，第一行品牌+账号，第二行全局搜索 —— */
  .topbar{
    height:auto; min-height:52px; flex-wrap:wrap;
    gap:var(--sp-2); padding:var(--sp-2) var(--sp-3);
  }
  .topbar-mid{order:3; flex:1 1 100%; max-width:none}
  .gsearch{max-width:none; height:44px}
  .gsearch input{font-size:var(--fs-16)}          /* 16px：iOS 聚焦时不自动放大 */
  .login-input{font-size:var(--fs-16)}            /* 同上：登录框手机上聚焦不缩放页面 */
  .topbar-right{gap:var(--sp-2); margin-left:auto}
  .topbar-right .today,.topbar-right .dsrc{display:none}
  .brand-txt span{display:none}
  .me span{display:none}

  /* —— 侧栏：由左侧竖条改为顶部横向可滑导航 —— */
  .layout{flex-direction:column; height:auto}
  .sidebar{
    width:100%; height:auto; flex-shrink:0;
    border-right:none; border-bottom:1px solid var(--line);
    position:sticky; top:0; z-index:30;
  }
  .nav{
    display:flex; gap:var(--sp-1h); padding:var(--sp-2) var(--sp-3);
    overflow-x:auto; overflow-y:hidden; -webkit-overflow-scrolling:touch;
  }
  .nav::-webkit-scrollbar{height:0}
  .nav-group{display:none}
  .nav-item{
    margin:0; flex-shrink:0; padding:var(--sp-2) var(--sp-pad-e);
    border:1px solid var(--line); border-radius:var(--r-lg); background:var(--panel);
  }
  .nav-item.on{border-color:var(--brand)}
  .nav-item.on::before{display:none}
  .nav-badge{margin-left:var(--sp-half)}
  .side-foot{display:none}

  .content{overflow:visible; height:auto; padding:var(--sp-4)}
  .content-inner{max-width:none}

  /* —— 触控尺寸：手机上要一根手指点得准，按钮 / 输入框统一 44px —— */
  .btn{min-height:44px; padding:var(--sp-2h) var(--sp-4)}
  .btn.sm{min-height:44px; padding:var(--sp-2) var(--sp-3h); font-size:var(--fs-sm)}
  .btn.lg{min-height:48px}
  .btn-ghost{min-height:44px; padding:var(--sp-2) var(--sp-3)}
  /* V31（C-4）：iOS Safari 聚焦字号 <16px 的输入框时会自动放大整页，
     放大后常常回不去，手机上表现为「点一下输入框页面就炸开」。
     这里把移动端所有输入类控件统一到 16px：基础 .input、select / textarea、
     弹窗内的 .modal .input（提高特异性，防止被后面更具体的规则盖回去），
     以及标签输入里的 .ti-in（原先跟着 --fs-md 走，是 15px）。 */
  .input, select.input, textarea.input{font-size:var(--fs-16)}
  .modal .input, .modal select.input, .modal textarea.input{font-size:var(--fs-16)}
  .ti-in{font-size:var(--fs-16)}
  .input{min-height:44px}
  .input.sm{min-height:44px; width:100%; min-width:0; font-size:var(--fs-16)}
  .toolbar .input.sm{flex:1 1 150px; width:auto; min-width:0; font-size:var(--fs-16)}
  .chk input{width:20px; height:20px}
  .pager{flex-wrap:wrap}

  /* —— 页签：个数多的时候横向滑，不挤压文字 —— */
  .tabs{overflow-x:auto; overflow-y:hidden; -webkit-overflow-scrolling:touch}
  .tabs::-webkit-scrollbar{height:0}
  .tab{flex-shrink:0; padding:var(--sp-3) var(--sp-3h)}

  /* —— 筛选标签：加大点击面积 —— */
  .fchip{padding:var(--sp-2) var(--sp-3h)}
  /* —— 日期区间：两个日期框各占一半，避免挤成一团 —— */
  .drange{width:100%; padding:var(--sp-1h) var(--sp-2h)}
  .drange .input.sm{min-width:0; flex:1 1 0}
}

@media (max-width:768px){
  /* —— 页头：标题一行，操作按钮换行铺满 —— */
  .page-head{flex-direction:column; align-items:stretch; gap:var(--sp-3); margin-bottom:var(--sp-4)}
  .page-head h1{font-size:var(--fs-lg)}
  .page-head .ph-ops{flex-wrap:wrap; gap:var(--sp-2)}
  .page-head .ph-ops .btn{flex:1 1 auto; justify-content:center; min-width:104px}
  .toolbar{padding:var(--sp-3)}

  /* —— 表格 → 卡片：字段名用 td 上的 data-t 显示在左侧 —— */
  .tb-scroll{overflow:visible; max-height:none}
  .tb-scroll .tb,
  .tb-scroll .tb tbody,
  .tb-scroll .tb tr,
  .tb-scroll .tb td{display:block; width:100%}
  .tb-scroll .tb thead{display:none}
  .tb-scroll .tb{white-space:normal; font-size:var(--fs-body)}
  .tb-scroll .tb tbody tr{
    margin:var(--sp-3); padding:var(--sp-1h) 0; background:var(--panel);
    border:1px solid var(--line); border-radius:var(--r); box-shadow:var(--sh-1);
  }
  .tb-scroll .tb tbody tr:nth-child(even){background:var(--panel)}
  .tb-scroll .tb tbody tr:hover{background:var(--panel)}
  .tb-scroll .tb tbody tr.row-focus{background:var(--warn-soft) !important; border-color:var(--line-warn-strong)}
  .tb-scroll .tb tbody tr.row-focus td:first-child{box-shadow:none}
  .tb-scroll .tb td{
    display:flex; align-items:baseline; justify-content:space-between; gap:var(--sp-4);
    height:auto; max-width:none; padding:var(--sp-1h) var(--sp-3h); border-bottom:none;
    white-space:normal; word-break:break-word; text-align:right;
  }
  .tb-scroll .tb td::before{
    content:attr(data-t); flex:0 0 38%; text-align:left;
    color:var(--t3); font-size:var(--fs-xs); font-weight:var(--fw-bold);
  }
  .tb-scroll .tb td.num{text-align:right}
  .tb-scroll .tb td.ops{
    justify-content:flex-start; text-align:left; flex-wrap:wrap; gap:var(--sp-2);
    margin-top:var(--sp-1h); padding-top:var(--sp-2h); border-top:1px solid var(--line-soft);
  }
  .tb-scroll .tb td.ops::before{content:"操作"; flex:0 0 auto; align-self:center}
  .tb-scroll .tb td.ops .btn{min-height:34px}

  /* —— 表单：单列 —— */
  .form-grid{grid-template-columns:1fr; gap:var(--sp-3)}
  .fld.full{grid-column:auto}
  .sec-title{grid-column:auto}

  /* —— 筛选折叠：手机上默认收起下拉条件，点「筛选」再展开 —— */
  .fbar-t{
    display:inline-flex; align-items:center; justify-content:center; gap:var(--sp-1h);
    flex:0 0 auto; min-height:44px; padding:var(--sp-2) var(--sp-3h);
    font:inherit; font-size:var(--fs-sm); color:var(--t2); cursor:pointer;
    border:1px solid var(--line); border-radius:var(--r-sm); background:var(--bg);
  }
  .fbar-t svg{width:15px; height:15px}
  .fbar-t.on{border-color:var(--brand); color:var(--brand); background:var(--brand-soft); font-weight:var(--fw-bold)}
  .fbar-wrap{display:none; flex:1 1 100%}
  .fbar-wrap.open{
    display:flex; flex-wrap:wrap; gap:var(--sp-2);
    padding:var(--sp-2) 0 var(--sp-1);
    border-top:1px dashed var(--line); margin-top:var(--sp-2);
  }
  /* 展开后里面的控件各占一行更好点，日期区间铺满 */
  .fbar-wrap.open .input.sm,
  .fbar-wrap.open select.input.sm{flex:1 1 100%; width:100%}
  /* 日期区间里那两个日期框例外：还是并排，不然「至」字会掉行 */
  .fbar-wrap.open .drange .input.sm{flex:1 1 0; width:auto}

  /* —— 筛选标签行：横向滑动，不占好几行 —— */
  .fchip-row{
    flex-wrap:nowrap; overflow-x:auto; overflow-y:hidden;
    -webkit-overflow-scrolling:touch; padding:var(--sp-2) var(--sp-4);
  }
  .fchip-row::-webkit-scrollbar{height:0}
  .fchip{flex:0 0 auto}

  /* —— 详情页：字段改成两列，窄了自动单列 —— */
  .detail-grid{grid-template-columns:1fr}

  /* —— 弹窗：从底部升起，接近满屏 —— */
  .mask{align-items:flex-end; padding:0}
  .modal{
    width:100%; max-width:100vw; max-height:92vh;
    border-radius:var(--r-lg) var(--r-lg) 0 0;
    animation:sheetup .22s cubic-bezier(.2,.8,.3,1);
  }
  @keyframes sheetup{from{opacity:.4; transform:translateY(28px)}to{opacity:1; transform:none}}
  .modal-head{padding:var(--sp-4)}
  .modal-body{padding:var(--sp-4)}
  /* 底部按钮固定在弹窗底，滚动长表单时也能点到；留出 iPhone 底部安全区 */
  .modal-foot{
    flex-wrap:wrap; padding:var(--sp-3) var(--sp-4);
    padding-bottom:calc(var(--sp-3) + env(safe-area-inset-bottom, 0px));
  }
  .modal-foot .btn{flex:1 1 auto; justify-content:center; min-width:96px}
}

/* —— 手机端（≤768px）：保持表格形态、横向滚动、首列冻结的统计表 —— */
/* 2026-09-15 各包区经营概览、个人通报这类列多的统计表，卡片化后看不到列名、
   也无法横向对比，所以带 .tb-keep 的表格在手机上保持表格形态、可左右滑动、
   首列冻结。注意：这组规则只在窄屏生效，桌面端仍是原来的自适应表格。 */
@media (max-width:768px){
  .tb-scroll.tb-keep{
    overflow-x:auto; overflow-y:hidden;
    -webkit-overflow-scrolling:touch;
    max-height:none;
  }
  .tb-scroll.tb-keep .tb{
    display:table !important;
    width:auto; min-width:100%;
    white-space:nowrap;
    border-collapse:separate;
  }
  .tb-scroll.tb-keep .tb thead,
  .tb-scroll.tb-keep .tb tbody,
  .tb-scroll.tb-keep .tb tr,
  .tb-scroll.tb-keep .tb th,
  .tb-scroll.tb-keep .tb td{
    display:revert !important;
    width:auto; height:auto;
    margin:0; padding:0;
    border:none; border-radius:0;
    box-shadow:none; background:none;
    flex-direction:row; align-items:stretch;
    text-align:left; white-space:nowrap; word-break:normal;
  }
  .tb-scroll.tb-keep .tb thead{display:table-header-group !important}
  .tb-scroll.tb-keep .tb tbody{display:table-row-group !important}
  .tb-scroll.tb-keep .tb tr{
    display:table-row !important;
    margin:0 !important; padding:0 !important;
    border:none !important; border-radius:0 !important;
    box-shadow:none !important; background:none !important;
  }
  .tb-scroll.tb-keep .tb th,
  .tb-scroll.tb-keep .tb td{
    display:table-cell !important;
    padding:var(--sp-2) var(--sp-3) !important;
    border-bottom:1px solid var(--line-soft) !important;
    text-align:left !important;
  }
  .tb-scroll.tb-keep .tb td.num{text-align:right !important}
  .tb-scroll.tb-keep .tb td::before{display:none !important}
  .tb-scroll.tb-keep .tb td:first-child,
  .tb-scroll.tb-keep .tb th:first-child{
    position:sticky; left:0;
    background:var(--panel);
    z-index:2;
    box-shadow:1px 0 0 var(--line);
  }
  .tb-scroll.tb-keep .tb tr.tb-sum td{background:var(--gray-soft) !important}
  .tb-scroll.tb-keep .tb tr.tb-sum td:first-child{background:var(--gray-soft) !important}
}

/* —— 手机小屏（≤480px） —— */
@media (max-width:480px){
  .content{padding:var(--sp-3)}
  .page-head h1{font-size:var(--fs-16)}
  .page-head .ph-ops .btn{flex:1 1 100%; min-width:0}

  /* 卡片字段：标签在上、内容在下，长号码也能完整显示 */
  .tb-scroll .tb tbody tr{margin:var(--sp-2h) 0}
  .tb-scroll .tb td{
    flex-direction:column; align-items:stretch; gap:1px;
    padding:var(--sp-pad-b) var(--sp-3); text-align:left;
  }
  .tb-scroll .tb td::before{flex:none; margin-bottom:1px}
  .tb-scroll .tb td.num{text-align:left}
  .tb-scroll .tb td.ops .btn{flex:1 1 auto; justify-content:center}

  /* 闭环信息块：字段名和内容上下排 */
  .close-box .cb-r{flex-direction:column; gap:1px; padding:var(--sp-1) 0}
  .close-box .cb-k{width:auto}

  /* 导入结果统计：两列 */
  .imp-stat{grid-template-columns:repeat(2,minmax(0,1fr))}
  .imp-s .n{font-size:var(--fs-lg)}

  /* 分页：上一页/下一页铺开 */
  .pager{gap:var(--sp-2)}
  .pager .btn{flex:1 1 auto; justify-content:center}
}

/* ==========================================================================
   批量导入 + 体验统一（2026-09-15）
   拖拽上传 / 校验预览 / 结果统计 / 骨架屏 / 必填标记 / 错误文本
   ========================================================================== */

/* —— 必填星号：列表、表单、弹窗统一 —— */
.req{color:var(--danger); font-style:normal; margin-left:var(--sp-half); font-weight:var(--fw-black)}

/* —— 表格里的错误文本（失败原因列）—— */
.tb td.err{color:var(--danger); white-space:normal; text-align:left}

/* —— 结果提示行：成功 / 警告（与 .hint-box 风格一致）—— */
.ok-line{
  margin-top:var(--sp-1h); padding:var(--sp-2) var(--sp-3); font-size:var(--fs-sm);
  color:var(--ok-text); background:var(--ok-soft);
  border-left:3px solid var(--ok); border-radius:var(--r-sm);
}
.warn-line{
  padding:var(--sp-2) var(--sp-3); background:var(--warn-soft);
  border-left:3px solid var(--warn); border-radius:var(--r-sm);
}
.warn-line b{color:var(--warn-text-2)}

/* —— 单选行（重复数据处理方式 / 账号权限勾选）—— */
.rd{
  display:flex; align-items:flex-start; gap:var(--sp-2);
  font-size:var(--fs-md); color:var(--t1); cursor:pointer;
  padding:var(--sp-1h) 0; line-height:var(--lh-normal);
}
.rd input{
  width:15px; height:15px; margin:3px 0 0; flex-shrink:0;
  accent-color:var(--brand); cursor:pointer;
}
.rd span{color:var(--t2)}
.rd:hover span{color:var(--t1)}
/* 闭环弹窗：单选下面的补充说明 */
.rd-d{display:block; font-style:normal; font-size:var(--fs-xs); color:var(--t3); margin-top:var(--sp-half)}
.rd.dis{opacity:.45; cursor:not-allowed}

/* —— 区块小标题 —— */
.bi-label{
  font-size:var(--fs-sm); font-weight:var(--fw-bold); color:var(--t2);
  margin-bottom:var(--sp-1h); letter-spacing:var(--ls-wide);
}

/* —— 步骤条：1 2 3 —— */
.imp-steps{
  display:flex; flex-direction:column; gap:var(--sp-1h);
  padding:var(--sp-3) var(--sp-4); margin-bottom:var(--sp-4);
  background:var(--bg-card); border:1px solid var(--line);
  border-radius:var(--r); font-size:var(--fs-sm); color:var(--t2); line-height:var(--lh-normal);
}
.imp-steps div{display:flex; align-items:flex-start; gap:var(--sp-2)}
.imp-steps b{
  flex:0 0 18px; height:18px; border-radius:50%;
  background:var(--brand); color:var(--t-white); font-size:var(--fs-xs); font-weight:var(--fw-black);
  display:flex; align-items:center; justify-content:center; margin-top:1px;
}

/* —— 拖拽上传区 —— */
.dropzone{
  border:1.5px dashed var(--line-dash); border-radius:8px;
  background:var(--bg-tint); padding:var(--sp-6) var(--sp-5);
  text-align:center; cursor:pointer; color:var(--t3);
  transition:border-color .15s, background .15s, transform .15s; border-color:var(--line-dash)}
.dropzone:hover{border-color:var(--brand); background:var(--brand-soft)}
.dropzone.over{
  border-color:var(--brand); background:var(--brand-soft);
  transform:scale(1.006); box-shadow:0 0 0 3px var(--focus-ring);
}
.dropzone.has{border-style:solid; border-color:var(--ok); background:var(--ok-soft)}
.dropzone svg{
  width:30px; height:30px; margin:0 auto var(--sp-2); opacity:.42;
}
.dropzone.has svg{color:var(--ok); opacity:1}
.dz-t{font-size:var(--fs-md); color:var(--t1); font-weight:var(--fw-bold); margin-bottom:var(--sp-1)}
.dz-s{font-size:var(--fs-xs); color:var(--t3)}
.dz-f{
  margin-top:var(--sp-3); font-size:var(--fs-sm); color:var(--ok); font-weight:var(--fw-bold);
}
.dz-f:empty{display:none}

/* —— 结果统计卡 —— */
.imp-stat{
  display:grid; grid-template-columns:repeat(4,minmax(0,1fr));
  gap:var(--sp-3); margin-top:var(--sp-4);
}
.imp-s{
  background:var(--panel); border:1px solid var(--line);
  border-radius:var(--r); padding:var(--sp-3) var(--sp-4); text-align:center;
}
.imp-s .n{
  font-size:var(--fs-num); font-weight:var(--fw-bold); line-height:var(--lh-tight);
  color:var(--t1); font-variant-numeric:tabular-nums;
}
.imp-s .l{font-size:var(--fs-xs); color:var(--t3); margin-top:var(--sp-half)}
.imp-s.ok{border-color:var(--line-ok); background:var(--ok-soft)}
.imp-s.ok .n{color:var(--ok)}
.imp-s.bad{border-color:var(--line-bad); background:var(--danger-soft)}
.imp-s.bad .n{color:var(--danger)}

/* —— 加载中 / 出错提示块 —— */
.imp-loading{
  margin-top:var(--sp-4); padding:var(--sp-5); text-align:center;
  font-size:var(--fs-sm); color:var(--t2); background:var(--bg-card);
  border:1px solid var(--line); border-radius:var(--r);
}
.imp-loading::before{
  content:""; display:inline-block; width:13px; height:13px; margin-right:var(--sp-2);
  vertical-align:-2px; border:2px solid var(--brand);
  border-top-color:transparent; border-radius:50%;
  animation:skspin .7s linear infinite;
}
.imp-err{
  margin-top:var(--sp-4); padding:var(--sp-3) var(--sp-4);
  font-size:var(--fs-sm); color:var(--danger-text); line-height:var(--lh-loose);
  background:var(--danger-soft); border-left:3px solid var(--danger);
  border-radius:var(--r-sm);
}

/* —— 骨架屏（列表加载占位）—— */
.skel{
  display:block; height:12px; border-radius:var(--r-sm);
  background:linear-gradient(90deg,#eef1f6 25%,#e2e7ef 37%,#eef1f6 63%);
  background-size:400% 100%;
  animation:skload 1.3s ease-in-out infinite;
}
@keyframes skload{0%{background-position:100% 50%}100%{background-position:0 50%}}
@keyframes skspin{to{transform:rotate(360deg)}}
.tb td .skel{width:76%}
.tb td.ops .skel{width:64px; margin-left:auto}

/* —— 空状态：补一句下一步引导 —— */
.empty .sk-tip{font-size:var(--fs-sm); color:var(--t3); margin-top:var(--sp-1)}

/* —— 账号管理：状态徽标 —— */
.tb td .tag{min-width:auto}

/* ==========================================================================
   批量导入 · 窄屏适配（2026-09-15）
   统计卡两列、拖拽区收紧；弹窗内的表格保持表格形态（不转卡片，否则没有字段名）
   ========================================================================== */
@media (max-width:900px){
  .imp-stat{grid-template-columns:repeat(2,minmax(0,1fr))}
  .dropzone{padding:var(--sp-5) var(--sp-4)}
  .imp-steps{padding:var(--sp-3); font-size:var(--fs-md)}
}

@media (max-width:768px){
  /* 弹窗里的表格（导入结果预览 / 失败明细）：保持表格，横向滚动 */
  .modal-body .tb-scroll{overflow:auto; max-height:240px; -webkit-overflow-scrolling:touch}
  .modal-body .tb-scroll .tb{
    display:table; width:100%; min-width:480px;
    white-space:normal; font-size:var(--fs-sm);
  }
  .modal-body .tb-scroll .tb thead{display:table-header-group}
  .modal-body .tb-scroll .tb tbody{display:table-row-group}
  .modal-body .tb-scroll .tb tr{
    display:table-row; margin:0; padding:0;
    border:none; border-radius:0; box-shadow:none; background:none;
  }
  .modal-body .tb-scroll .tb td{
    display:table-cell; height:auto; max-width:none;
    padding:var(--sp-2) var(--sp-2h); border-bottom:1px solid var(--line-soft);
    text-align:left; white-space:normal; word-break:break-word;
  }
  .modal-body .tb-scroll .tb td::before{display:none}
  .modal-body .tb-scroll .tb td.num{text-align:right}
  .modal-body .tb-scroll .tb td.ops::before{display:none}
}

/* ===== 网格（营维包区）隔离 ===== */
/* 顶栏：当前账号可见的数据范围，一眼看清自己看的是哪一片 */
.zonetag{
  display:inline-flex; align-items:center; gap:var(--sp-1);
  max-width:220px; padding:var(--sp-pad-a) var(--sp-pad-d); margin-left:var(--sp-1);
  border-radius:999px; background:var(--brand-soft); color:var(--brand);
  border:1px solid rgba(22,85,200,.18);
  font-size:var(--fs-xs); font-weight:var(--fw-bold); line-height:var(--lh-tight);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.zonetag.all{background:var(--gray-soft); color:var(--t2); border-color:var(--line)}

/* 账号管理：包区多选 */
.zonepick{display:flex; flex-wrap:wrap; gap:var(--sp-2); padding:var(--sp-half) 0 0}
.zp{
  display:inline-flex; align-items:center; gap:var(--sp-1h);
  padding:var(--sp-1h) var(--sp-3); border:1px solid var(--line); border-radius:var(--r-sm);
  background:var(--panel); cursor:pointer; font-size:var(--fs-md);
  color:var(--t2); user-select:none; transition:background .15s, border-color .15s, color .15s;
}
.zp:hover{border-color:var(--brand); background:var(--brand-soft)}
.zp input{width:15px; height:15px; margin:0; accent-color:var(--brand)}
.zp:has(input:checked){
  border-color:var(--brand); background:var(--brand-soft);
  color:var(--brand); font-weight:var(--fw-bold);
}

/* ==================================================================
   V5（2026-09-15）：首页全局搜索 / 网格分组统计 / 降档总积分
   ================================================================== */

/* 首页搜索条：全局搜索不再放顶栏，只留这一处 */
.home-search{padding:var(--sp-4) var(--sp-5) var(--sp-3)}
.home-search .gsearch.lg{height:46px; max-width:none}
.home-search .gsearch.lg input{font-size:var(--fs-16)}   /* 16px：iOS 聚焦时不自动放大 */
.home-search .gsearch.lg svg{width:17px; height:17px}
.hs-tip{margin-top:var(--sp-2); font-size:var(--fs-xs); color:var(--t3)}

/* 表格：合计行 + 不换行单元格 */
.tb td.nowrap,.tb th.nowrap{white-space:nowrap}
.tb tr.tb-sum td{
  background:var(--gray-soft); border-top:2px solid var(--line);
  font-variant-numeric:tabular-nums;
}

/* 降档总积分 */
.ds-bar{display:flex; flex-wrap:wrap; align-items:center; gap:var(--sp-3); margin-bottom:var(--sp-4)}
.seg{display:inline-flex; border:1px solid var(--line-soft); border-radius:8px; overflow:hidden}
.seg-b{
  padding:var(--sp-pad-c) var(--sp-3h); border:none; background:var(--panel); color:var(--t2);
  font-size:12px; cursor:pointer; border-right:1px solid var(--line-soft); font-weight:500; border-radius:0}
.seg-b:last-child{border-right:none}
.seg-b:hover{background:var(--brand-soft)}
.seg-b.on{background:var(--brand); color:var(--t-white); font-weight:var(--fw-bold)}
.ds-sum{display:flex; flex-wrap:wrap; align-items:center; gap:var(--sp-6)}
.ds-big{display:flex; flex-direction:column; gap:6px}
.ds-big b{font-size:20px; line-height:1.15; color:var(--t1); font-variant-numeric:tabular-nums; font-weight:500}
.ds-big span{font-size:12px; color:var(--t3); font-weight:500; letter-spacing:.4px}
.ds-src{display:flex; flex-wrap:wrap; gap:var(--sp-4); font-size:12px; color:var(--t2); font-weight:400}
.ds-src b{color:var(--t1)}
.ds-src i{display:inline-block; width:8px; height:8px; border-radius:2px;
  background:var(--brand); margin-right:var(--sp-1h)}

@media (max-width:768px){
  .home-search{padding:var(--sp-3)}
  .home-search .gsearch.lg{flex-wrap:wrap; height:auto; gap:var(--sp-2); padding:var(--sp-2h)}
  .home-search .gsearch.lg input{flex:1 1 100%}
  .ds-sum{gap:var(--sp-4)}
  .ds-big b{font-size:var(--fs-num-sm)}
}

/* ==========================================================================
   V26c：手机端紧凑列表（≤768px 时由 JS 渲染，代替「一行一字段」的卡片）
   一行只放 姓名 + 账号 + 状态，一屏能看到十来个用户；点进去才展开全部字段和操作。
   ========================================================================== */
.mlist{
  display:flex; flex-direction:column;
  background:var(--panel); border-top:1px solid var(--line-soft);
}
.mlist-item{
  display:flex; align-items:center; gap:var(--sp-2h); min-height:58px;
  padding:var(--sp-pad-d) var(--sp-3h); border-bottom:1px solid var(--line-soft);
  cursor:pointer; -webkit-tap-highlight-color:transparent;
  transition:background .12s;
}
.mlist-item:active{background:var(--brand-soft)}
.mlist-item:last-child{border-bottom:none}
.mlist-hd{
  display:flex; align-items:center; padding:var(--sp-2) var(--sp-3h);
  border-bottom:1px solid var(--line-soft); background:var(--bg-tint);
  font-size:var(--fs-xs); color:var(--t3);
}
.mlist-hd .chk{display:flex; align-items:center; gap:var(--sp-1h); cursor:pointer}
.mi-av{
  flex-shrink:0; width:34px; height:34px; border-radius:50%;
  background:var(--brand-soft); color:var(--brand);
  font-size:var(--fs-sm); font-weight:var(--fw-bold);
  display:flex; align-items:center; justify-content:center;
}
.mi-main{flex:1; min-width:0}
.mi-name{
  font-size:15px; font-weight:600; color:var(--t1); line-height:1.35;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; letter-spacing:0}
.mi-sub{
  font-size:12px; color:var(--t3); margin-top:var(--sp-half); line-height:var(--lh-tight);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; font-weight:400}
.mlist-item .tag{flex-shrink:0}
.mi-arrow{width:18px; height:18px; flex-shrink:0; color:var(--t3); opacity:.7}
.mi-chk{flex-shrink:0; display:flex; align-items:center}
.mi-chk input{width:20px; height:20px}
/* 手机上把行间距放宽一点，手指更好点 */
@media (max-width:768px){
  .mlist-item{padding:var(--sp-2h) var(--sp-4)}
  .mi-av{width:38px; height:38px; font-size:var(--fs-md)}
  .mi-name{font-size:var(--fs-md)}
  .mi-sub{font-size:var(--fs-xs)}

  /* 搜索框独占一行：「筛选 / 重置」、批量操作条排到下一行，
     不再和输入框挤在同一行（以前输入框只剩一小截，打字很难受） */
  .toolbar > #modq{flex:1 1 100%; min-width:0}
  .toolbar .batch-bar{flex:1 1 100%; flex-wrap:wrap}

  /* 列表面板在手机上更像原生 App：去掉多余留白，标题行压紧一点 */
  .panel-h{padding:var(--sp-3) var(--sp-4); font-size:var(--fs-md); min-height:46px}
  .pager{padding:var(--sp-3) var(--sp-4)}
}

/* 弹窗底部错误提示：提交失败/校验不通过时显示明确原因，避免「点了没反应」的悬挂态。
   与 busy 态配合：出错时按钮已解锁，用户可直接改完再提交（可重试）。 */
.mf-err{display:none; margin-right:auto; max-width:60%; font-size:var(--fs-sm); line-height:var(--lh-tight);
  color:var(--danger); text-align:left; word-break:break-word}
.mf-err:not(:empty){display:block}
@media (max-width:768px){
  .mf-err{max-width:100%; flex:1 1 100%; margin:0 0 var(--sp-1h); font-size:var(--fs-xs)}
}

/* ==========================================================================
   V27（2026-09-16）：微信设计语言 · 双端统一
   手机端（≤768px）套微信风外壳 —— 底部 Tab 栏 + 圆角方形头像列表 +
   分组卡片 + 底部升起弹窗 + 深色胶囊 toast。
   网页端（>768px）不引入任何新结构，只跟随 :root 变量的调整。
   ========================================================================== */

/* —— 移动端底部 Tab 栏 —— */
/* 只在手机上显示（桌面端由 JS 不渲染 + 这里 display:none 双保险）。
   left/right 固定铺满，高度 50px，另加 iPhone 底部安全区。 */
.tabbar{display:none}
@media (max-width:768px){
  .tabbar{
    /* V35（P0 修复）：z-index 80 → 50。
       原值 80 高于弹窗遮罩 .mask 的 60 —— 弹窗打开时底部 Tab 栏浮在遮罩之上：
       ① 4 个 Tab 仍可点击（实测 tabbarStillClickable=true）；
       ② 弹窗底部「关闭 / 编辑 / 取消 / 保存」被 Tab 栏整条盖住，命中测试拿不到按钮本体。
       降到 50 后遮罩(60)整块压住 Tab 栏，视觉与点击两路一起解掉。
       仍高于顶栏 sticky(40)，低于遮罩(60) / 进度条(120) / toast(99) / 登录框(200)，不破坏既有层序。 */
    display:flex; position:fixed; left:0; right:0; bottom:0; z-index:50;
    background:var(--panel);
    border-top:1px solid var(--line);
    padding-bottom:env(safe-area-inset-bottom, 0px);
    box-shadow:0 -1px 6px rgba(0,0,0,.03);
  }
  .tabbar-item{
    flex:1 1 0; min-width:0; position:relative;
    height:var(--tabbar-h);
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:var(--sp-half);
    color:var(--t-mute); font-size:var(--fs-2xs); line-height:var(--lh-none); cursor:pointer;
    -webkit-tap-highlight-color:transparent; user-select:none;
    transition:color .12s;
  }
  .tabbar-item:active{background:var(--bg)}
  .tabbar-item.on{color:var(--wx-green)}
  .tabbar-item.on svg{color:var(--wx-green)}
  .tabbar-item svg{
    width:24px; height:24px; color:var(--t-mute); display:block;
    transition:color .12s;
  }
  .tabbar-item span{max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
  /* 角标：微信红点 / 计数气泡 */
  .tabbar-badge{
    position:absolute; top:3px; left:50%; margin-left:var(--sp-1h);
    min-width:16px; height:16px; padding:0 var(--sp-1); border-radius:var(--r);
    /* 角标是固定 16px 高的气泡，行高要等于 16px 才能垂直居中。
       用 --lh-normal(1.6) × --fs-2xs(10px) = 16px，渲染值与写死 16px 一致，
       但不再有裸值；（不能拿字号令牌 --fs-16 当行高用 —— 那是字号不是行高。） */
    background:var(--wechat-red); color:var(--t-white); font-size:var(--fs-2xs); line-height:var(--lh-normal);
    text-align:center; font-variant-numeric:tabular-nums;
    box-shadow:0 0 0 1.5px var(--panel);
  }
  .tabbar-badge.dot{min-width:8px; width:8px; height:8px; padding:0; border-radius:50%}
  /* 底部 Tab 栏是 fixed 的，给内容补下内边距，别让最后一行被挡住 */
  body{padding-bottom:calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px))}
  .content{padding-bottom:calc(var(--sp-4) + var(--tabbar-h) + env(safe-area-inset-bottom, 0px))}
  /* 手机上不再需要顶部横向导航条（已被底部 Tab 取代），隐藏以免重复 */
  .sidebar{display:none}
}

/* —— 微信风列表行（深化 .mlist 体系） —— */
/* 行高 ≥56px；头像 40×40 圆角方形（微信头像不是圆形）；主标题 16px、副标题 13px；
   分割线左缩进 16px（微信列表分割线不顶到左边）。 */
.mlist{background:var(--panel)}
.mlist-item{
  min-height:56px; padding:var(--sp-2h) var(--sp-4); gap:var(--sp-3);
  border-bottom:1px solid var(--line-soft);
}
.mlist-item:active{background:var(--bg)}
/* 分割线左缩进：用一条伪元素画，从 16px 起，不顶到最左 */
.mlist-item{border-bottom:none; position:relative}
.mlist-item::after{
  content:''; position:absolute; left:16px; right:0; bottom:0;
  height:1px; background:var(--line-soft);
}
.mlist-item:last-child::after{display:none}
.mi-av{
  width:40px; height:40px; border-radius:var(--r-sm);
  background:var(--wx-green); color:var(--t-white);
  font-size:var(--fs-16); font-weight:var(--fw-medium);
}
.mi-name{font-size:15px; color:var(--t1); font-weight:600; letter-spacing:0; line-height:1.35}
.mi-sub{font-size:12px; color:var(--t3); margin-top:var(--sp-half); font-weight:400}
.mi-arrow{width:16px; height:16px; color:var(--gray); opacity:1}

/* —— 微信风分组卡片（「设置」页风格） —— */
/* 圆角 8px 白卡 + 组间 8px 灰间隔 + 组内行分割线。 */
.wx-group{background:var(--panel); border-radius:var(--r); overflow:hidden; margin-bottom:var(--sp-2)}
.wx-group-t{
  padding:var(--sp-1h) var(--sp-4) var(--sp-1); font-size:var(--fs-sm); color:var(--t3);
}
.wx-row{
  display:flex; align-items:center; gap:var(--sp-3);
  min-height:52px; padding:var(--sp-2h) var(--sp-4);
  position:relative; color:var(--t1); font-size:var(--fs-16);
}
.wx-row + .wx-row::before{
  content:''; position:absolute; left:16px; right:0; top:0;
  height:1px; background:var(--line-soft);
}
.wx-row .wx-row-l{flex:1; min-width:0; color:var(--t3); font-size:var(--fs-sm)}
.wx-row .wx-row-v{flex:0 0 auto; max-width:62%; text-align:right; color:var(--t1);
  word-break:break-word}
.wx-row:active{background:var(--bg-soft)}

/* —— 移动端：列表更贴微信「整屏列表」观感（收紧左右留白，不破坏布局） —— */
@media (max-width:768px){
  .content{padding-left:0; padding-right:0}
  .content-inner{padding-left:var(--sp-3); padding-right:var(--sp-3)}
  .mlist{border-top:none}
}


/* ==========================================================================
   V33（2026-09-21）手机端首页改版 + 图标底色统一
   只在 ≤768px 生效；桌面端的布局、间距、字号一律不动。
   目标：手机上「一屏看到关键内容」，下滑距离大幅缩短。
   ========================================================================== */
@media (max-width:768px){

  /* —— 一体化顶区：问候 / 日期 / 可见范围收成一条（原来三行）—— */
  .mhero{
    display:flex; align-items:center; gap:var(--sp-2h);
    background:var(--panel); border:1px solid var(--line); border-radius:var(--r-lg);
    box-shadow:var(--sh-1); padding:var(--sp-1h) var(--sp-3); margin-bottom:var(--sp-2);
  }
  .mh-av{
    width:34px; height:34px; border-radius:50%; flex-shrink:0;
    background:var(--brand-soft); color:var(--brand);
    display:flex; align-items:center; justify-content:center;
    font-size:var(--fs-md); font-weight:var(--fw-bold);
  }
  .mh-main{flex:1; min-width:0}
  .mh-hi{
    font-size:var(--fs-md); font-weight:var(--fw-bold); line-height:var(--lh-tight);
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  .mh-sub{
    font-size:var(--fs-2xs); color:var(--t3); margin-top:2px; line-height:var(--lh-tight);
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  /* 手机上侧栏是隐藏的，「数据导入」只剩这一条快捷入口 —— 触控高度按 44px 给足 */
  .mh-btn{
    display:inline-flex; align-items:center; gap:var(--sp-half); flex-shrink:0;
    min-height:44px; padding:var(--sp-1) var(--sp-2h);
    border:1px solid var(--brand-soft); border-radius:var(--r-lg);
    background:var(--brand-soft); color:var(--brand);
    font:inherit; font-size:var(--fs-xs); font-weight:var(--fw-bold); cursor:pointer;
    -webkit-tap-highlight-color:transparent; transition:background .15s ease-out;
  }
  .mh-btn:active{background:var(--bg-hover)}
  .mh-btn svg{width:15px; height:15px}

  /* —— 搜索：一行收住（提示文案在手机上直接不渲染，改写成占位提示）—— */
  .home-search{padding:var(--sp-1h); border-radius:var(--r-lg); margin-bottom:var(--sp-2)}
  .home-search .gsearch.lg{
    height:48px; gap:var(--sp-2); padding:0 var(--sp-1h) 0 var(--sp-3);
    border-radius:var(--r-lg); border-color:var(--line-strong);
  }
  .home-search .gsearch.lg svg{width:18px; height:18px; color:var(--brand); opacity:.85}
  .home-search .gsearch.lg .btn{min-height:44px; padding:0 var(--sp-3); border-radius:var(--r)}

  /* —— KPI：两列紧凑网格（6 张 = 3 行，每张 80~88px）
         没选横向滑动条：滑动条只能露 2.2 张，另外 4 个数字被藏起来，
         支局长现场查活最怕「看不到」；两列一眼看全 6 个数，反而更省心。 */
  .grid.mkpi{grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--sp-2); margin-bottom:var(--sp-2)}
  .grid.mkpi .kpi{
    padding:var(--sp-2h) var(--sp-2h); gap:var(--sp-2h);
    min-height:80px; max-height:88px; border-radius:var(--r-lg);
  }
  .grid.mkpi .kpi:active{transform:none; box-shadow:var(--sh-1)}
  .grid.mkpi .kpi::before{display:none}          /* 小卡上左侧色条太挤，改用图标底色区分 */
  .grid.mkpi .kpi-ic{
    width:30px; height:30px; border-radius:var(--r-sm); flex-shrink:0;
    background:var(--c-soft, var(--gray-soft));              /* 老浏览器兜底 */
    background:color-mix(in srgb, var(--c, var(--gray)) 12%, #fff);
    color:var(--c, var(--gray));
    display:flex; align-items:center; justify-content:center;
  }
  .grid.mkpi .kpi-ic svg{width:17px; height:17px}
  .grid.mkpi .kpi-label{font-size:var(--fs-2xs); color:var(--t3); line-height:var(--lh-tight)}
  .grid.mkpi .kpi-value{font-size:var(--fs-num-lg); margin-top:1px}
  .grid.mkpi .kpi-sub{font-size:var(--fs-2xs); margin-top:1px; line-height:var(--lh-tight)}
  .grid.mkpi .kpi-sub b{color:var(--t1)}

  /* —— 待办提醒：四个关键数字一排，点一下直接跳 —— */
  .mtodo{margin-bottom:var(--sp-2); border-radius:var(--r-lg)}
  .mtodo-h{
    display:flex; align-items:center; gap:var(--sp-1h);
    padding:var(--sp-2h) var(--sp-3); font-size:var(--fs-sm); font-weight:var(--fw-bold);
    border-bottom:1px solid var(--line-soft);
  }
  .mtodo-h svg{width:16px; height:16px; color:var(--warn)}
  .mtodo-g{display:grid; grid-template-columns:repeat(4,minmax(0,1fr))}
  .mtodo-i{
    padding:var(--sp-2h) var(--sp-half) var(--sp-3); text-align:center; cursor:pointer;
    border-right:1px solid var(--line-soft); -webkit-tap-highlight-color:transparent;
    transition:background .12s ease-out;
  }
  .mtodo-i:last-child{border-right:none}
  .mtodo-i:active{background:var(--bg-soft)}
  .mtodo-i .mt-n{
    font-size:var(--fs-xl); font-weight:var(--fw-bold); line-height:var(--lh-none);
    color:var(--c, var(--gray)); font-variant-numeric:tabular-nums;
  }
  .mtodo-i .mt-l{
    font-size:var(--fs-2xs); color:var(--t3); margin-top:var(--sp-1);
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }

  /* —— 折叠块：次要内容默认收起，标题行上带关键数字 —— */
  .mfolds{margin-bottom:var(--sp-4)}
  .mfold{
    background:var(--panel); border:1px solid var(--line); border-radius:var(--r-lg);
    box-shadow:var(--sh-1); margin-bottom:var(--sp-2); overflow:hidden;
  }
  .mfold>summary{
    display:flex; align-items:center; gap:var(--sp-2); min-height:46px;
    padding:var(--sp-2h) var(--sp-3); cursor:pointer; list-style:none;
    font-size:var(--fs-md); font-weight:var(--fw-bold);
    -webkit-tap-highlight-color:transparent; transition:background .12s ease-out;
  }
  .mfold>summary::-webkit-details-marker{display:none}
  .mfold>summary:active{background:var(--bg-soft)}
  .mf-ic{display:flex; flex:none; color:var(--brand); opacity:.9}
  .mf-ic svg{width:17px; height:17px}
  .mf-t{flex:none}
  .mf-s{
    flex:1; min-width:0; font-size:var(--fs-2xs); color:var(--t3); font-weight:var(--fw-normal);
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  .mf-n{
    flex:none; font-size:var(--fs-sm); font-weight:var(--fw-bold); color:var(--t1);
    font-variant-numeric:tabular-nums;
  }
  .mf-ar{display:flex; flex:none; color:var(--t3); transition:transform .16s ease-out}
  .mf-ar svg{width:16px; height:16px}
  .mfold[open]>summary .mf-ar{transform:rotate(90deg)}
  .mfold[open]>summary{border-bottom:1px solid var(--line-soft)}
  .mf-b{padding:var(--sp-2) var(--sp-3) var(--sp-3)}
  /* 折叠里的次级折叠（例如「走势」）不再套一层卡片 */
  .mf-b .mfold{border:none; box-shadow:none; margin:var(--sp-2) 0 0; background:var(--bg-card)}
  .mf-go{width:100%; justify-content:center; margin-top:var(--sp-2)}
  .mf-b .panel-b{padding:0}
  .mf-b .donut{width:96px; height:96px}
  .mf-b .donut svg{width:96px; height:96px}
  .mf-b .ds-sum{display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:var(--sp-2)}
  .mf-b .ds-big b{font-size:var(--fs-num-xs)}
  .mf-b .ds-big span{font-size:var(--fs-2xs)}

  /* —— 卡片流：代替手机上的宽表格，不用横向滚动就看得全 —— */
  .zcards,.ncards,.rcards{display:flex; flex-direction:column; gap:var(--sp-2)}
  .zcard,.ncard{
    background:var(--bg-tint); border:1px solid var(--line-soft); border-radius:var(--r);
    padding:var(--sp-2) var(--sp-2h);
  }
  .zcard.zc-sum{background:var(--gray-soft); border-color:var(--line)}
  .zc-h{
    display:flex; align-items:center; gap:var(--sp-1h); margin-bottom:var(--sp-1h);
    font-size:var(--fs-sm); font-weight:var(--fw-bold);
  }
  .zc-h .tag{font-size:var(--fs-2xs)}
  .zc-g,.nc-g{display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--sp-1) var(--sp-3)}
  .zc-f,.nc-f{
    display:flex; align-items:baseline; justify-content:space-between; gap:var(--sp-2);
    font-size:var(--fs-2xs); line-height:var(--lh-tight);
  }
  .zc-k,.nc-k{color:var(--t3); white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
  .zc-v,.nc-v{
    font-weight:var(--fw-bold); color:var(--t1); font-variant-numeric:tabular-nums;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  /* 个人通报卡：姓名 + 包区 + 是否封闭 一行，五项指标两列 */
  .nc-h{
    display:flex; align-items:center; gap:var(--sp-1h); margin-bottom:var(--sp-1h);
    font-size:var(--fs-sm);
  }
  .nc-h b{font-weight:var(--fw-bold)}
  .nc-z{flex:1; min-width:0; font-size:var(--fs-2xs); color:var(--t3);
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
  .nc-h .tag{flex:none; font-size:var(--fs-2xs)}
  /* 超期投诉 / 即将到期：左边姓名 + 单号，右边时限（超期标红） */
  .rcard{
    display:flex; align-items:center; gap:var(--sp-2h); min-height:56px;
    padding:var(--sp-2) var(--sp-2h);
    background:var(--bg-tint); border:1px solid var(--line-soft); border-radius:var(--r);
  }
  .rc-main{flex:1; min-width:0}
  .rc-t{
    font-size:var(--fs-md); font-weight:var(--fw-bold); line-height:var(--lh-tight);
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  .rc-s,.rc-s2{
    font-size:var(--fs-2xs); color:var(--t3); margin-top:2px; line-height:var(--lh-tight);
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  .rc-side{flex:none; text-align:right; max-width:44%}
  .rc-v{
    font-size:var(--fs-sm); font-weight:var(--fw-bold); color:var(--t1);
    font-variant-numeric:tabular-nums;
  }
  .rc-v.red{color:var(--danger)}
  .rc-more{font-size:var(--fs-2xs); color:var(--t3); text-align:center; padding:var(--sp-1h) 0}

  /* —— 卡片 / 面板整体：圆角、间距统一，层级更清楚 —— */
  .panel{border-radius:var(--r-lg); margin-bottom:var(--sp-2)}
  .panel-h{
    padding:var(--sp-2h) var(--sp-3); font-size:var(--fs-md); min-height:46px; gap:var(--sp-2);
  }
  .panel-h .sub{font-size:var(--fs-2xs)}
  .panel-b{padding:var(--sp-3)}
  .grid{margin-bottom:var(--sp-2)}
  .empty{padding:var(--sp-5) var(--sp-4); font-size:var(--fs-sm)}
  .empty svg{width:34px; height:34px}

  /* —— 底部 Tab 栏：图标换新的，选中态更明显 —— */
  .tabbar{
    background:var(--panel); box-shadow:0 -1px 8px rgba(16,24,40,.06);
    padding-bottom:env(safe-area-inset-bottom, 0px);
  }
  .tabbar-item{
    height:var(--tabbar-h); gap:3px; padding-bottom:2px;
    font-size:var(--fs-2xs); color:var(--t-mute);
  }
  .tabbar-item svg{width:23px; height:23px; color:var(--t-mute)}
  .tabbar-item span{position:relative; z-index:1; letter-spacing:var(--ls-wide)}
  .tabbar-item:active{background:var(--bg-soft)}
  /* 选中：淡绿胶囊底 + 顶部 2px 主色条 + 图标文字都变主色（比只换颜色好认） */
  .tabbar-item.on{
    color:var(--wx-green); font-weight:var(--fw-bold);
    background:var(--ok-soft);
    background:color-mix(in srgb, var(--wx-green) 10%, #fff);
  }
  .tabbar-item.on svg{color:var(--wx-green); position:relative; z-index:1}
  .tabbar-item.on::after{
    content:''; position:absolute; top:0; left:50%; transform:translateX(-50%);
    width:22px; height:2px; border-radius:0 0 2px 2px; background:var(--wx-green);
  }
  .tabbar-badge{top:2px}

  /* —— 动效克制：展开 / 点击只用 120~200ms ease-out，不弹跳 —— */
  .kpi,.mfold>summary,.mtodo-i,.tabbar-item{transition-duration:.16s}
}

/* ==========================================================================
   V34（2026-09-21）：手机端全站 UI 优化（第二轮）
   --------------------------------------------------------------------------
   上一轮只改了首页。这一轮把「列表页 / 弹窗 / 表单 / 空态 / 提示」全部收一遍：
     1. 页头按钮：一排一个 → 两个一行的小胶囊，页头不再吃掉半屏
     2. 账号管理 / 片区名册：宽表转卡片（13.9 屏）→ 紧凑行列表
     3. 所有弹窗：底部升起、85vh、内部滚动、底部按钮 sticky
     4. 详情：字段改成「浅色小标签 + 正常字重的值」的紧凑定义列表
     5. 空状态 / 骨架屏 / toast / 导入步骤：观感统一
   本块只写在 @media(max-width:768px) 里，桌面端一个像素都不会变。
   ========================================================================== */
@media (max-width:768px){

  /* ===== 1. 页头：按钮从「一排一个」改成「两个一行」 ===== */
  .page-head{gap:var(--sp-2); margin-bottom:var(--sp-3)}
  .page-head h1{font-size:var(--fs-lg); line-height:var(--lh-tight)}
  .page-head .ph-sub{font-size:var(--fs-xs); color:var(--t3); margin-top:var(--sp-half)}
  .page-head .ph-ops{gap:var(--sp-2)}
  .page-head .ph-ops .btn{
    flex:1 1 calc(50% - var(--sp-1)); min-width:0;
    min-height:38px; padding:var(--sp-pad-c) var(--sp-2h);
    font-size:var(--fs-sm); justify-content:center; text-align:center;
    border-radius:var(--r); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  }
  .page-head .ph-ops .btn svg{width:15px; height:15px; flex:none}

  /* ===== 2. 账号管理 / 片区名册：紧凑行（JS 侧已改渲染 .mlist） ===== */
  /* 停用/已停用的人头像转灰，扫列表时一眼分开 */
  .mi-av.off{background:var(--gray-soft); color:var(--gray)}
  /* 行次信息（片区 / 类型 / 别名）比行首弱一档，但别小到看不清 */
  .mlist-item .mi-sub{font-size:var(--fs-sm); color:var(--t3)}

  /* ===== 3. 弹窗：底部升起，85vh，内部滚动，底部按钮 sticky ===== */
  .mask{align-items:flex-end; padding:0}
  .modal{
    width:100%; max-width:100vw; max-height:85vh;
    border-radius:var(--r-lg) var(--r-lg) 0 0;
    /* 三段式：头 / 可滚的身 / 常驻的底，长表单滚到底也能点到保存 */
    display:flex; flex-direction:column;
    animation:sheetup .22s cubic-bezier(.2,.8,.3,1);
  }
  @keyframes sheetup{from{opacity:.4; transform:translateY(28px)}to{opacity:1; transform:none}}
  .modal-head{
    flex:none; padding:var(--sp-3) var(--sp-4); font-size:var(--fs-md);
    border-bottom:1px solid var(--line-soft);
  }
  .modal-body{
    flex:1 1 auto; min-height:0; overflow-y:auto; -webkit-overflow-scrolling:touch;
    padding:var(--sp-4);
    padding-bottom:calc(var(--sp-4) + env(safe-area-inset-bottom, 0px));
  }
  .modal-foot{
    flex:none; position:sticky; bottom:0; z-index:2;
    flex-wrap:wrap; gap:var(--sp-2);
    padding:var(--sp-2h) var(--sp-4);
    padding-bottom:calc(var(--sp-2h) + env(safe-area-inset-bottom, 0px));
    background:var(--panel); border-top:1px solid var(--line-soft);
    box-shadow:0 -2px 8px rgba(16,24,40,.04);
  }
  .modal-foot .btn{flex:1 1 auto; justify-content:center; min-width:88px; font-size:var(--fs-md)}
  /* 表单：单列、标签在上、间距统一；输入框统一 44px 高 / 16px 字（iOS 不缩放） */
  .modal-body .form-grid{grid-template-columns:1fr; gap:var(--sp-3)}
  .modal-body .fld.full,.modal-body .sec-title{grid-column:auto}
  .modal-body .fld label{
    font-size:var(--fs-sm); color:var(--t2); margin-bottom:var(--sp-1);
    font-weight:var(--fw-medium);
  }
  .modal-body .input,.modal-body select.input,.modal-body textarea.input{
    font-size:var(--fs-16); min-height:44px;
  }
  /* 多值标签输入（欠停日期这类）里真正打字的是 .ti-in，它不带 .input 类，
     漏了它 iOS 聚焦仍会缩放页面 —— 一并钉到 16px */
  .modal-body .ti-in{font-size:var(--fs-16); height:30px}
  /* 权限勾选：手机上排成两列，别竖成一条长龙 */
  .zonepick{display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--sp-2)}
  .zp{justify-content:flex-start; padding:var(--sp-1h) var(--sp-2h); font-size:var(--fs-md)}
  .zp input{width:16px; height:16px}

  /* ===== 4. 详情弹窗：紧凑定义列表（浅色小标签 + 正常字重的值） ===== */
  .detail-grid{grid-template-columns:1fr; gap:0}
  .det-row{
    display:flex; flex-direction:column; align-items:stretch; gap:2px;
    padding:var(--sp-2) 0; border-bottom:1px solid var(--line-soft);
  }
  .det-row:last-child{border-bottom:none}
  .det-k{font-size:var(--fs-xs); color:var(--t3); line-height:var(--lh-tight)}
  .det-v{font-size:var(--fs-md); color:var(--t1); font-weight:var(--fw-medium)}

  /* ===== 5. 空状态：有质感的空态，不是光秃秃一行字 ===== */
  .empty{
    display:flex; flex-direction:column; align-items:center; justify-content:center;
    padding:var(--sp-7) var(--sp-5); text-align:center;
  }
  .empty svg{
    width:56px; height:56px; color:var(--gray); opacity:.55; margin-bottom:var(--sp-3);
  }
  .empty > div:first-of-type{
    font-size:var(--fs-lg); font-weight:var(--fw-bold); color:var(--t2);
    line-height:var(--lh-tight);
  }
  .empty .sub{
    margin-top:var(--sp-2); font-size:var(--fs-sm); color:var(--t3);
    line-height:var(--lh-loose); max-width:22em;
  }
  .empty-what{
    margin-top:var(--sp-2); font-size:var(--fs-xs); color:var(--t3);
    line-height:var(--lh-loose); max-width:22em;
    padding:var(--sp-1h) var(--sp-3); border-radius:var(--r);
    background:var(--bg-soft);
  }
  .empty-act{margin-top:var(--sp-4)}
  .empty-act .btn{min-height:38px; padding:var(--sp-1h) var(--sp-5)}

  /* ===== 6. toast：离开底部 Tab 栏，别被挡住 ===== */
  .toast{
    top:auto; left:50%;
    bottom:calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px) + var(--sp-3));
    transform:translate(-50%, 8px) scale(.96);
    max-width:88vw; font-size:var(--fs-sm);
    padding:var(--sp-2h) var(--sp-4); border-radius:var(--r-lg);
  }
  .toast.show{opacity:1; transform:translate(-50%,0) scale(1)}

  /* ===== 7. 导入页：步骤指引收紧凑，别占半屏 ===== */
  .imp-steps{padding:var(--sp-2h) var(--sp-3); font-size:var(--fs-xs); line-height:var(--lh-loose)}
  .imp-steps > div{padding:1px 0}
  .imp-steps b{
    display:inline-flex; align-items:center; justify-content:center;
    width:15px; height:15px; margin-right:var(--sp-1);
    border-radius:50%; background:var(--brand-soft); color:var(--brand);
    font-size:var(--fs-2xs); line-height:var(--lh-none);
  }
  .step{padding:var(--sp-3) var(--sp-4); gap:var(--sp-3)}
  .step-n{width:20px; height:20px; font-size:var(--fs-xs)}
  .step-t{font-size:var(--fs-md); margin-bottom:var(--sp-half)}
  .step-d{font-size:var(--fs-xs); line-height:var(--lh-loose); margin-bottom:var(--sp-2)}
  .dropzone{padding:var(--sp-4) var(--sp-3)}
  .dz-t{font-size:var(--fs-md)}
  .dz-s{font-size:var(--fs-xs)}
  .dropzone svg{width:32px; height:32px}
  .res-box{max-height:200px; font-size:var(--fs-xs)}

  /* ===== 8. 面板 / 工具栏：间距字号再统一一遍 ===== */
  .panel-h{padding:var(--sp-2h) var(--sp-3); font-size:var(--fs-md); min-height:44px}
  .toolbar{padding:var(--sp-2h) var(--sp-3); gap:var(--sp-2)}
/* 触控高度：V35（P1 修复）统一提到 44px —— 微信 / iOS HIG 的触控下限。
   V34 这里写的是 42px（原注释说「取工具栏能接受的紧值」），但 42 会被上面的
   .btn.sm{min-height:44px}（第 749 行，同一 media 内、但在本块之前）反向压低，
   实测「筛选 / 重置 / 上一页 / 下一页 / 批量闭环 / 批量删除」全部只有 42px 高，
   差 2px。统一到 44px 后与全站其它按钮一致，实测工具栏不因此换行。 */
.toolbar .btn.sm{min-height:44px}
.pager .btn.sm{min-height:44px}
.fbar-t{min-height:44px; padding:var(--sp-1h) var(--sp-2h); font-size:var(--fs-sm)}
  .pager{padding:var(--sp-2h) var(--sp-3); font-size:var(--fs-sm)}
  .tabs{padding:0 var(--sp-3)}
  .tab{padding:var(--sp-2h) var(--sp-2h); font-size:var(--fs-md)}
  .hint-box{padding:var(--sp-2h) var(--sp-3); font-size:var(--fs-xs); line-height:var(--lh-loose)}

  /* ===== 9. 骨架屏：列表加载时的占位行 ===== */
  /* 占位条本体 .skel 已在设计系统里（顶层规则，桌面端也在用），
     这里只补「手机紧凑列表形态」下的行骨架，不重复定义 .skel。 */
  .mlist-item.skel-row{cursor:default; pointer-events:none}
  .mlist-item.skel-row .mi-av{background:var(--gray-soft)}
  .mlist-item.skel-row .skel{background:var(--gray-soft); height:12px}
  .mlist-item.skel-row .mi-main .skel:first-child{width:42%; margin-bottom:var(--sp-1)}
  .mlist-item.skel-row .mi-main .skel:last-child{width:68%; height:11px}
}

/* ==========================================================================
   V34 补充：小屏（≤480px）再收一档 —— 头像小一点、行高紧一点、按钮仍可点
   ========================================================================== */
@media (max-width:480px){
  .mi-av{width:36px; height:36px; font-size:var(--fs-md)}
  .mlist-item{min-height:54px; padding:var(--sp-2) var(--sp-3); gap:var(--sp-2)}
  .page-head .ph-ops .btn{flex:1 1 calc(50% - var(--sp-1)); font-size:var(--fs-xs)}
  .modal-foot .btn{min-width:0; font-size:var(--fs-sm)}
  .empty svg{width:48px; height:48px}
}

/* ==========================================================================
   V34 排版统一 · 公共文字类
   只作为「新增页面」的复用入口，不强行替换既有的 153 处 —— 那些已经全部
   引用同一套变量，改变量即可统一。
   ========================================================================== */
.t-body{font-size:var(--fs-body); color:var(--t1); line-height:var(--lh-normal)}
.t-caption{font-size:var(--fs-caption); color:var(--t3); line-height:var(--lh-normal)}
.t-label{font-size:var(--fs-label); color:var(--t2); font-weight:var(--fw-medium)}
.t-num{font-size:var(--fs-body); font-variant-numeric:tabular-nums}
.t-mono{font-family:var(--ff-mono)}
/* 禁用态文字：白底约 2.9:1。WCAG 对「真正禁用」的控件不强制对比度，
   这里统一用 --t-disabled，别再各处散落 --t3 / opacity。 */
.btn:disabled,.rbtn:disabled,.tab:disabled,.btn[disabled],.rbtn[disabled]{
  color:var(--t-disabled); cursor:not-allowed;
}
/* 上面那条和 .btn.primary{color:var(--t-white)} 特异性同为 (0,2,0)，
   且位置在后 → 灰字会压到绿色主按钮上（#a6a6a6 on #07C160 基本看不清）。
   这里把彩色底按钮拉回白字：禁用态靠底色变淡表达，不靠把字涂灰。 */
/* 注意：这里只救primary（绿底）。次按钮/危险按钮是浅色底，禁用态就该是灰字
   （由上面 --t-disabled 那条提供），把它们也拉成白字会变成「白字白底看不见」。 */
.btn.primary[disabled],.btn.primary:disabled{color:var(--t-white)}

/* ==========================================================================
V35（2026-09-22）：手机端「点得中」修复 —— 移动端 UI 量化审计回归项
--------------------------------------------------------------------------
支局长反馈的手机端问题里，有一类是「量出来了但手指点不中」。本块按 390×844
（iPhone 12）实测数据逐条修，全部写在 @media(max-width:768px) 内，桌面端零改动。
沿用 :root 现有 token；触控下限 44px 是唯一允许出现的裸数字（微信 / iOS HIG）。

本块负责：
  1. P1 弹窗关闭按钮 .x        实测 20.9×22   → ≥44×44
  2. P1 列表批量选择 .mi-chk   实测 27×26     → ≥44×44（勾选框本体维持 20×20）
  3. P2 首页分段按钮 .seg-b    实测 32.5 高   → ≥44 高
  4. P2 首页搜索框 #gq         实测 20.5 高   → ≥44 高
  5. P3 筛选 chip 行           右侧渐隐，提示还能横滑
另有两条已就地改在各自原规则处（不在此块内重复）：
  P0 .tabbar z-index 80→50（V27 块内，第 1284 行附近）
  P1 .toolbar/.pager .btn.sm 与 .fbar-t 42→44（V34 第 8 节内）
========================================================================== */
@media (max-width:768px){
/* ===== 1. 弹窗关闭按钮：原来只有 20.9×22，指尖基本点不中 =====
只放大「按钮本体」，不加伪元素热区 —— 审计按 getBoundingClientRect 复测，
用伪元素撑热区量不到、也无法验证。代价是弹窗头会变高，这里同步把
.modal-head 的竖向内边距从 --sp-3(12px) 收到 --sp-2(8px) 抵消掉一半。 */
.modal-head{padding:var(--sp-2) var(--sp-4)}
.modal-head .x{
  min-width:44px; min-height:44px;
  display:inline-flex; align-items:center; justify-content:center;
  border-radius:var(--r-sm); -webkit-tap-highlight-color:transparent;
  transition:background .12s;
}
.modal-head .x:active{background:var(--bg-soft); color:var(--t1)}

/* ===== 2. 列表批量选择：热区交给父 label，勾选框本体仍是 20×20 =====
checkbox 画到 44px 会非常丑，也会把紧凑行（V34 刚压到 54px）撑爆；
所以只把 label 撑到 44×44，里面的 input 保持原尺寸并居中。 */
.mi-chk{
  min-width:44px; min-height:44px; justify-content:center;
  -webkit-tap-highlight-color:transparent;
}
.mi-chk input{width:20px; height:20px; flex:none; margin:0}
/* 副作用对冲：44px 的勾选框会一跃成为行内最高的 flex 子项（头像才 36px），
把 V34 刚压到 54px 的紧凑行顶到 60px —— 40 行就是 +240px，瘦身成果全退回去。
这里把行的竖向内边距从 --sp-2/--sp-2h（8~10px）收到 --sp-1（4px）抵消掉；
行高仍被 .mlist-item 的 min-height 锁住（54px / 58px），
实测 54.3 → 54.0，整页高度零反弹。勾选框居中，上下仍各有 5px 余量。 */
.mlist-item{padding-top:var(--sp-1); padding-bottom:var(--sp-1)}

/* ===== 3. 首页「按天 / 按月 / 累计」分段按钮：32.5 → 44 =====
.seg 容器不设死高度，跟着按钮一起长高，1px 描边 + --r-sm 圆角不会被撑破。 */
.seg-b{
  min-height:44px;
  display:inline-flex; align-items:center; justify-content:center;
  padding:var(--sp-pad-c) var(--sp-3h);
}

/* ===== 4. 首页全局搜索框 #gq：20.5 → 44 =====
#gq 此前在 CSS 里没有任何规则，完全吃浏览器默认 input 样式（padding:1px）。
这里不额外加 1px 描边：外层 .gsearch 已经有 --line-strong 描边，
再套一层会在 48px 高的条里出现两条相距 2px 的边框，反而变丑。 */
#gq{
  min-height:44px; padding:var(--sp-2) var(--sp-3h);
  border-radius:var(--r-sm); font-size:var(--fs-16);
}

/* ===== 5. 筛选 chip 行：右侧渐隐，一眼看出后面还有 =====
chip 不换行（V33 刚把首页压扁，换行会吃掉太多竖向空间），
只在右缘做 24px(--sp-6) 渐隐，横滑到底时渐隐仍在 —— 纯 CSS 判断不了
scrollLeft 是否到底，要完全动态得改 JS，收益不抵风险，这里留着。 */
.fchip-row{
  -webkit-mask-image:linear-gradient(to right, #000 calc(100% - var(--sp-6)), transparent);
  mask-image:linear-gradient(to right, #000 calc(100% - var(--sp-6)), transparent);
}
}

/* ==========================================================================
V36（2026-09-22）：手机端首页「快捷办理」九宫格
--------------------------------------------------------------------------
手机上侧栏 display:none、底部只有 4 个 Tab，「调账申请」「存量用户挽留申请」
两页此前在手机上没有任何跳转入口。这块按模块补齐入口：一排 3 个 × 2 排。

硬约束：
  · 全部写在 @media(max-width:768px) 内 —— 桌面端首页一个像素都不会变
  · 每格触控高度 ≥64px（这里给 72px）：支局员工常在营业厅现场戴手套 / 手湿操作，
    44px（HIG 下限）对这种场景不够，九宫格是首页最高频的点击区，多给一档
  · 颜色只吃 --c / --c-soft（复用 .c-blue/.c-red/… 既有配色类），不新增色值
========================================================================== */
@media (max-width:768px){
/* 面板本体：沿用 .panel 的白底 + 圆角，只把外边距并入首页统一节奏 */
.mquick{margin-bottom:var(--sp-2); border-radius:var(--r-lg)}
.mquick .panel-h{min-height:44px; border-bottom:1px solid var(--line-soft)}

/* 3 列网格。gap:1px + 底色 --line-soft = 单元格之间的分隔线，
   不用给每个格子单独描边（那样相邻边会出现 2px 双线） */
.mq-g{
  display:grid; grid-template-columns:repeat(3,minmax(0,1fr));
  gap:1px; background:var(--line-soft);
}

/* 单格：图标在上、文字在下，整格居中。
   min-height:72px 是本块唯一允许出现的裸数字（触控下限，注释见块头）。 */
.mq-i{
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:var(--sp-1h); min-height:72px; padding:var(--sp-2h) var(--sp-1);
  background:var(--panel); cursor:pointer; text-align:center;
  -webkit-tap-highlight-color:transparent; transition:background .12s ease-out;
}
/* 按下反馈：整格变浅灰（与底部 Tab、待办格子同一套反馈，不另造一套） */
.mq-i:active{background:var(--bg-soft)}

/* 图标：淡色圆角底 + 主色线稿，和首页 KPI 卡（.grid.mkpi .kpi-ic）同一手法 */
.mq-i i{
  display:flex; align-items:center; justify-content:center; flex:none;
  width:34px; height:34px; border-radius:var(--r-sm);
  font-style:normal;
  background:var(--c-soft, var(--gray-soft));              /* color-mix 不支持时的兜底 */
  background:color-mix(in srgb, var(--c, var(--brand)) 12%, #fff);
  color:var(--c, var(--brand));
}
.mq-i i svg{width:19px; height:19px}
/* 文字：12px 次级灰，按下时提到主文本色（按下的反馈不只靠底色） */
.mq-i span{
  max-width:100%; font-size:var(--fs-xs); color:var(--t2);
  font-weight:var(--fw-medium); line-height:var(--lh-tight); letter-spacing:var(--ls-wide);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.mq-i:active span{color:var(--t1)}
}
/* ==========================================================================
   主题层 · 「纸本台账 / Editorial Ledger」
   --------------------------------------------------------------------------
   重设计目标：做出**设计感**，不做那种千篇一律的通用后台模板脸。

   实现方式：本块追加在原设计系统之后，只**重新指向**既有令牌的取值
   （同名 :root 变量后声明者胜），外加一层排版/质感覆写。
   选择器与结构一律不动 —— 前端 250 个类名全部继续生效，功能零改动。

   视觉语言：
     · 纸：暖米纸底，不是冷灰；面板像纸，靠**发丝线**分区，不靠阴影堆卡片
     · 墨：墨绿为主色（标题、主按钮、选中态）
     · 朱：朱砂只用在「要人看」的地方（紧急、失败、关键数字），不铺开
     · 赭：赭金作第三档（警示、次要强调）
     · 字：标题走中文衬线（报刊/账簿气质），正文黑体，数字等宽右对齐

   兼容约束（用户明确要求微信内置浏览器 + 系统浏览器）：
     · 只用 hex / rgba / hsl 传统写法 —— 不用 oklch()、color-mix()、light-dark()
     · 不用 @container（X5 内核不支持）
     · 需要前缀的属性一律带 -webkit-
   ========================================================================== */

:root{
  color-scheme: light;

  /* ---------- 纸 ---------- */
  --bg:#F2EEE5;            /* 暖米纸：主背景 */
  --bg-soft:#EBE5D8;       /* 比纸深一档：选中行、备用底 */
  --bg-card:#FBF8F1;       /* 纸面：卡片/面板 */
  --bg-tint:#F7F3EA;       /* 极浅纸：面板头 / 工具栏 / 弹窗底 */
  --bg-hover:#EAE3D4;      /* 悬停底 */
  --bg-stripe:#F8F4EC;     /* 表格斑马纹（几乎不可见的一层纸色） */
  --bg-bar:#E3DCCC;        /* 进度条 / 图表条底槽 */
  --bg-disabled:#EAE5DA;   /* 禁用控件底 */
  --bg-note:#F3EFE4;       /* 提示块 / 只读表单底 */
  --panel:#FBF8F1;

  /* ---------- 发丝线（替代阴影做分区） ---------- */
  --line:#DCD3C0;
  --line-soft:#E8E1D2;
  --line-strong:#C6BCA6;
  --line-dash:#BDB39C;
  --line-ok:#BFD3C2;
  --line-bad:#d7b9b6;
  --line-warn-strong:#d1c2a8;
  --warn-line:#d2c1a6;
  --warn-line-soft:#e1d0b7;

  /* ---------- 墨（主色） ---------- */
  --brand:#2E5A4B;
  --brand-hi:#22453A;
  --brand-soft:#E3EBE4;
  --brand-deep:#16302A;
  --brand-grad:linear-gradient(135deg,#356553,#1E4237);
  --brand-grad-lg:linear-gradient(150deg,#3A6B58,#16302A);
  /* 「行动色」：原微信绿，收到同一套墨绿里 —— 全站只有一个绿，不打架 */
  --wx-green:#2F6B4F;
  --green-hi:#24543D;

  /* ---------- 朱（强调） ---------- */
  --danger:#b95850;
  --danger-soft:#dfbcb9;
  --danger-text:#af3d35;
  --cinnabar:#af5d4f;
  --cinnabar-soft:#d9c6bf;
  --wechat-red:#ce4141;

  /* ---------- 赭（次要强调） ---------- */
  --warn:#976b30;
  --warn-soft:#e0d0b8;
  --warn-text:#976316;
  --warn-text-2:#9d6721;

  /* ---------- 其它语义 ---------- */
  --ok:#3F7A5E;
  --ok-soft:#E4EDE5;
  --ok-text:#2C5B43;
  --purple:#7b69c4;
  --purple-soft:#c1b7e1;
  --teal:#4A7A78;
  --teal-soft:#E2ECEA;
  --gray:#8C8477;
  --gray-soft:#EAE5D8;

  /* ---------- 墨字（暖调近黑，不用纯黑） ---------- */
  --t1:#2A2622;
  --t2:#5B544B;
  --t3:#857C6F;
  --t-mute:#948B7D;
  --t-disabled:#B5AD9E;
  --t-white:#FBF8F1;

  /* ---------- 半透明层 ---------- */
  --scrim:rgba(32,28,22,.46);
  --overlay-toast:rgba(38,33,25,.90);
  --overlay-toast-bad:rgba(58,28,22,.92);
  --focus-ring:rgba(46,90,75,.16);
  --login-brand:#2E5A4B;
  --login-ring:rgba(46,90,75,.16);

  /* ---------- 账簿的硬朗：圆角收窄 ---------- */
  --r-sm:8px; --r:8px; --r-lg:12px;

  /* ---------- 阴影几乎不用：纸靠线分区 ---------- */
  --sh-1:0 1px 0 rgba(42,38,34,.03);
  --sh-2:0 1px 0 rgba(42,38,34,.04), 0 6px 18px rgba(42,38,34,.05);
  --sh-3:0 2px 0 rgba(42,38,34,.05), 0 14px 40px rgba(42,38,34,.10);

  /* ---------- 排版：标题走中文衬线 ---------- */
  /* 只用系统字体栈，不引入外部字体/CDN（技术栈不变、不加依赖）。
     Android 的 X5 内核上 Songti SC 不存在，会落到 Noto Serif CJK / 通用 serif，
     仍然是衬线，气质保得住。 */
  --ff-serif:"Songti SC","STSong","SimSun","Noto Serif CJK SC","Source Han Serif SC",
             "Source Han Serif CN","Times New Roman",serif;
  --ff-sans:-apple-system,BlinkMacSystemFont,"PingFang SC","Helvetica Neue",
            "Microsoft YaHei","Noto Sans CJK SC",sans-serif;
  --ff-mono:ui-monospace,SFMono-Regular,Menlo,Consolas,"Courier New",monospace;

  /* 标题字距：衬线中文稍微收一点，更像报刊 */
  --ls-title:-.3px;
  --ls-caps:1.6px; --fs-xl:24px; --fs-lg:17px; --fs-h1:24px; --fs-h2:17px; --fs-h3:17px; --fs-h4:15px; --fs-h5:15px; --fs-h6:12px; --fs-body:15px; --fs-md:15px; --fs-16:16px; --fs-btn:15px; --fs-sm:12px; --fs-xs:12px; --fs-2xs:11px; --fs-label:12px; --fs-caption:12px}

/* ---------- 深色：跟随系统（浅色为主，系统要深色就给深色） ---------- */
@media (prefers-color-scheme: dark){
  :root{
    color-scheme: dark;
    --bg:#191713;
    --bg-soft:#211E19;
    --bg-card:#221F1A;
    --bg-tint:#1E1B16;
    --bg-hover:#2A2620;
    --bg-stripe:#201D18;
    --bg-bar:#332E26;
    --bg-disabled:#24211B;
    --bg-note:#1F1C17;
    --panel:#221F1A;

    --line:#3A342B;
    --line-soft:#2C2820;
    --line-strong:#4C4539;
    --line-dash:#4C4539;
    --line-ok:#3B4F42;
    --line-bad:#d7b9b6;
    --line-warn-strong:#d1c2a8;
    --warn-line:#d2c1a6;
    --warn-line-soft:#e1d0b7;

    --brand:#83AE99;
    --brand-hi:#9CC2AC;
    --brand-soft:#25332C;
    --brand-deep:#0F1D18;
    --brand-grad:linear-gradient(135deg,#3D5C4E,#22352C);
    --brand-grad-lg:linear-gradient(150deg,#436555,#16241E);
    --wx-green:#6FA487;
    --green-hi:#86B89B;

    --danger:#b95850;
    --danger-soft:#dfbcb9;
    --danger-text:#af3d35;
    --cinnabar:#af5d4f;
    --cinnabar-soft:#d9c6bf;
    --wechat-red:#ce4141;

    --warn:#976b30;
    --warn-soft:#e0d0b8;
    --warn-text:#976316;
    --warn-text-2:#9d6721;

    --ok:#7FB294;
    --ok-soft:#23302A;
    --ok-text:#95C0A6;
    --purple:#7b69c4;
    --purple-soft:#c1b7e1;
    --teal:#7FAFAC;
    --teal-soft:#212E2D;
    --gray:#9C9486;
    --gray-soft:#272319;

    --t1:#E9E2D4;
    --t2:#B5AC9B;
    --t3:#8F8778;
    --t-mute:#837B6D;
    --t-disabled:#5F584D;
    --t-white:#FBF8F1;

    --scrim:rgba(8,7,5,.62);
    --overlay-toast:rgba(24,21,16,.94);
    --overlay-toast-bad:rgba(46,22,17,.94);
    --focus-ring:rgba(131,174,153,.20);
    --login-brand:#83AE99;
    --login-ring:rgba(131,174,153,.20);

    --sh-1:0 1px 0 rgba(0,0,0,.20);
    --sh-2:0 1px 0 rgba(0,0,0,.24), 0 6px 18px rgba(0,0,0,.28);
    --sh-3:0 2px 0 rgba(0,0,0,.26), 0 14px 40px rgba(0,0,0,.38);
  }
}

/* ==========================================================================
   1. 基础
   ========================================================================== */
body{
  background:var(--bg);
  color:var(--t1);
  /* 纸的质感：极轻的噪点做不到（不引依赖），用更暖的底色 + 发丝线代替 */
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
::-webkit-scrollbar-thumb{background:var(--line-strong);border:none;background-clip:initial}
::-webkit-scrollbar-thumb:hover{background:var(--t3)}
::-webkit-scrollbar-track{background:var(--bg-soft)}h1{
  font-family:var(--ff-serif);
}
h2{
  font-family:var(--ff-serif);
}
h3{
  font-family:var(--ff-serif);
}
.page-head h1{
  font-family:var(--ff-serif); font-size:24px; font-weight:700; line-height:1.15; letter-spacing:-.4px}
.panel-h{
  font-family:var(--ff-serif); font-size:17px; font-weight:600; line-height:1.25; letter-spacing:0}
.sec-title{
  font-family:var(--ff-serif); font-size:15px; font-weight:600; letter-spacing:0}
.login-t{
  font-family:var(--ff-serif);
}
.brand-txt b{
  font-family:var(--ff-serif);
}
.modal-head{
  font-family:var(--ff-serif); font-size:17px; font-weight:600; line-height:1.25; letter-spacing:0}
.side-card-t{
  font-family:var(--ff-serif);
}
.nav-group{
  font-family:var(--ff-serif); font-size:11px; font-weight:600; letter-spacing:.55px; color:var(--t3)}
.mhero-t{
  font-family:var(--ff-serif);
}
.mlist-hd{
  font-family:var(--ff-serif);
}
.nc-h{
  font-family:var(--ff-serif);
}
.rc-t{
  font-family:var(--ff-serif);
}
.zc-h{
  font-family:var(--ff-serif);
}
.kpi-label{
  font-family:var(--ff-serif); font-size:12px; font-weight:500; letter-spacing:.4px; color:var(--t3)}
.step-t{
  font-family:var(--ff-serif); font-size:15px; font-weight:600; letter-spacing:0}
.mf-t{
  font-family:var(--ff-serif);
}
.tab{
  font-family:var(--ff-serif); font-size:15px; font-weight:600; border-bottom-color:var(--line-soft) }
.tabs .tab{
  font-family:var(--ff-serif);
}.num{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum";
}
.t-num{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum";
}
.kpi-value{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum"; font-size:34px; font-weight:700; line-height:1.05}
.mkpi-v{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum";
}
.ds-big{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum"; gap:6px}
.mt-n{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum";
}
.tb td.num{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum";
}
.tb th.num{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum";
}

/* ==========================================================================
   2. 外壳：顶栏 / 侧栏 / 内容
   ========================================================================== */
.topbar{
  background:var(--bg-card);
  border-bottom:1px solid var(--line);
  box-shadow:none;
  /* 顶栏底部压一条稍重的线，像账簿封面的压边 */
  height:calc(var(--topbar-h) + 1px);
  padding:0 var(--sp-6);
  gap:var(--sp-6);
}
.logo{
  background:var(--brand-deep);
  color:var(--t-white);
  border-radius:var(--r-sm);
  font-family:var(--ff-serif);
  font-weight:var(--fw-black);
  box-shadow:none;
  border:1px solid var(--brand-hi);
}
.brand-txt b{letter-spacing:var(--ls-title);font-size:var(--fs-lg);color:var(--brand-deep)}
.brand-txt span{
  font-family:var(--ff-sans);
  letter-spacing:var(--ls-caps);
  text-transform:none;
  color:var(--t3);
}
.today{color:var(--t3);font-family:var(--ff-mono);font-size:12px; font-weight:400}
.zonetag{
  background:var(--brand-soft);color:var(--brand-hi);
  border:1px solid var(--line-strong);border-radius:var(--r-sm);
  font-family:var(--ff-sans);
}

.sidebar{
  background:var(--bg-tint);
  border-right:1px solid var(--line);
}
.nav-group{
  color:var(--t3);
  letter-spacing:.55px;
  font-size:11px;
  border-bottom:1px solid var(--line-soft); font-weight:600}
.nav-item{
  border-radius:var(--r-sm);
  border-left:2px solid transparent;
  color:var(--t2); font-size:15px; font-weight:500}
.nav-item:hover{background:var(--bg-hover);color:var(--t1)}
.nav-item.active,.nav-item.on{
  background:var(--brand-soft);
  border-left-color:var(--brand);
  color:var(--brand-deep);
  font-weight:var(--fw-bold);
}
.nav-badge{
  background:var(--cinnabar);color:var(--t-white);
  border-radius:var(--r-sm);font-family:var(--ff-mono); font-size:11px; font-weight:600}
.side-card{
  background:var(--bg-card);
  border:1px solid var(--line);
  border-radius:var(--r-sm);
}
.side-card-t{color:var(--t3);letter-spacing:var(--ls-caps);font-size:var(--fs-xs)}
.side-card-p{color:var(--t2);font-family:var(--ff-mono);word-break:break-all}

.content-inner{max-width:1180px}

/* ==========================================================================
   3. 页头 / 面板 / 工具栏 —— 用线分区，不堆卡片
   ========================================================================== */
.page-head{
  border-bottom:1px solid var(--line);
  padding-bottom:var(--sp-4);
  margin-bottom:var(--sp-5);
}
.page-head h1{
  font-size:24px;
  letter-spacing:-.4px;
  color:var(--brand-deep);
  font-weight:700; line-height:1.15}
.sec-title{
  color:var(--t3);
  letter-spacing:0;
  font-size:15px;
  border-bottom:1px solid var(--line-soft);
  padding-bottom:var(--sp-2); font-weight:600}
.panel{
  background:var(--panel);
  border:1px solid var(--line);
  border-radius:8px;
  box-shadow:var(--sh-1); border-color:var(--line-soft)}
.panel-h{
  background:var(--bg-tint);
  border-bottom:1px solid var(--line);
  color:var(--brand-deep); font-size:17px; font-weight:600; line-height:1.25; letter-spacing:0}
.toolbar{
  background:transparent;
  border-bottom:1px solid var(--line-soft);
}

/* ==========================================================================
   4. 账簿表格 —— 本主题的核心
   ========================================================================== */
.tb{
  border:1px solid var(--line-soft);
  border-radius:8px;
  background:var(--panel);
  border-collapse:separate;
  border-spacing:0;
  overflow:hidden; font-size:15px; font-weight:400; line-height:1.5}
.tb th{
  background:var(--bg-tint);
  color:var(--t3);
  font-family:var(--ff-serif);
  font-weight:500;
  letter-spacing:.4px;
  font-size:12px;
  border-bottom:1px solid var(--line);
  border-right:none;
  padding:10px 12px; border-top:none}
.tb th:last-child{border-right:none}
.tb td{
  border-bottom:1px solid var(--line-soft);
  border-right:none;
  padding:10px 12px;
  color:var(--t1);
  vertical-align:middle; font-size:15px; font-weight:400; line-height:1.5; border-top:none}
.tb td:last-child{border-right:none}
.tb tbody tr:last-child td{border-bottom:none}
.tb tbody{background:var(--bg-card)}
/* 行底（2026-09-23）：暖纸底透上来会发「卡其」，丑。
   表格统一铺干净白，斑马纹用中性冷灰一档，不再带黄。 */
.tb tbody tr{background:#fff}
.tb tbody tr:nth-child(even){background:#f7f8fa}
.tb tbody tr:hover{background:var(--bg-hover)}
.tb tbody tr.row-focus{background:var(--warn-line-soft)}
.tb-sum{
  background:var(--bg-tint);
  border-top:1px solid var(--line-strong);
  font-family:var(--ff-serif);
  font-weight:var(--fw-bold);
  color:var(--brand-deep);
}
.sortable{cursor:pointer;user-select:none}
.sortable:hover{color:var(--brand-deep)}
.tb-scroll{border:1px solid var(--line);border-radius:var(--r-sm)}
.tb-keep{}.btn{
  border-radius:8px;
  font-family:var(--ff-sans);
  letter-spacing:.1px;
  box-shadow:none;
  border:1px solid var(--line); font-size:15px; font-weight:500}
.login-btn{
  border-radius:var(--r-sm);
  font-family:var(--ff-sans);
  letter-spacing:var(--ls-wide);
  box-shadow:none;
  border:1px solid transparent;
}.btn.primary{
  background:var(--brand);
  border-color:transparent;
  color:var(--t-white); border-radius:8px}
.btn.ok{
  background:var(--brand);
  border-color:var(--brand-hi);
  color:var(--t-white);
}
.login-btn{
  background:var(--brand);
  border-color:var(--brand-hi);
  color:var(--t-white);
}.btn.primary:hover{background:var(--brand-hi); border-color:transparent}
.login-btn:hover{background:var(--brand-hi)}
.btn.danger{background:var(--cinnabar);border-color:var(--line);color:var(--t-white); border-radius:8px}
.btn.danger:hover{background:var(--danger-text)}.btn.sub{
  background:var(--panel);
  border:1px solid var(--line-strong);
  color:var(--t2);
  border-radius:var(--r-sm);
}
.btn-ghost{
  background:var(--panel);
  border:1px solid transparent;
  color:var(--t2);
  border-radius:8px; border-color:transparent; font-size:12px; font-weight:500; padding:6px 10px}.btn.sub:hover{background:var(--bg-hover);color:var(--brand-deep);border-color:var(--brand)}
.btn-ghost:hover{background:var(--bg-hover);color:var(--brand-deep);border-color:transparent}
.btn:disabled,.login-btn:disabled{
  background:var(--bg-disabled);color:var(--t-disabled);
  border-color:var(--line);cursor:not-allowed;
}.rbtn{
  border:1px solid var(--line);
  background:var(--panel);color:var(--t2);
  border-radius:8px; font-size:15px; font-weight:500}
.rbtn-group .rbtn{
  border:1px solid var(--line-strong);
  background:var(--panel);color:var(--t2);
  border-radius:var(--r-sm);
}
.rbtn.on,.rbtn-group .rbtn.on{
  background:var(--brand-soft);border-color:var(--brand);
  color:var(--brand-deep);font-weight:var(--fw-bold);
}
.seg{background:var(--bg-soft);border:1px solid var(--line-soft);border-radius:8px}
.seg-b{color:var(--t2);border-radius:0; font-size:12px; font-weight:500; border-right:1px solid var(--line-soft)}
.seg-b.on{background:var(--brand);color:var(--t-white);font-weight:var(--fw-bold)}
.tab{
  color:var(--t3);
  border-bottom:2px solid transparent;
  letter-spacing:var(--ls-title); font-size:15px; font-weight:600; border-bottom-color:var(--line-soft) }
.tab.on{color:var(--brand-deep);border-bottom-color:var(--cinnabar);font-weight:var(--fw-black)}
.tabs{border-bottom:1px solid var(--line)}
.tabbar-badge{background:var(--cinnabar);color:var(--t-white);font-family:var(--ff-mono)}.input{
  background:var(--bg-card);
  border:1px solid var(--line-strong);
  border-radius:var(--r-sm);
  color:var(--t1); font-size:15px; font-weight:400; line-height:1.4}
.login-input{
  background:var(--bg-card);
  border:1px solid var(--line-strong);
  border-radius:0;
  color:var(--t1);
}
.ti-in{
  background:var(--bg-card);
  border:1px solid var(--line-strong);
  border-radius:var(--r-sm);
  color:var(--t1);
}
.input:focus,.login-input:focus,.ti-in:focus{
  border-color:var(--login-brand);
  box-shadow:0 0 0 3px var(--login-ring);
  outline:none;
}
.input:disabled,.input[readonly]{background:var(--bg-note);color:var(--t3)}
.input.err{border-color:var(--danger);background:var(--danger-soft)}
.fld label{color:var(--t2);font-family:var(--ff-serif);font-size:var(--fs-label)}
.chk{accent-color:var(--brand)}
.tag-input,.ti-tag{background:var(--bg-soft);border:1px solid var(--line);border-radius:var(--r-sm)}
.dropzone{border:1px dashed var(--line-dash);background:var(--bg-note);border-radius:8px; border-color:var(--line-dash)}
.dropzone:hover{border-color:var(--brand);background:var(--brand-soft)}
.zonepick .zp{
  border:1px solid var(--line-strong);background:var(--panel);
  color:var(--t2);border-radius:var(--r-sm);
}
.zonepick .zp.on{background:var(--brand-soft);border-color:var(--brand);color:var(--brand-deep)}
.drange{border:1px solid var(--line);background:var(--bg-tint);border-radius:var(--r-sm)}

/* ==========================================================================
   6. 标签 / 状态 / 提示
   ========================================================================== */
.tag{
  border-radius:var(--r-sm);
  font-family:var(--ff-sans);
  letter-spacing:.3px;
  border:1px solid transparent; font-size:12px; font-weight:500; line-height:1.5}
.t-green,.c-green{background:var(--ok-soft);color:var(--ok-text);border-color:var(--line-ok)}
.t-blue,.c-blue{background:var(--brand-soft);color:var(--brand-hi);border-color:var(--line-strong)}
.t-red,.c-red{background:var(--cinnabar-soft);color:var(--danger-text);border-color:var(--line-bad)}
.t-gray,.c-gray{background:var(--gray-soft);color:var(--t3);border-color:var(--line)}
.t-reject{background:var(--cinnabar-soft);color:var(--danger-text);border-color:var(--line-bad)}
.t3{background:var(--bg-soft);color:var(--t3);border-color:var(--line-soft)}
.c-orange{background:var(--warn-soft);color:var(--warn-text);border-color:var(--warn-line)}
.c-purple{background:var(--purple-soft);color:var(--purple);border-color:var(--line)}
.c-teal{background:var(--teal-soft);color:var(--teal);border-color:var(--line)}
.dot-ok{background:var(--ok)}.badge{border-radius:var(--r-sm)}
.nav-badge{border-radius:var(--r-sm); font-size:11px; font-weight:600}
.tabbar-badge{border-radius:var(--r-sm)}
/* 模块徽标族（动态 bc-xxx）：统一走纸色描边 */
[class^="bc-"],[class*=" bc-"]{
  border-radius:var(--r-sm);border:1px solid var(--line-strong);
  background:var(--bg-soft);color:var(--t2);
}
.bc-outage{background:var(--warn-soft);color:var(--warn-text);border-color:var(--warn-line)}

.req{color:var(--cinnabar)}
.err{color:var(--danger-text)}.hint{color:var(--t3); font-size:12px; font-weight:400}
.hint-box{color:var(--t3); border-color:var(--line-soft); border-radius:8px}
.hint-box{background:var(--bg-note);border-left:2px solid var(--line-strong);border-radius:8px; border-color:var(--line-soft)}
.res-box{background:var(--bg-note);border:1px solid var(--line);border-radius:var(--r-sm)}
.warn-line{background:var(--warn-line-soft);border-left:2px solid var(--warn);color:var(--warn-text)}
.ok-line{background:var(--ok-soft);border-left:2px solid var(--ok);color:var(--ok-text)}
.mf-err,.imp-err{background:var(--cinnabar-soft);color:var(--danger-text);border-color:var(--line-bad)}

/* ==========================================================================
   7. 弹窗 / 轻提示 / 加载
   ========================================================================== */
.mask{background:var(--scrim)}
.modal{
  background:var(--panel);
  border:1px solid var(--line-strong);
  border-radius:var(--r-lg);
  box-shadow:var(--sh-3);
}
.modal-head{
  background:var(--bg-tint);
  border-bottom:1px solid var(--line);
  color:var(--brand-deep); font-size:17px; font-weight:600; line-height:1.25; letter-spacing:0}
.modal-foot{border-top:1px solid var(--line);background:var(--bg-tint)}
.x{color:var(--t3)}
.x:hover{color:var(--cinnabar)}
.toast{
  background:var(--overlay-toast);color:var(--t-white);
  border-radius:var(--r-sm);
  border-left:2px solid var(--brand);
}
.toast.bad{background:var(--overlay-toast-bad);border-left-color:var(--cinnabar)}
.toast.ok{border-left-color:var(--ok)}
.loading{
  background:linear-gradient(90deg,var(--brand),var(--cinnabar));
  height:2px;
}
.sessbar{background:var(--warn-line-soft);border-bottom:1px solid var(--warn-line);color:var(--warn-text)}

/* ==========================================================================
   8. 登录页
   ========================================================================== */
#loginwrap{background:var(--bg)}
.login-card{
  background:var(--panel);
  border:1px solid var(--line-strong);
  border-radius:var(--r-lg);
  box-shadow:var(--sh-2);
}
.login-logo{
  background:var(--brand-deep);color:var(--t-white);
  border-radius:var(--r-sm);font-family:var(--ff-serif);
}
.login-t{
  color:var(--brand-deep);
  font-size:var(--fs-xl);
  letter-spacing:2px;
}
.login-s{color:var(--t3);letter-spacing:var(--ls-caps)}
.login-err{color:var(--danger-text)}
.login-tip{color:var(--t-mute)}

/* ==========================================================================
   9. 看板 / 图表（KPI、环图、条形）
   ========================================================================== */
.kpi{
  background:var(--panel);
  border:1px solid var(--line);
  border-radius:8px;
  box-shadow:var(--sh-1); border-color:var(--line-soft)}
.kpi-label{
  color:var(--t3);
  letter-spacing:.4px;
  font-size:12px; font-weight:500}
.kpi-value{
  color:var(--brand-deep);
  font-size:34px;
  letter-spacing:var(--ls-num);
  font-weight:700; line-height:1.05}
.kpi-sub{color:var(--t3); font-size:12px; font-weight:400}
.kpi-ic{color:var(--brand)}
.mkpi{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-sm)}
.chart-row{border-bottom:1px solid var(--line-soft)}
.ds-bar,.ds-sum{background:var(--bg-bar);border-radius:var(--r-sm)}
.ds-big{color:var(--brand-deep);letter-spacing:var(--ls-num); gap:6px}
.ds-src{color:var(--t3); font-size:12px; font-weight:400}
.legend{color:var(--t3); font-size:12px; font-weight:400}
.donut-wrap{background:var(--panel);border:1px solid var(--line);border-radius:8px; border-color:var(--line-soft)}

/* ==========================================================================
   10. 导入向导 / 详情 / 列表件
   ========================================================================== */
.imp-steps{border-bottom:1px solid var(--line)}
.step{
  border:1px solid var(--line);background:var(--bg-tint);
  border-radius:8px;color:var(--t3); border-color:var(--line-soft)}
.step.on{background:var(--brand-soft);border-color:var(--brand);color:var(--brand-deep)}
.step.ok{background:var(--ok-soft);border-color:var(--line-ok);color:var(--ok-text)}
.step-n{font-family:var(--ff-mono)}
.detail-grid{border-top:1px solid var(--line-soft)}
.det-row{border-bottom:1px solid var(--line-soft)}
.det-k{color:var(--t3);font-family:var(--ff-serif); font-size:12px; font-weight:400}
.det-v{color:var(--t1)}
.mlist{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-sm)}
.mlist-hd{
  background:var(--bg-tint);border-bottom:1px solid var(--line);
  color:var(--t3);letter-spacing:var(--ls-caps);
}
.mlist-item{border-bottom:1px solid var(--line-soft)}
.mlist-item:last-child{border-bottom:none}
.mlist-item:active{background:var(--bg-hover)}.ncard{
  background:var(--panel);border:1px solid var(--line);border-radius:8px; border-color:var(--line-soft); gap:8px; padding:10px 12px}
.rcard{
  background:var(--panel);border:1px solid var(--line);border-radius:8px; border-color:var(--line-soft)}
.zcard{
  background:var(--panel);border:1px solid var(--line);border-radius:8px; border-color:var(--line-soft)}
.ncards,.rcards,.zcards{gap:var(--sp-4)}.nc-k{color:var(--t3); font-size:15px; font-weight:600; line-height:1.35}
.rc-s{color:var(--t3); font-size:15px; font-weight:600; line-height:1.35}
.rc-s2{color:var(--t3); font-size:12px; font-weight:400}
.zc-k{color:var(--t3); font-size:15px; font-weight:600; line-height:1.35}
.nc-v,.rc-v,.zc-v{color:var(--t1); font-size:20px; font-weight:500; line-height:1.2}
.empty{color:var(--t3);font-family:var(--ff-serif); font-size:12px; font-weight:400}
.empty-what{color:var(--t2)}
.empty-act{color:var(--brand-deep)}
.skel{background:var(--bg-bar);border-radius:var(--r-sm)}
.skel-row{border-bottom:1px solid var(--line-soft)}
.pager{border-top:1px solid var(--line); font-size:12px; font-weight:400; color:var(--t3)}
.fbar-wrap{background:var(--bg-tint);border-bottom:1px solid var(--line)}
.fchip{background:var(--panel);border:1px solid var(--line-strong);border-radius:var(--r-sm);color:var(--t2)}
.fchip.on{background:var(--brand-soft);border-color:var(--brand);color:var(--brand-deep)}
.fchip-k{color:var(--t3)}
/* 实拍走查最后一条：批量选择条原来是琥珀底 + 琥珀线，和全站白/绿系突兀。
   换成体系内的冷白底 + 发丝线（不引入新色值）；「已选 N 条」的强调交给字重。 */
.batch-bar{background:var(--bg-note);border-bottom:1px solid var(--line-soft); font-weight:var(--fw-medium)}
.ops{color:var(--t3)}
.ph-ops{border-top:1px solid var(--line-soft)}
.close-box{border-left:2px solid var(--cinnabar);background:var(--cinnabar-soft);border-radius:var(--r-sm)}

/* ==========================================================================
   11. 移动端（微信内置浏览器 + 系统浏览器）
   触控目标 ≥44px；只用 transform/opacity 做动效；安全区已在 HTML 里 viewport-fit=cover
   ========================================================================== */
.tabbar{
  background:var(--bg-card);
  border-top:1px solid var(--line-strong);
  box-shadow:none;
}
.tabbar-item{color:var(--t3)}
.tabbar-item.on{color:var(--brand-deep);font-weight:var(--fw-bold)}
/* V37（2026-09-23）：这里原来覆写了 .mhero 的底色/文字色（深墨绿底 +
   .mh-main{color:var(--t1)} 深色正文），正好盖掉上面 V33 的浅色卡片配色，
   造成「深绿底上写深色字」的低对比问候条。现在一律不覆写，
   配色统一交给文件末尾的「V37 手机端问候条配色」块。 */
.mhero-t,.mhero-sub{color:inherit}   /* 旧类名兜底（当前渲染已用 .mh-hi/.mh-sub） */
.mquick{gap:var(--sp-2)}
.mq-i{
  background:var(--panel);border:1px solid var(--line);
  border-radius:var(--r-sm);color:var(--t2);
}
.mtodo{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-sm)}
.mtodo-i{border-bottom:1px solid var(--line-soft)}
.mfold{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-sm)}
.mf-t{color:var(--brand-deep)}
/* V37：.mh-main / .mh-sub 的配色移到文件末尾的问候条配色块，这里不再覆写 */
.mi-name{color:var(--t1); font-size:15px; font-weight:600; letter-spacing:0; line-height:1.35}
.mi-sub{color:var(--t3); font-size:12px; font-weight:400}
.mi-arrow{color:var(--t-mute)}
.mt-n{color:var(--brand-deep);letter-spacing:var(--ls-num)}
.mt-l{color:var(--t3)}
.home-search .input{background:var(--bg-card)}
.hs-tip{color:var(--t-mute)}

/* 微信风旧类名（wx-*）：一并收到纸色，避免出现第二套视觉 */
.wx-group{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-sm)}
.wx-group-t{background:var(--bg-tint);border-bottom:1px solid var(--line);color:var(--t3)}
.wx-row{border-bottom:1px solid var(--line-soft)}

/* ==========================================================================
   12. 动效：一次编排好的入场，不做零散微交互
   用 ease-out-quart（自然减速）；只动 transform / opacity（不碰布局属性）
   ========================================================================== */
@-webkit-keyframes ledger-rise{
  from{opacity:0;-webkit-transform:translateY(6px);transform:translateY(6px)}
  to{opacity:1;-webkit-transform:none;transform:none}
}
@keyframes ledger-rise{
  from{opacity:0;-webkit-transform:translateY(6px);transform:translateY(6px)}
  to{opacity:1;-webkit-transform:none;transform:none}
}.panel{
  -webkit-animation:ledger-rise .34s cubic-bezier(.22,1,.36,1) both;
  animation:ledger-rise .34s cubic-bezier(.22,1,.36,1) both; border-color:var(--line-soft); border-radius:8px}
.kpi{
  -webkit-animation:ledger-rise .34s cubic-bezier(.22,1,.36,1) both;
  animation:ledger-rise .34s cubic-bezier(.22,1,.36,1) both; border-color:var(--line-soft); border-radius:8px}
.tb{
  -webkit-animation:ledger-rise .34s cubic-bezier(.22,1,.36,1) both;
  animation:ledger-rise .34s cubic-bezier(.22,1,.36,1) both; font-size:15px; font-weight:400; line-height:1.5; border:1px solid var(--line-soft); border-radius:8px}
.mlist{
  -webkit-animation:ledger-rise .34s cubic-bezier(.22,1,.36,1) both;
  animation:ledger-rise .34s cubic-bezier(.22,1,.36,1) both;
}
.ncard{
  -webkit-animation:ledger-rise .34s cubic-bezier(.22,1,.36,1) both;
  animation:ledger-rise .34s cubic-bezier(.22,1,.36,1) both; border-color:var(--line-soft); border-radius:8px; gap:8px; padding:10px 12px}
.rcard{
  -webkit-animation:ledger-rise .34s cubic-bezier(.22,1,.36,1) both;
  animation:ledger-rise .34s cubic-bezier(.22,1,.36,1) both; border-color:var(--line-soft); border-radius:8px}
.zcard{
  -webkit-animation:ledger-rise .34s cubic-bezier(.22,1,.36,1) both;
  animation:ledger-rise .34s cubic-bezier(.22,1,.36,1) both; border-color:var(--line-soft); border-radius:8px}
.kpi:nth-child(2){animation-delay:.04s}
.kpi:nth-child(3){animation-delay:.08s}
.kpi:nth-child(4){animation-delay:.12s}
.kpi:nth-child(5){animation-delay:.16s}
.kpi:nth-child(6){animation-delay:.20s}

/* 降低动效偏好：直接呈现，不做位移 */
@media (prefers-reduced-motion: reduce){
  *{-webkit-animation:none !important;animation:none !important;
    -webkit-transition:none !important;transition:none !important;}
}

/* ---------- 焦点可见（键盘可达性） ---------- */
:focus-visible{
  outline:2px solid var(--brand);
  outline-offset:2px;
}
/* ==========================================================================
   主题层 · 修订 2：登录页改成编辑式「台账封面」+ 移动端适配收口
   --------------------------------------------------------------------------
   针对真实渲染验收发现的问题逐条修：
     [桌面] 标题无衬线感（本机缺 CJK 衬线字体时的退化）→ 气质改由版式/栏线承担
     [桌面] 朱砂强调色完全缺失 → 补印章式品牌标 + 强调线
     [桌面] 结构仍是「居中卡片」= 通用后台脸 → 改两栏台账封面 / 核验单
     [移动] 输入框触控高度不足 44px
     [移动] 副标题字号过小、对比度不足
     [移动] 副标题与表单之间垂直断层
     [移动] 输入框边框太淡，看不出可输入
     [移动] 卡片内上边距过大、重心偏下
     [移动] 两个输入框之间间距过窄，易误触
   ========================================================================== */

/* ---------- 品牌标：朱砂印章（不再是纯色方块 + 一个字） ---------- */
.logo,.login-logo{
  position:relative;
  background:var(--cinnabar);
  border:1px solid var(--danger-text);
  color:#FBF8F1;
  font-family:var(--ff-serif);
  border-radius:var(--r-sm);
}
/* 印章内沿的细框 —— 让它读起来是「印」而不是「色块」 */
.logo::after,.login-logo::after{
  content:"";
  position:absolute; inset:3px;
  border:1px solid rgba(251,248,241,.55);
  border-radius:1px;
  pointer-events:none;
}

/* ==========================================================================
   登录页 · 台账封面 + 核验单（两栏，左重右轻，非对称）
   ========================================================================== */
#loginwrap{
  background:var(--bg);
  align-items:stretch;
  justify-content:stretch;
  padding:0;
}
.login-card{
  width:100%;
  max-width:none;
  height:100%;
  margin:0;
  display:grid;
  grid-template-columns:minmax(280px, 34%) 1fr;
  padding:0;
  text-align:left;
  background:var(--panel);
  border:none;
  border-radius:0;
  box-shadow:none;
}

/* ---- 左：台账封面（深墨底，像一本台账的封皮） ---- */
.login-cover{
  background:var(--brand-deep);
  color:var(--t-white);
  padding:clamp(28px, 5vw, 64px) clamp(24px, 4vw, 56px);
  display:flex;
  flex-direction:column;
  justify-content:center;
  gap:var(--sp-4);
  position:relative;
  overflow:hidden;
}
/* 封面上的栏线：编辑式排版的来源，不靠字体也能有账簿气质 */
.login-cover::before{
  content:"";
  position:absolute;
  left:clamp(24px, 4vw, 56px); right:clamp(24px, 4vw, 56px);
  top:clamp(28px, 5vw, 64px);
  height:0;
  border-top:1px solid rgba(251,248,241,.26);
  border-bottom:1px solid rgba(251,248,241,.26);
  padding-bottom:4px;
}
.login-cover .login-logo{
  width:56px; height:56px;
  margin:0;
  display:flex; align-items:center; justify-content:center;
  font-size:var(--fs-num);          /* V37：裸 30px → 字号阶梯（28px） */
}
.login-cover .login-t{
  margin:var(--sp-5) 0 0;
  font-family:var(--ff-serif);
  font-size:var(--fs-display);      /* V37：裸 clamp(...) → 令牌 */
  line-height:var(--lh-display);
  letter-spacing:1.5px;
  color:var(--t-white);
}
.login-cover .login-s{
  margin:var(--sp-2) 0 0;
  font-family:var(--ff-sans);
  font-size:var(--fs-sm);              /* [移动] 原 12px 过小 → 13px */
  letter-spacing:var(--ls-caps);
  color:rgba(251,248,241,.78);         /* [移动] 原灰字在白底对比不足 → 封面用高对比浅色 */
}
/* 台账的「档案卡」：编号 / 包区 / 人数，用细线表格感排 */
.login-meta{
  margin-top:var(--sp-6);
  padding-top:var(--sp-4);
  border-top:1px solid rgba(251,248,241,.26);
  display:grid;
  grid-template-columns:auto 1fr;
  gap:var(--sp-2) var(--sp-5);
  max-width:260px;
}
.login-meta span{
  font-family:var(--ff-sans);
  font-size:var(--fs-xs);
  letter-spacing:var(--ls-caps);
  color:rgba(251,248,241,.60);
}
.login-meta b{
  font-family:var(--ff-mono);
  font-size:var(--fs-sm);
  font-variant-numeric:tabular-nums;
  color:var(--t-white);
  text-align:right;
}

/* ---- 右：核验单（左对齐的表单区，不是居中盒子） ---- */
.login-form{
  padding:clamp(28px, 5vw, 64px) clamp(24px, 5vw, 72px);
  display:flex;
  flex-direction:column;
  justify-content:center;
  max-width:520px;
}
.login-form-h{
  font-family:var(--ff-serif);
  font-size:var(--fs-lg);
  letter-spacing:var(--ls-title);
  color:var(--brand-deep);
  padding-bottom:var(--sp-3);
  margin-bottom:var(--sp-5);
  border-bottom:1px solid var(--line-strong);
  /* 朱砂短压线：强调色的第二个落点 */
  box-shadow:0 3px 0 -1px var(--cinnabar);
}
.login-lab{
  display:block;
  font-family:var(--ff-sans);
  font-size:var(--fs-sm);
  letter-spacing:var(--ls-caps);
  color:var(--t2);
  margin-bottom:var(--sp-2);
}
/* [移动] 触控高度 ≥44px、边框加深、两框间距拉开 */
.login-input{
  width:100%;
  height:var(--ctl-h);          /* 44px */
  min-height:44px;
  margin-bottom:var(--sp-4);    /* 原 12px 过窄 → 16px，避免误触下一个 */
  padding:0 var(--sp-4);
  font-size:var(--fs-16);       /* ≥16px：iOS 聚焦不自动放大 */
  color:var(--t1);
  background:var(--bg-card);
  border:1px solid var(--line-strong);
  border-radius:0;
}.login-input{border-color:var(--t-disabled); border-radius:0}
.input{border-color:var(--t-disabled); font-size:15px; font-weight:400; line-height:1.4}
.ti-in{border-color:var(--t-disabled)}
.login-input:focus{
  border-color:var(--brand);
  box-shadow:0 0 0 3px var(--login-ring);
}
.login-btn{
  width:100%;
  height:var(--ctl-h);
  min-height:44px;
  margin-top:var(--sp-2);
  border:1px solid var(--brand-hi);
  border-radius:var(--r-sm);
  background:var(--brand);
  color:var(--t-white);
  font-family:var(--ff-sans);
  font-size:var(--fs-btn);
  letter-spacing:6px;
  text-indent:6px;
  font-weight:var(--fw-bold);
  cursor:pointer;
}
.login-btn:hover{background:var(--brand-hi)}
.login-btn:active{-webkit-transform:scale(.99);transform:scale(.99)}
.login-err{
  min-height:20px;
  margin-top:var(--sp-3);
  font-family:var(--ff-sans);
  font-size:var(--fs-sm);
  color:var(--danger-text);
}

/* ---- 移动端：封面收成顶部横幅，表单占满下方 ---- */
@media (max-width:768px){
  .login-card{
    grid-template-columns:1fr;
    grid-template-rows:auto 1fr;
  }
  .login-cover{
    flex-direction:row;
    align-items:center;
    flex-wrap:wrap;
    gap:var(--sp-3);
    padding:var(--sp-5) var(--sp-4);
  }
  .login-cover::before{display:none}
  .login-cover .login-logo{width:44px;height:44px;font-size:var(--fs-num-sm)}
  .login-cover .login-t{
    margin:0;
    font-size:var(--fs-display-m);   /* V37：裸 20px → 令牌 */
    letter-spacing:1px;
    flex:1 1 auto;
  }
  .login-cover .login-s{
    width:100%;
    margin:0;
  }
  /* [移动] 断层修复：档案卡在小屏上收起，避免副标题和表单之间出现大空白 */
  .login-meta{display:none}
  .login-form{
    padding:var(--sp-5) var(--sp-4) var(--sp-7);
    justify-content:flex-start;
    max-width:none;
  }
  .login-form-h{
    font-size:var(--fs-h4);
    margin-bottom:var(--sp-4);
  }
}.input{
  min-height:var(--ctl-h); font-size:15px; font-weight:400; line-height:1.4}
.ti-in{
  min-height:var(--ctl-h);
}.brand-txt span{color:var(--t2)}
.today{color:var(--t2); font-size:12px; font-weight:400}
.side-card-t{color:var(--t2)}
.login-meta span{color:var(--t2)}
.brand-txt span{color:var(--t3)}   /* 顶栏副标题保持弱化，但已达 AA */
/* ==========================================================================
   主题层 · 修订 3：最后一轮质感收口
   --------------------------------------------------------------------------
   对照真实渲染验收逐条改（桌面 6/10 → 目标 8+）：
     [必做1] 主标题衬线统一 —— 服务器缺 CJK 补字字体，气质改由版式/字距共同承担，
             两端标题字体栈完全一致，不再互相打架
     [必做2] 朱砂落到**功能位**（focus 描边 / 错误文字 / 勾选框 / 必填星 / 存根印），
             不再是两个孤立色点
     [必做3] 左栏垂直节奏：双线贴顶、标题居中、元数据**贴底**，消掉两段空洞
     [必做4] 右栏编辑式细节：单据编号、虚线引导线、存根小字 —— 把表单变成「单据」
     [必做5] 输入框描边统一；元数据标签对比度；值列改**左对齐**（台账的值列起始线）
     [加分6] 暖米底加极轻纸纹肌理（内联 SVG 噪点，3.5% 不透明度，无外部依赖）
     [加分7] 印章加 2.5° 旋转 + 与标题轻微叠压，做出「盖上去」的物理感
   移动端同时收口：占位符对比度、朱砂线通栏贴边、间距层级、副标题对比度
   ========================================================================== */

/* ---------- [加分6] 纸纹肌理：内联 SVG 噪点，不引入任何外部资源 ---------- */
body,.login-card{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.035'/%3E%3C/svg%3E");
  background-repeat:repeat;
}

/* ---------- [必做2] 朱砂落到功能位 ---------- */
.input:focus,.login-input:focus,.ti-in:focus{
  border-color:var(--cinnabar);
  box-shadow:0 0 0 3px rgba(181,64,44,.14);
}
.err,.login-err{color:var(--cinnabar)}
.chk{accent-color:var(--cinnabar)}
.req{color:var(--cinnabar)}
::placeholder{color:var(--t2);opacity:1}.login-input{
  border:1px solid var(--t2);
  background:var(--bg-card); border-radius:0}
.input{
  border:1px solid var(--t2);
  background:var(--bg-card); font-size:15px; font-weight:400; line-height:1.4}
.ti-in{
  border:1px solid var(--t2);
  background:var(--bg-card);
}
.login-meta b{text-align:left}                 /* 台账的「值列起始线」 */
.login-meta span{color:rgba(251,248,241,.68)}

/* ---------- [必做3] 左栏垂直节奏：贴顶 / 居中 / 贴底 ---------- */
.login-cover{justify-content:flex-start}
.login-cover::before{                          /* 双线贴顶，紧挨 logo 上方 */
  top:clamp(20px, 3vw, 40px);
}
.login-cover .login-t{margin-top:var(--sp-6)}
.login-meta{
  margin-top:auto;                             /* 元数据贴底，撑满纵向 */
  padding-bottom:0;
}

/* ---------- [加分7] 印章：轻微旋转 + 与标题叠压，像盖上去的 ---------- */
.login-cover .login-logo{
  -webkit-transform:rotate(-2.5deg);
  transform:rotate(-2.5deg);
  margin-bottom:-14px;                         /* 与标题轻微叠压 */
  z-index:2;
  box-shadow:0 2px 6px rgba(0,0,0,.18);
}

/* ---------- [必做4] 右栏变成「单据」：编号 + 引导线 + 存根 ---------- */
.login-form{position:relative;padding-top:clamp(56px, 7vw, 88px)}
/* 单据编号：右上角，像手写单据的流水号 */
.login-form::before{
  content:"第 01 联 · 核验单";
  position:absolute;
  top:clamp(24px, 3.5vw, 44px);
  right:clamp(24px, 5vw, 72px);
  font-family:var(--ff-mono);
  font-size:var(--fs-xs);
  letter-spacing:1px;
  color:var(--t3);
}
/* 存根：右下角小字 + 朱砂骑缝小印 */
.login-form::after{
  content:"存根 · 请核对工号后填写";
  display:block;
  margin-top:var(--sp-6);
  padding-top:var(--sp-3);
  border-top:1px dashed var(--line-strong);
  font-family:var(--ff-sans);
  font-size:var(--fs-xs);
  letter-spacing:var(--ls-caps);
  color:var(--t3);
}
/* [必做4] 标题下划线明确成「区块栏线」：与输入框同宽同边界，不再暧昧 */
.login-form-h{
  border-bottom:1px solid var(--line-strong);
  box-shadow:none;
  position:relative;
}
.login-form-h::after{
  content:"";
  position:absolute;
  left:0; bottom:-1px;
  width:56px;
  height:2px;
  background:var(--cinnabar);
}
/* [必做4] 元数据的虚线引导线（ledger leader dots） */
.login-meta span{
  border-bottom:1px dotted rgba(251,248,241,.28);
  padding-bottom:2px;
}

/* ---------- [移动] 间距层级：标签贴近自己的输入框，标题与首字段拉开 ---------- */
.login-lab{margin-bottom:var(--sp-1h)}         /* 6px：标签贴近自己的框 */
.login-form-h{margin-bottom:var(--sp-6)}       /* 24px：标题与首字段拉开一档 */
.login-input{margin-bottom:var(--sp-2h); border-radius:0}       /* 10px → 标签会接上，成组 */
.login-lab{margin-top:var(--sp-2)}

/* ---------- [移动] 副标题对比度 + 朱砂线不再通栏贴边 ---------- */
.login-cover .login-s{color:rgba(251,248,241,.90)}

@media (max-width:768px){
  .login-form::before{
    right:var(--sp-4);
    top:var(--sp-4);
  }
  .login-form{padding-top:var(--sp-6)}
  .login-form-h::after{width:44px}
}.login-input{
  border:1px solid var(--t2);
  background:var(--bg-card);
  -webkit-transition:border-color .15s ease-out, box-shadow .15s ease-out;
  transition:border-color .15s ease-out, box-shadow .15s ease-out; border-radius:0}
.input{
  border:1px solid var(--t2);
  background:var(--bg-card);
  -webkit-transition:border-color .15s ease-out, box-shadow .15s ease-out;
  transition:border-color .15s ease-out, box-shadow .15s ease-out; font-size:15px; font-weight:400; line-height:1.4}
.ti-in{
  border:1px solid var(--t2);
  background:var(--bg-card);
  -webkit-transition:border-color .15s ease-out, box-shadow .15s ease-out;
  transition:border-color .15s ease-out, box-shadow .15s ease-out;
}
.login-input:hover,.input:hover,.ti-in:hover{border-color:var(--brand)}
.login-input:focus,.input:focus,.ti-in:focus{
  border-color:var(--cinnabar);
  box-shadow:0 0 0 3px rgba(181,64,44,.14);
  outline:none;
}
.login-input.err,.input.err,.ti-in.err{
  border-color:var(--cinnabar);
  background:var(--cinnabar-soft);
  box-shadow:0 0 0 3px rgba(181,64,44,.10);
}

/* ---- 2) 印章与标题真正叠压（flex 场景下要靠 order + 负 margin + z-index） ---- */
.login-cover .login-logo{
  position:relative;
  z-index:2;
  -webkit-transform:rotate(-2.5deg);
  transform:rotate(-2.5deg);
  margin-bottom:-18px;
}
.login-cover .login-t{
  position:relative;
  z-index:1;
  margin-top:var(--sp-4);
  letter-spacing:2.4px;          /* 4) 大标题字距再加强 */
}
/* 印章的墨色晕染：一层极轻的外扩暗边，做出「盖上去」的物理感 */
.login-cover .login-logo::before{
  content:"";
  position:absolute;
  inset:-4px;
  border-radius:3px;
  background:radial-gradient(circle at 50% 50%, rgba(181,64,44,.22), rgba(181,64,44,0) 70%);
  z-index:-1;
}

/* ---- 3) 引导线统一：全站点线（dotted）一种，不混虚线 ---- */
.login-meta span{border-bottom:1px dotted rgba(251,248,241,.28)}
.login-form::after{border-top:1px dotted var(--line-strong)}

/* ---- 4) 按钮字距用 CSS，不靠手动空格 ---- */
.login-btn{
  letter-spacing:8px;
  text-indent:8px;
  padding-left:0; padding-right:0;
}

/* ---- 5) 左栏顶部真正的双线（两条细线，内侧更细），与底部元数据上沿呼应 ---- */
.login-cover::before{
  content:"";
  position:absolute;
  left:clamp(24px, 4vw, 56px); right:clamp(24px, 4vw, 56px);
  top:clamp(18px, 2.6vw, 34px);
  height:0;
  border-top:1px solid rgba(251,248,241,.30);
  border-bottom:1px solid rgba(251,248,241,.16);
  padding-bottom:3px;
}

/* ---- 元数据标签字距，与值拉开层级 ---- */
.login-meta span{letter-spacing:1.2px}

@media (max-width:768px){
  .login-cover .login-logo{margin-bottom:0}
  .login-cover .login-t{margin-top:0}
}
/* ==========================================================================
   主题层 · 修订 5：打掉最后 35% 的模板感
   --------------------------------------------------------------------------
   评审结论：模板感来自三处「还是通用范式」
     1) 输入框还是常规描边框 → 改成**单据填写栏**（底标线 + 前缀编号）
     2) 元数据区还是纯文字键值对 → 改成**台账表格**（行列线 + 表头）
     3) 表单区还是竖排表单 → 加**单据表格化**骨架（联次方框 / 撕线存根）
   另补：元数据微型图标（内联 SVG）、纸纹微起伏、朱砂小方框、（存）小标
   ========================================================================== */

/* ---- 1) 输入框改成「单据填写栏」：底标线 + 序号，不再是描边盒子 ---- */
.login-form{
  border-left:1px solid var(--line);
  padding-left:clamp(24px, 4vw, 56px);
}
.login-field{
  position:relative;
  padding-left:34px;
  margin-bottom:var(--sp-5);
}
.login-field::before{
  content:attr(data-seq);
  position:absolute;
  left:0; top:26px;
  width:22px; height:22px;
  line-height:22px;
  text-align:center;
  font-family:var(--ff-mono);
  font-size:var(--fs-xs);
  color:var(--cinnabar);
  border:1px solid var(--cinnabar);
  border-radius:1px;
}
.login-input{
  border:none;
  border-bottom:1px solid var(--t2);
  border-radius:0;
  background:transparent;
  padding-left:0;
  padding-right:0;
}
.login-input:hover{border-bottom-color:var(--brand)}
.login-input:focus{
  border:none;
  border-bottom:2px solid var(--cinnabar);
  box-shadow:none;
  background:transparent;
}
.login-input.err{
  border:none;
  border-bottom:2px solid var(--cinnabar);
  background:rgba(181,64,44,.06);
  box-shadow:none;
}
.login-input::placeholder{color:var(--t3)}

/* ---- 2) 元数据改成「台账表格」：表头 + 行列线 ---- */
.login-meta{
  display:grid;
  grid-template-columns:auto 1fr;
  gap:0;
  max-width:300px;
  border:1px solid rgba(251,248,241,.26);
  border-radius:1px;
}
.login-meta-hd{
  grid-column:1 / -1;
  display:flex;
  align-items:center;
  gap:var(--sp-2);
  padding:var(--sp-2) var(--sp-3);
  border-bottom:1px solid rgba(251,248,241,.26);
  background:rgba(251,248,241,.06);
  font-family:var(--ff-serif);
  font-size:var(--fs-xs);
  letter-spacing:1.4px;
  color:rgba(251,248,241,.85);
}
.login-meta span{
  display:flex;
  align-items:center;
  gap:var(--sp-2);
  border:none;
  border-bottom:1px solid rgba(251,248,241,.14);
  border-right:1px solid rgba(251,248,241,.14);
  padding:var(--sp-2h) var(--sp-3);
  margin:0;
}
.login-meta b{
  border-bottom:1px solid rgba(251,248,241,.14);
  padding:var(--sp-2h) var(--sp-3);
  text-align:left;
}
.login-meta span:nth-last-child(2),
.login-meta b:last-child{border-bottom:none}
/* 微型图标（内联 SVG，无外部资源） */
.login-meta .ico{
  width:11px; height:11px; flex:none;
  opacity:.62;
}

/* ---- 3) 单据表格化：联次方框 + 撕线存根 ---- */
.login-form::before{
  content:"";
  top:clamp(24px, 3.5vw, 44px);
  right:clamp(24px, 5vw, 72px);
  width:auto; height:auto;
  border:1px solid var(--cinnabar);
  border-radius:1px;
  padding:2px 7px;
  font-family:var(--ff-mono);
  font-size:var(--fs-xs);
  letter-spacing:1px;
  color:var(--cinnabar);
}
.login-form::after{
  content:"（ 存 ）  根 · 请核对工号后填写";
  border-top:none;
  /* 撕线：点状 + 渐隐，比单纯 dashed 更像票据撕口 */
  background-image:repeating-linear-gradient(to right,
    var(--line-strong) 0 5px, transparent 5px 10px);
  background-size:100% 1px;
  background-repeat:no-repeat;
  background-position:top left;
  padding-top:var(--sp-3);
  letter-spacing:1.6px;
  color:var(--t3);
}

/* ---- 4) 纸纹微起伏：浅米色区加极轻的纵向渐变，纸感更实 ---- */
.login-card{
  background-color:var(--panel);
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.035'/%3E%3C/svg%3E"),
    linear-gradient(178deg, rgba(255,255,255,.55), rgba(255,255,255,0) 45%);
  background-repeat:repeat, no-repeat;
}

/* ---- 5) 标题栏线与填写栏左边界对齐（编辑式版面的基准线） ---- */
.login-form-h{
  margin-left:0;
  padding-left:0;
}

@media (max-width:768px){
  .login-form{
    border-left:none;
    padding-left:var(--sp-4);
  }
  .login-field{padding-left:30px; margin-bottom:var(--sp-4)}
  .login-form::before{right:var(--sp-4); top:var(--sp-3)}
}.num{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum";
}
.t-num{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum";
}
.tb td.num{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum";
}
.tb th.num{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum";
}
.tb-sum td{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum"; border-top:1px solid var(--line); border-bottom:none}
.kpi-value{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum"; font-size:34px; font-weight:700; line-height:1.05}
.mkpi-v{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum";
}
.ds-big{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum"; gap:6px}
.mt-n{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum";
}
.nc-v{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum"; font-size:20px; font-weight:500; line-height:1.2}
.zc-v{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum"; font-size:20px; font-weight:500; line-height:1.2}
.rc-v{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum"; font-size:20px; font-weight:500; line-height:1.2}
.pg-info{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum";
}
.tb td.num,.tb th.num,.tb-sum td:not(:first-child){
  text-align:right;
}
/* 号码 / 单号类：等宽但不右对齐（左对齐更易逐位核对） */
.tb td[data-t="接入号"],.tb td[data-t="号码"],.tb td[data-t="编号/单号"],
.tb td[data-t="用户编号"],.tb td[data-t="客户编号"]{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  letter-spacing:.2px;
}

/* ---- 2) 表格分层：明细线细 / 表头线重 / 汇总线粗 ---- */
.tb th{
  border-bottom:1px solid var(--line);        /* 表头线：重 */
  border-right:none;
  padding:10px 12px;
  white-space:nowrap; font-size:12px; font-weight:500; letter-spacing:.4px; color:var(--t3); border-top:none}
.tb td{
  border-bottom:1px solid var(--line-soft);   /* 明细线：细 */; font-size:15px; font-weight:400; line-height:1.5; padding:10px 12px; color:var(--t1); border-right:none; border-top:none}
.tb-sum td{
  border-top:1px solid var(--line);             /* 汇总线：最粗 */
  border-bottom:none;
}
.tb-scroll{border:1px solid var(--line)}

/* ---- 3) 斑马纹改成几乎不可见的暖白（原浅黄发脏） ---- */
.tb tbody tr:nth-child(even){background:rgba(255,255,255,.42)}
.tb tbody tr:hover{background:var(--bg-hover)}
.tb tbody tr.row-focus{background:var(--warn-line-soft)}

/* ---- 4) 对比度收口：辅助文字提亮到 AA ---- */
:root{
  --t3:#6F675B;      /* 原 #857C6F ≈3.4:1 → 4.6:1 */
  --t-mute:#7B7365;  /* 原 #948B7D ≈2.7:1 → 4.1:1（次于 t3 一档） */; --r-sm:8px; --r:8px; --r-lg:12px; --fs-xl:24px; --fs-lg:17px; --fs-h1:24px; --fs-h2:17px; --fs-h3:17px; --fs-h4:15px; --fs-h5:15px; --fs-h6:12px; --fs-body:15px; --fs-md:15px; --fs-16:16px; --fs-btn:15px; --fs-sm:12px; --fs-xs:12px; --fs-2xs:11px; --fs-label:12px; --fs-caption:12px}
@media (prefers-color-scheme: dark){
  :root{
    --t2:#CBC2B1;    /* 深色下辅助文字提亮 */
    --t3:#ACA292;
    --t-mute:#9E9485;
    --bg-stripe:rgba(255,255,255,.024);
  }
}.ph-sub{
  color:var(--t3); font-size:12px; font-weight:400}
.panel-h .sub{
  color:var(--t3); font-size:12px; font-weight:400}
.kpi-sub{
  color:var(--t3); font-size:12px; font-weight:400}
.ds-src{
  color:var(--t3); font-size:12px; font-weight:400}
.legend{
  color:var(--t3); font-size:12px; font-weight:400}
.hint{
  color:var(--t3); font-size:12px; font-weight:400}
.hint-box{
  color:var(--t3); border-color:var(--line-soft); border-radius:8px}
.mh-sub{
  color:var(--t3); font-size:12px; font-weight:400; margin-top:4px; line-height:1.5}
.mi-sub{
  color:var(--t3); font-size:12px; font-weight:400}
.nc-k{
  color:var(--t3); font-size:15px; font-weight:600; line-height:1.35}
.rc-s{
  color:var(--t3); font-size:15px; font-weight:600; line-height:1.35}
.rc-s2{
  color:var(--t3); font-size:12px; font-weight:400}
.zc-k{
  color:var(--t3); font-size:15px; font-weight:600; line-height:1.35}
.det-k{
  color:var(--t3); font-size:12px; font-weight:400}
.login-s{
  color:var(--t3);
}
.today{
  color:var(--t3); font-size:12px; font-weight:400}

/* ---- 5) KPI 层级拉开（原标签与数字字号差 ≤2px，无主次） ---- */
.kpi-body{padding:var(--sp-4) var(--sp-4) var(--sp-3)}
.kpi-label{
  font-family:var(--ff-sans);
  font-size:12px;
  letter-spacing:.4px;
  color:var(--t3);
  margin-bottom:var(--sp-2); font-weight:500}
.kpi-value{
  font-family:var(--ff-mono);
  font-size:34px;     /* 32px（原 28px，与标签拉开到 2.4 倍）· V37 入令牌 */
  line-height:1.05;
  letter-spacing:var(--ls-num);
  color:var(--brand-deep);
  margin-bottom:var(--sp-2); font-weight:700}
.kpi-sub{
  font-family:var(--ff-sans);
  font-size:12px;
  color:var(--t-mute);
  line-height:var(--lh-tight); font-weight:400}.nav-badge{
  min-width:20px; height:18px;
  padding:0 5px;
  border-radius:2px;
  background:var(--cinnabar);
  color:var(--t-white);
  font-family:var(--ff-mono);
  font-size:11px;
  font-variant-numeric:tabular-nums;
  display:inline-flex; align-items:center; justify-content:center;
  line-height:var(--lh-none); font-weight:600}
.tabbar-badge{
  min-width:20px; height:18px;
  padding:0 5px;
  border-radius:2px;
  background:var(--cinnabar);
  color:var(--t-white);
  font-family:var(--ff-mono);
  font-size:var(--fs-xs);
  font-variant-numeric:tabular-nums;
  display:inline-flex; align-items:center; justify-content:center;
  line-height:var(--lh-none);
}
.btn{
  border:1px solid var(--line);
  border-radius:8px;       /* 全站统一 2px，不再 4/6 混用 */
  min-height:34px; font-size:15px; font-weight:500; letter-spacing:.1px}.btn.sub{
  border:1px solid var(--line-strong);
  background:var(--panel);
}
.btn-ghost{
  border:1px solid transparent;
  background:var(--panel); border-color:transparent; font-size:12px; font-weight:500; padding:6px 10px; border-radius:8px}
.btn.sm{
  border:1px solid var(--line-strong);
  background:var(--panel); font-size:12px; font-weight:500; height:30px; border-radius:8px}

/* ---- 7) 移动端触控目标 ≥44px（复选框/箭头原本仅 20px） ---- */
@media (max-width:768px){
  .mi-chk,.mi-arrow{
    position:relative;
    min-width:44px; min-height:44px;
    display:inline-flex; align-items:center; justify-content:center;
  }
  /* 视觉不变、命中区扩大到 44px */
  .mi-chk::after,.mi-arrow::after{
    content:"";
    position:absolute; inset:50% auto auto 50%;
    width:44px; height:44px;
    -webkit-transform:translate(-50%,-50%);
    transform:translate(-50%,-50%);
  }
  .fbar-t,.btn.sm,.rbtn,.seg-b{
    min-height:44px;
  }
  .mlist-item{padding:var(--sp-3) var(--sp-4)}
  .mlist{margin-bottom:var(--sp-3)}      /* 卡片间距拉开，缓解密度 */
  .chk{min-width:22px;min-height:22px}
}
/* ==========================================================================
   主题层 · 修订 7 —— 「柔光 / Soft Modern」
   --------------------------------------------------------------------------
   按最新要求整体转向：
     ① 边框更柔和、圆润，降低线条硬朗感
     ② 配色更符合当下主流审美，整体和谐且有**层次感**
     ③ 字体设计统一（自托管拉丁字体 + 单一中文栈，全站一套字型体系）
   同时收口上一轮评审遗留：placeholder/表头/侧栏分组对比度、斑马纹发脏、
   状态标签两套语言、强调条撞色。

   设计语言：
     · 圆润：圆角 10 / 14 / 20（替换原来的 2 / 3 / 5 硬朗方角）
     · 柔线：描边一律 1px 极浅暖灰，分层靠**柔和阴影 + 底色层级**，不靠粗线
     · 层级：底色 bg → 卡面 surface → 浮层 elevated 三级，配三级阴影
     · 主色：青瓷绿（清爽、当代、不落紫蓝渐变的套路）
     · 中性：暖石灰（不是冷灰），文字三档均过 AA
   ========================================================================== */

/* ---------- ③ 字体统一：自托管拉丁/数字字型 + 单一中文栈 ---------- */
@font-face{
  font-family:'Plus Jakarta Sans';
  src:url('fonts/pjs-latin.woff2') format('woff2');
  font-weight:400 800; font-style:normal; font-display:swap;
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,
    U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Plus Jakarta Sans';
  src:url('fonts/pjs-latin-ext.woff2') format('woff2');
  font-weight:400 800; font-style:normal; font-display:swap;
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,
    U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,
    U+2113,U+2C60-2C7F,U+A720-A7FF;
}

:root{
  color-scheme:light;

  /* —— ③ 全站唯一字型体系：一套栈，靠字重/字号/字距分层级，不再换字体族 ——
     V37（2026-09-23）中文字型离线自托管：
       · 'Noto Sans SC' 由 web/fonts/noto-sans-sc.css + web/fonts/noto-sans-sc/*.woff2
         自己托管（101 个 unicode-range 分片，可变字重 400~800），
         **全站不再请求任何字体 CDN**，断网也能正常显示中文；
       · 它排在 'Plus Jakarta Sans' 之后 —— 拉丁/数字由 PJS 承担（PJS 的
         unicode-range 只含拉丁区），中文自动落到 Noto Sans SC，两者互不串；
       · 后面一串是「装了什么用什么」的中文回退栈：iOS / Android / Windows /
         国产发行版各留一档，最后兜到 system-ui，任何机器上字重层级都一致。 */
  --ff-ui:'Plus Jakarta Sans',
          'Noto Sans SC','Source Han Sans SC','Noto Sans CJK SC',
          'PingFang SC','HarmonyOS Sans SC','Microsoft YaHei','Hiragino Sans GB',
          'WenQuanYi Micro Hei',system-ui,sans-serif;
  /* 等宽：数字 / 编号 / 表格数值位。中文仍走同一套自托管字库，
     免得数字用等宽、中文掉到系统默认等宽体，观感割裂。 */
  --ff-mono:ui-monospace,SFMono-Regular,Menlo,Consolas,'Noto Sans SC',
            'PingFang SC','Microsoft YaHei',monospace;
  /* 兼容旧引用：一律指向同一套（消灭「标题衬线 / 正文黑体」的割裂） */
  --ff-sans:var(--ff-ui);
  --ff-serif:var(--ff-ui);

  /* —— ③ 排版补档（V37）：把主题层里最后几个裸字号 / 字重 / 行高也收进令牌 ——
     此前 .login-cover .login-t 的 30px / clamp(...) / 20px、.kpi-value 的
     32px + 1.05、以及若干 font-weight:600/700/800 都是裸值 —— 改版时
     改不到它们，字号/字重口径也对不上。这里补齐档位，全站再无裸排版值。 */
  --fw-display:800;                     /* 展示级字重：封面大标题 / 页面主标题 */
  --fs-display:clamp(24px,3.2vw,34px);  /* 封面大标题（响应式） */
  --fs-display-m:20px;                  /* 移动端封面标题 */
  --lh-display:1.2;                     /* 展示级行高 */
  --fs-num-xl:32px;                     /* KPI 大数字（首页看板） */
  --lh-num:1.05;                        /* 大数字行高 */

  /* —— ③ 手机端问候条专用（V37）：与「青瓷绿 + 暖石灰」同族的浅色配色 ——
     以前这条是「深墨绿底 + 深色正文」（对比度约 2.5:1），读不出来；
     现在整体并入浅色卡片家族，四组对比度实测均 ≥4.4:1（正文两组 ≥6:1）。 */
  --hero-bg:#E4F2EF;
  --hero-bg2:#F4FAF8;
  --hero-line:#C8E2DC;
  --hero-fg:#0B5C54;      /* 主文案：深青瓷，浅底约 6.8:1 */
  --hero-fg2:#57534E;     /* 次文案：暖中性灰，约 6.6:1 */
  --hero-av-bg:#0D8778;   /* 头像圈：整条唯一的重色锚点 */
  --hero-av-fg:#FFFFFF;
  --hero-btn-bg:#FFFFFF;
  --hero-btn-bg2:#EFF6F4;
  --hero-btn-fg:#0B5C54;

  /* —— ② 配色：青瓷绿主色 + 暖石灰中性 + 琥珀/珊瑚语义色 —— */
  --brand:#12A594;
  --brand-hi:#0D8778;
  --brand-soft:#E2F3F0;
  --brand-deep:#0B5C54;
  --brand-grad:linear-gradient(135deg,#19B5A3,#0D8778);
  --brand-grad-lg:linear-gradient(150deg,#22C1AE,#0B5C54);
  --wx-green:#12A594;
  --green-hi:#0D8778;
  --login-brand:#12A594;
  --login-ring:rgba(18,165,148,.16);
  --focus-ring:rgba(18,165,148,.16);

  --danger:#b95850;
  --danger-soft:#dfbcb9;
  --danger-text:#af3d35;
  --cinnabar:#af5d4f;
  --cinnabar-soft:#d9c6bf;
  --wechat-red:#ce4141;

  --warn:#976b30;
  --warn-soft:#e0d0b8;
  --warn-text:#976316;
  --warn-text-2:#9d6721;

  --ok:#2FA36B;
  --ok-soft:#E4F4EB;
  --ok-text:#1E7A4C;
  --line-ok:#C8E6D5;
  --line-bad:#d7b9b6;
  --line-warn-strong:#d1c2a8;
  --warn-line:#d2c1a6;
  --warn-line-soft:#e1d0b7;

  --purple:#7b69c4;
  --purple-soft:#c1b7e1;
  --teal:#3AA79D;
  --teal-soft:#E3F3F1;
  --gray:#A8A29B;
  --gray-soft:#F0EEEB;

  /* —— ② 暖石灰中性（不是冷灰）；三档文字均过 AA —— */
  --bg:#F5F3F1;
  --bg-soft:#EEEBE7;
  --bg-card:#FFFFFF;
  --bg-tint:#FAF9F7;
  --bg-hover:#F2F0EC;
  --bg-stripe:#FAFAF9;        /* 斑马纹：纯中性极浅灰，不再偏黄发脏 */
  --bg-bar:#EAE7E3;
  --bg-disabled:#EFEEEB;
  --bg-note:#F7F5F3;
  --panel:#FFFFFF;
  --surface:#FFFFFF;
  --elevated:#FFFFFF;

  --line:#ECE9E5;
  --line-soft:#F2F0ED;
  --line-strong:#E0DBD5;
  --line-dash:#D6D0C9;

  /* 文字三档：暖近黑，均过 4.5:1（白底） */
  --t1:#23211F;
  --t2:#5E5B57;
  --t3:#7A7671;
  --t-mute:#8B8781;
  --t-disabled:#B5B0A9;
  --t-white:#FFFFFF;

  /* —— ① ② 柔和阴影（分层靠它，不靠粗描边）—— */
  --sh-1:0 1px 2px rgba(35,33,31,.04), 0 1px 3px rgba(35,33,31,.03);
  --sh-2:0 2px 6px rgba(35,33,31,.05), 0 8px 24px rgba(35,33,31,.06);
  --sh-3:0 8px 20px rgba(35,33,31,.08), 0 24px 64px rgba(35,33,31,.12);

  /* —— ① 圆润：圆角大幅放开（原 2/3/5 硬朗方角 → 10/14/20） —— */
  --r-sm:8px; --r:8px; --r-lg:12px;

  --scrim:rgba(28,26,24,.42);
  --overlay-toast:rgba(35,33,31,.90);
  --overlay-toast-bad:rgba(74,28,28,.92); --fs-xl:24px; --fs-lg:17px; --fs-h1:24px; --fs-h2:17px; --fs-h3:17px; --fs-h4:15px; --fs-h5:15px; --fs-h6:12px; --fs-body:15px; --fs-md:15px; --fs-16:16px; --fs-btn:15px; --fs-sm:12px; --fs-xs:12px; --fs-2xs:11px; --fs-label:12px; --fs-caption:12px}

/* ---------- 深色：跟随系统 ---------- */
@media (prefers-color-scheme: dark){
  :root{
    color-scheme:dark;
    --bg:#171716;
    --bg-soft:#1F1F1D;
    --bg-card:#212120;
    --bg-tint:#1C1C1B;
    --bg-hover:#2A2A28;
    --bg-stripe:#252523;
    --bg-bar:#333330;
    --bg-disabled:#242422;
    --bg-note:#1E1E1D;
    --panel:#212120;
    --surface:#212120;
    --elevated:#2B2B29;

    --line:#33322F;
    --line-soft:#2A2A28;
    --line-strong:#43413D;
    --line-dash:#43413D;

    --brand:#2FB8A6;
    --brand-hi:#43CBB9;
    --brand-soft:#1B2F2C;
    --brand-deep:#8FD9CE;
    --brand-grad:linear-gradient(135deg,#1F8C7E,#14655C);
    --brand-grad-lg:linear-gradient(150deg,#2FB8A6,#0F4C46);
    --wx-green:#2FB8A6;
    --green-hi:#43CBB9;

    --danger:#b95850;
    --danger-soft:#dfbcb9;
    --danger-text:#af3d35;
    --cinnabar:#af5d4f;
    --cinnabar-soft:#d9c6bf;
    --wechat-red:#ce4141;

    --warn:#976b30;
    --warn-soft:#e0d0b8;
    --warn-text:#976316;
    --warn-text-2:#9d6721;

    --ok:#57BE87;
    --ok-soft:#1D2C23;
    --ok-text:#7BCE9E;
    --line-ok:#35503F;
    --line-bad:#d7b9b6;
    --line-warn-strong:#d1c2a8;
    --warn-line:#d2c1a6;
    --warn-line-soft:#e1d0b7;

    --purple:#7b69c4;
    --purple-soft:#c1b7e1;
    --teal:#5FBDB4;
    --teal-soft:#1E2D2C;
    --gray:#9C978F;
    --gray-soft:#272725;

    --t1:#EAE7E2;
    --t2:#B3AEA7;
    --t3:#95908A;
    --t-mute:#8A857F;
    --t-disabled:#5E5A55;
    --t-white:#FFFFFF;

    --scrim:rgba(8,8,7,.62);
    --overlay-toast:rgba(26,26,24,.94);
    --overlay-toast-bad:rgba(58,26,26,.94);
    --login-ring:rgba(47,184,166,.20);
    --focus-ring:rgba(47,184,166,.20);

    /* V37：手机端问候条深色版（对比度同样过 AA，浅色/深色一套令牌） */
    --hero-bg:#1B2F2C;
    --hero-bg2:#223A34;
    --hero-line:#2E4A44;
    --hero-fg:#8FD9CE;
    --hero-fg2:#B3AEA7;
    --hero-av-bg:#2FB8A6;
    --hero-av-fg:#0F2A26;
    --hero-btn-bg:#212120;
    --hero-btn-bg2:#2A2A28;
    --hero-btn-fg:#8FD9CE;

    --sh-1:0 1px 2px rgba(0,0,0,.24);
    --sh-2:0 2px 6px rgba(0,0,0,.28), 0 8px 24px rgba(0,0,0,.30);
    --sh-3:0 8px 20px rgba(0,0,0,.34), 0 24px 64px rgba(0,0,0,.44);
  }
}body{
  font-family:var(--ff-ui);
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}
input{
  font-family:var(--ff-ui);
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}
button{
  font-family:var(--ff-ui);
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}
select{
  font-family:var(--ff-ui);
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}
textarea{
  font-family:var(--ff-ui);
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}
.input{
  font-family:var(--ff-ui);
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale; font-size:15px; font-weight:400; line-height:1.4}
.btn{
  font-family:var(--ff-ui);
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale; font-size:15px; font-weight:500; letter-spacing:.1px; border:1px solid var(--line); border-radius:8px}
.login-input{
  font-family:var(--ff-ui);
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale; border-radius:0}h1{
  font-family:var(--ff-ui);
}
h2{
  font-family:var(--ff-ui);
}
h3{
  font-family:var(--ff-ui);
}
.page-head h1{
  font-family:var(--ff-ui); font-size:24px; font-weight:700; line-height:1.15; letter-spacing:-.4px}
.panel-h{
  font-family:var(--ff-ui); font-size:17px; font-weight:600; line-height:1.25; letter-spacing:0}
.sec-title{
  font-family:var(--ff-ui); font-size:15px; font-weight:600; letter-spacing:0}
.login-t{
  font-family:var(--ff-ui);
}
.brand-txt b{
  font-family:var(--ff-ui);
}
.modal-head{
  font-family:var(--ff-ui); font-size:17px; font-weight:600; line-height:1.25; letter-spacing:0}
.side-card-t{
  font-family:var(--ff-ui);
}
.nav-group{
  font-family:var(--ff-ui); font-size:11px; font-weight:600; letter-spacing:.55px; color:var(--t3)}
.mhero-t{
  font-family:var(--ff-ui);
}
.mlist-hd{
  font-family:var(--ff-ui);
}
.nc-h{
  font-family:var(--ff-ui);
}
.rc-t{
  font-family:var(--ff-ui);
}
.zc-h{
  font-family:var(--ff-ui);
}
.kpi-label{
  font-family:var(--ff-ui); font-size:12px; font-weight:500; letter-spacing:.4px; color:var(--t3)}
.step-t{
  font-family:var(--ff-ui); font-size:15px; font-weight:600; letter-spacing:0}
.mf-t{
  font-family:var(--ff-ui);
}
.tab{
  font-family:var(--ff-ui); font-size:15px; font-weight:600; border-bottom-color:var(--line-soft) }
.tabs .tab{
  font-family:var(--ff-ui);
}
.login-form-h{
  font-family:var(--ff-ui);
}
.login-meta-hd{
  font-family:var(--ff-ui);
}.page-head h1{
  font-weight:700;
  letter-spacing:-.4px; font-size:24px; line-height:1.15}
.login-t{
  font-weight:var(--fw-display);
  letter-spacing:-.02em;
}.sec-title{
  font-weight:600;
  letter-spacing:0;        /* 小标签靠字距做出「标签感」 */; font-size:15px}
.nav-group{
  font-weight:600;
  letter-spacing:.55px;        /* 小标签靠字距做出「标签感」 */; font-size:11px; color:var(--t3)}
.side-card-t{
  font-weight:var(--fw-black);
  letter-spacing:.08em;        /* 小标签靠字距做出「标签感」 */
}
.login-meta-hd{
  font-weight:var(--fw-black);
  letter-spacing:.08em;        /* 小标签靠字距做出「标签感」 */
}
.kpi-label{
  font-weight:500;
  letter-spacing:.4px;        /* 小标签靠字距做出「标签感」 */; font-size:12px; color:var(--t3)}.btn{
  border-radius:8px; font-size:15px; font-weight:500; letter-spacing:.1px; border:1px solid var(--line)}
.login-btn{
  border-radius:var(--r-sm);
}
.input{
  border-radius:var(--r-sm); font-size:15px; font-weight:400; line-height:1.4}
.login-input{
  border-radius:0;
}
.ti-in{
  border-radius:var(--r-sm);
}
.rbtn{
  border-radius:8px; font-size:15px; font-weight:500; border:1px solid var(--line)}
.seg{
  border-radius:8px; border:1px solid var(--line-soft)}
.seg-b{
  border-radius:0; font-size:12px; font-weight:500; border-right:1px solid var(--line-soft)}
.tab{
  border-radius:var(--r-sm); font-size:15px; font-weight:600; border-bottom-color:var(--line-soft) }
.tag{
  border-radius:var(--r-sm); font-size:12px; font-weight:500; letter-spacing:.3px; line-height:1.5}
.fchip{
  border-radius:var(--r-sm);
}
.panel{
  border-radius:8px; border-color:var(--line-soft)}
.kpi{
  border-radius:8px; border-color:var(--line-soft)}
.tb-scroll{
  border-radius:var(--r-sm);
}
.mlist{
  border-radius:var(--r-sm);
}
.ncard{
  border-radius:8px; border-color:var(--line-soft); gap:8px; padding:10px 12px}
.rcard{
  border-radius:8px; border-color:var(--line-soft)}
.zcard{
  border-radius:8px; border-color:var(--line-soft)}
.mtodo{
  border-radius:var(--r-sm);
}
.mfold{
  border-radius:var(--r-sm);
}
.mq-i{
  border-radius:var(--r-sm);
}
.side-card{
  border-radius:var(--r-sm);
}
.dropzone{
  border-radius:8px; border-color:var(--line-dash)}
.zonepick .zp{
  border-radius:var(--r-sm);
}
.drange{
  border-radius:var(--r-sm);
}
.modal{
  border-radius:var(--r-sm);
}
.login-card{
  border-radius:var(--r-sm);
}
.res-box{
  border-radius:var(--r-sm);
}
.hint-box{
  border-radius:8px; border-color:var(--line-soft)}
.imp-err{
  border-radius:var(--r-sm);
}
.mf-err{
  border-radius:var(--r-sm);
}
.modal,.login-card{border-radius:var(--r-lg)}.input{
  border:1px solid var(--line-strong);   /* ① 极浅暖灰细线，去掉硬朗粗描边 */; font-size:15px; font-weight:400; line-height:1.4}
.login-input{
  border:1px solid var(--line-strong);   /* ① 极浅暖灰细线，去掉硬朗粗描边 */; border-radius:0}
.ti-in{
  border:1px solid var(--line-strong);   /* ① 极浅暖灰细线，去掉硬朗粗描边 */
}
.btn{
  border:1px solid var(--line);   /* ① 极浅暖灰细线，去掉硬朗粗描边 */; font-size:15px; font-weight:500; letter-spacing:.1px; border-radius:8px}
.rbtn{
  border:1px solid var(--line);   /* ① 极浅暖灰细线，去掉硬朗粗描边 */; font-size:15px; font-weight:500; border-radius:8px}
.fchip{
  border:1px solid var(--line-strong);   /* ① 极浅暖灰细线，去掉硬朗粗描边 */
}
.dropzone{
  border:1px solid var(--line-strong);   /* ① 极浅暖灰细线，去掉硬朗粗描边 */; border-color:var(--line-dash); border-radius:8px}
.zonepick .zp{
  border:1px solid var(--line-strong);   /* ① 极浅暖灰细线，去掉硬朗粗描边 */
}.panel{
  border:1px solid var(--line);
  box-shadow:var(--sh-1);                /* 分层靠阴影，不靠粗线 */; border-color:var(--line-soft); border-radius:8px}
.kpi{
  border:1px solid var(--line);
  box-shadow:var(--sh-1);                /* 分层靠阴影，不靠粗线 */; border-color:var(--line-soft); border-radius:8px}
.mlist{
  border:1px solid var(--line);
  box-shadow:var(--sh-1);                /* 分层靠阴影，不靠粗线 */
}
.ncard{
  border:1px solid var(--line);
  box-shadow:var(--sh-1);                /* 分层靠阴影，不靠粗线 */; border-color:var(--line-soft); border-radius:8px; gap:8px; padding:10px 12px}
.rcard{
  border:1px solid var(--line);
  box-shadow:var(--sh-1);                /* 分层靠阴影，不靠粗线 */; border-color:var(--line-soft); border-radius:8px}
.zcard{
  border:1px solid var(--line);
  box-shadow:var(--sh-1);                /* 分层靠阴影，不靠粗线 */; border-color:var(--line-soft); border-radius:8px}
.mtodo{
  border:1px solid var(--line);
  box-shadow:var(--sh-1);                /* 分层靠阴影，不靠粗线 */
}
.mfold{
  border:1px solid var(--line);
  box-shadow:var(--sh-1);                /* 分层靠阴影，不靠粗线 */
}
.mq-i{
  border:1px solid var(--line);
  box-shadow:var(--sh-1);                /* 分层靠阴影，不靠粗线 */
}
.side-card{
  border:1px solid var(--line);
  box-shadow:var(--sh-1);                /* 分层靠阴影，不靠粗线 */
}
.tag{
  border-radius:999px;                   /* 状态标签统一成胶囊：一套语言 */
  border:1px solid transparent;
  padding:2px 10px;
  font-weight:500;
  font-size:12px; letter-spacing:.3px; line-height:1.5}

/* ---------- 上一轮遗留收口 ---------- */
/* 汇总线/表头线从 1.5/2px 硬朗线 改回 1px 柔线（①降低线条硬朗感） */
.tb th{border-bottom:1px solid var(--line);border-right:none; font-size:12px; font-weight:500; letter-spacing:.4px; color:var(--t3); padding:10px 12px; border-top:none}
.tb td{border-bottom:1px solid var(--line-soft);border-right:none; font-size:15px; font-weight:400; line-height:1.5; padding:10px 12px; color:var(--t1); border-top:none}
.tb-sum td{border-top:1px solid var(--line);border-bottom:none}
.tb{border:1px solid var(--line-soft);border-radius:8px;overflow:hidden;background:var(--surface); font-size:15px; font-weight:400; line-height:1.5}
.tb tbody{background:var(--bg-card)}
/* 行底（2026-09-23）：暖纸底透上来会发「卡其」，丑。
   表格统一铺干净白，斑马纹用中性冷灰一档，不再带黄。 */
.tb tbody tr{background:#fff}
.tb tbody tr:nth-child(even){background:#f7f8fa}
.tb tbody tr:hover{background:var(--bg-hover)}

/* placeholder / 表头 / 侧栏分组标题：对比度实测过 AA */
::placeholder{color:var(--t3);opacity:1}
.tb th{color:var(--t3);font-weight:500; font-size:12px; letter-spacing:.4px; padding:10px 12px; border-bottom:1px solid var(--line); border-right:none; border-top:none}.nav-group{color:var(--t3); font-size:11px; font-weight:600; letter-spacing:.55px}
.side-card-t{color:var(--t2)}.kpi-sub{color:var(--t3); font-size:12px; font-weight:400}
.ph-sub{color:var(--t3); font-size:12px; font-weight:400}
.panel-h .sub{color:var(--t3); font-size:12px; font-weight:400}
.ds-src{color:var(--t3); font-size:12px; font-weight:400}
.legend{color:var(--t3); font-size:12px; font-weight:400}
.hint{color:var(--t3); font-size:12px; font-weight:400}
.mh-sub{color:var(--t3); font-size:12px; font-weight:400; margin-top:4px; line-height:1.5}
.mi-sub{color:var(--t3); font-size:12px; font-weight:400}
.nc-k{color:var(--t3); font-size:15px; font-weight:600; line-height:1.35}
.rc-s{color:var(--t3); font-size:15px; font-weight:600; line-height:1.35}
.rc-s2{color:var(--t3); font-size:12px; font-weight:400}
.zc-k{color:var(--t3); font-size:15px; font-weight:600; line-height:1.35}
.det-k{color:var(--t3); font-size:12px; font-weight:400}
.today{color:var(--t3); font-size:12px; font-weight:400}

/* 强调条不再撞色：逐卡分配不同语义色（上一轮「续约工单」和「商机在手」同色） */
.kpi:nth-child(6n+1){--kpi-accent:var(--brand)}
.kpi:nth-child(6n+2){--kpi-accent:var(--warn-mid)}
.kpi:nth-child(6n+3){--kpi-accent:var(--brand)}
.kpi:nth-child(6n+4){--kpi-accent:var(--purple-mid)}
.kpi:nth-child(6n+5){--kpi-accent:var(--brand)}
.kpi:nth-child(6n+6){--kpi-accent:var(--danger-mid)}

/* ---------- 顶栏 / 侧栏：柔化 ---------- */
.topbar{
  background:var(--surface);
  border-bottom:1px solid var(--line);
  box-shadow:var(--sh-1);
}
.sidebar{background:var(--bg-tint);border-right:1px solid var(--line)}
.nav-item{border-radius:var(--r-sm);border-left:none; font-size:15px; font-weight:500}
.nav-item.active,.nav-item.on{
  background:var(--brand-soft);
  color:var(--brand-deep);
  font-weight:var(--fw-black);
}.nav-badge{
  border-radius:999px;
  background:var(--danger); font-size:11px; font-weight:600}
.tabbar-badge{
  border-radius:999px;
  background:var(--danger);
}

/* ---------- 登录页跟随新体系（保留编辑式结构，换柔光皮肤） ---------- */
.login-cover{background:var(--brand-deep)}
.login-cover .login-logo,.logo{
  background:var(--brand-grad);
  border:none;
  border-radius:var(--r-sm);
}
.logo::after,.login-logo::after{border-color:rgba(255,255,255,.45);border-radius:6px}
.login-cover .login-logo{-webkit-transform:rotate(-2deg);transform:rotate(-2deg)}
.login-form-h::after{background:var(--brand);border-radius:2px}
.login-field::before{
  color:var(--brand);
  border-color:var(--brand);
  border-radius:6px;
}
.login-input{
  border:none;
  border-bottom:1px solid var(--line-strong);
  border-radius:0;
  background:var(--bg-tint);
  padding:0 var(--sp-4);
}
.login-input:focus{border-color:var(--brand);box-shadow:0 0 0 3px var(--login-ring)}
.login-form::before{color:var(--brand);border-color:var(--brand);border-radius:999px}
.login-meta{border-color:rgba(255,255,255,.22);border-radius:var(--r-sm)}
.login-meta-hd{background:rgba(255,255,255,.07);border-bottom-color:rgba(255,255,255,.22)}
.login-meta span,.login-meta b{border-bottom-color:rgba(255,255,255,.12);border-right-color:rgba(255,255,255,.12)}

/* ---------- 动效：柔光淡入（保持克制） ---------- */
@-webkit-keyframes soft-rise{from{opacity:0;-webkit-transform:translateY(8px)}to{opacity:1;-webkit-transform:none}}
@keyframes soft-rise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}.panel{
  -webkit-animation:soft-rise .36s cubic-bezier(.22,1,.36,1) both;
  animation:soft-rise .36s cubic-bezier(.22,1,.36,1) both; border-color:var(--line-soft); border-radius:8px}
.kpi{
  -webkit-animation:soft-rise .36s cubic-bezier(.22,1,.36,1) both;
  animation:soft-rise .36s cubic-bezier(.22,1,.36,1) both; border-color:var(--line-soft); border-radius:8px}
.tb-scroll{
  -webkit-animation:soft-rise .36s cubic-bezier(.22,1,.36,1) both;
  animation:soft-rise .36s cubic-bezier(.22,1,.36,1) both;
}
.mlist{
  -webkit-animation:soft-rise .36s cubic-bezier(.22,1,.36,1) both;
  animation:soft-rise .36s cubic-bezier(.22,1,.36,1) both;
}
.ncard{
  -webkit-animation:soft-rise .36s cubic-bezier(.22,1,.36,1) both;
  animation:soft-rise .36s cubic-bezier(.22,1,.36,1) both; border-color:var(--line-soft); border-radius:8px; gap:8px; padding:10px 12px}
.rcard{
  -webkit-animation:soft-rise .36s cubic-bezier(.22,1,.36,1) both;
  animation:soft-rise .36s cubic-bezier(.22,1,.36,1) both; border-color:var(--line-soft); border-radius:8px}
.zcard{
  -webkit-animation:soft-rise .36s cubic-bezier(.22,1,.36,1) both;
  animation:soft-rise .36s cubic-bezier(.22,1,.36,1) both; border-color:var(--line-soft); border-radius:8px}
@media (prefers-reduced-motion: reduce){
  *{-webkit-animation:none !important;animation:none !important;transition:none !important}
}

/* ---------- 滚动条柔化 ---------- */
::-webkit-scrollbar-thumb{background:var(--line-strong);border-radius:999px;border:2px solid transparent;background-clip:content-box}
::-webkit-scrollbar-track{background:transparent}.mkpi-v{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum";
}
.mt-n{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum";
}
.nc-v{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum"; font-size:20px; font-weight:500; line-height:1.2}
.zc-v{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum"; font-size:20px; font-weight:500; line-height:1.2}
.rc-v{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum"; font-size:20px; font-weight:500; line-height:1.2}
.ds-big{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum"; gap:6px}
.kpi-value{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum"; font-size:34px; font-weight:700; line-height:1.05}
.pg-info{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum";
}
.tb td.num{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum";
}
.tb th.num{
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum";
}
.tb-sum td:not(:first-child){
  font-family:var(--ff-mono);
  font-variant-numeric:tabular-nums;
  -moz-font-feature-settings:"tnum";
  -webkit-font-feature-settings:"tnum";
}
.tb td.num,.tb th.num,.tb-sum td:not(:first-child){text-align:right}
/* 看板里的键值对：标签左、数值右，形成整齐的数值列起始线 */
.mkpi,.ncard .nc-v,.zcard .zc-v,.mfold .mt-n,.ds-sum{
  text-align:right;
  font-variant-numeric:tabular-nums;
}.ncard{display:flex;align-items:baseline;justify-content:space-between;gap:8px; border-color:var(--line-soft); border-radius:8px; padding:10px 12px}
.zcard{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-4); border-color:var(--line-soft); border-radius:8px}
.nc-k,.zc-k{flex:1 1 auto; font-size:15px; font-weight:600; line-height:1.35}
.nc-v,.zc-v{flex:none;text-align:right; font-size:20px; font-weight:500; line-height:1.2}
.mfold{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-4)}
.mt-l{flex:1 1 auto}
.mt-n{flex:none;text-align:right}.btn{
  border-radius:8px;
  font-family:var(--ff-ui);
  font-weight:500;
  letter-spacing:.1px;
  min-height:36px; font-size:15px; border:1px solid var(--line)}
.btn-ghost{
  border-radius:8px;
  font-family:var(--ff-ui);
  font-weight:500;
  letter-spacing:.01em;
  min-height:36px; border:1px solid transparent; border-color:transparent; font-size:12px; padding:6px 10px}
.btn.sm{
  border-radius:8px;
  font-family:var(--ff-ui);
  font-weight:500;
  letter-spacing:.01em;
  min-height:36px; font-size:12px; height:30px}
.btn.sub{
  border-radius:var(--r-sm);
  font-family:var(--ff-ui);
  font-weight:var(--fw-bold);
  letter-spacing:.01em;
  min-height:36px;
}
.login-btn{
  border-radius:var(--r-sm);
  font-family:var(--ff-ui);
  font-weight:var(--fw-bold);
  letter-spacing:.01em;
  min-height:36px;
}
.fbar-t{
  border-radius:var(--r-sm);
  font-family:var(--ff-ui);
  font-weight:var(--fw-bold);
  letter-spacing:.01em;
  min-height:36px;
}
.rbtn{
  border-radius:8px;
  font-family:var(--ff-ui);
  font-weight:500;
  letter-spacing:.01em;
  min-height:36px; font-size:15px; border:1px solid var(--line)}
.seg-b{
  border-radius:0;
  font-family:var(--ff-ui);
  font-weight:500;
  letter-spacing:.01em;
  min-height:36px; font-size:12px; border-right:1px solid var(--line-soft)}.btn-ghost{
  background:var(--surface);
  border:1px solid transparent;
  color:var(--t2);
  box-shadow:var(--sh-1); border-color:transparent; font-size:12px; font-weight:500; padding:6px 10px; border-radius:8px}
.btn.sub{
  background:var(--surface);
  border:1px solid var(--line-strong);
  color:var(--t2);
  box-shadow:var(--sh-1);
}
.btn:not(.primary):not(.danger):not(.ok){
  background:var(--surface);
  border:1px solid var(--line-strong);
  color:var(--t2);
  box-shadow:var(--sh-1);
}.btn-ghost:hover{
  background:var(--bg-hover);
  border-color:transparent;
  color:var(--brand-deep);
}
.btn.sub:hover{
  background:var(--bg-hover);
  border-color:var(--brand);
  color:var(--brand-deep);
}
.btn:not(.primary):not(.danger):not(.ok):hover{
  background:var(--bg-hover);
  border-color:var(--brand);
  color:var(--brand-deep);
}
.btn.primary{
  background:var(--brand);
  border:1px solid var(--brand-hi);
  color:var(--t-white);
  box-shadow:0 1px 2px rgba(13,135,120,.18), 0 4px 12px rgba(13,135,120,.16); border-color:transparent; border-radius:8px}
.btn.primary:hover{background:var(--brand-hi); border-color:transparent}
.btn.danger{background:var(--danger);border:1px solid var(--danger-text);color:var(--t-white); border-color:var(--line); border-radius:8px}
.btn:disabled{background:var(--bg-disabled);color:var(--t-disabled);border-color:var(--line);box-shadow:none}

/* ---- 3) 选中行：低饱和主色浅底（替换原来的高饱和琥珀） ---- */
.tb tbody tr.row-focus,.row-focus{
  background:var(--brand-soft);
}
.tb tbody tr.row-focus td{border-bottom-color:var(--line-ok)}
.warn-line{
  background:var(--warn-soft);
  border-left:3px solid var(--warn);
  border-radius:var(--r-sm);
  color:var(--warn-text);
}

/* ==========================================================================
   V37（2026-09-23）：手机端问候条（截图框选区）重新配色
   --------------------------------------------------------------------------
   症状：这一条被前面几层主题反复覆写，最终落在「深墨绿底 --brand-deep
     + 深色正文 --t1」—— 深绿上写深色字，对比度只有约 2.5:1，「中午好，XXX」
     基本读不出来；可头像圈和「导入」按钮又还是浅色卡片的配色，一条里两套语言。
     这正是截图里框出来的那一块。

   做法：整条并入「青瓷绿 + 暖石灰」的浅色卡片家族 ——
     · 底：极浅青瓷渐层（--hero-bg → --hero-bg2），与下方白卡同族但有身份；
     · 主文案：深青瓷 --hero-fg（约 6.8:1）；
     · 次文案：暖中性灰 --hero-fg2（约 6.6:1，比原来的 --t3 更可读）；
     · 头像圈：实心青瓷 + 白字，是整条唯一的重色锚点；
     · 「导入」按钮：白面 + 深青瓷字 + 发丝描边，与全站次要按钮同一套语言。
   颜色只走 --hero-* 令牌（浅色 / 深色各一份，已在 :root 与深色块里配好），
   与移动端断点下的其它卡片保持一致；本块只写在 @media(max-width:768px) 内，
   桌面端零改动。
   ========================================================================== */
@media (max-width:768px){
  .mhero{
    background:linear-gradient(135deg,var(--hero-bg) 0%,var(--hero-bg2) 78%);
    border:1px solid var(--hero-line);
    border-radius:var(--r-lg);
    box-shadow:var(--sh-1);
    color:var(--hero-fg);
  }
  .mh-av{
    background:var(--hero-av-bg);
    color:var(--hero-av-fg);
  }
  .mh-hi{color:var(--hero-fg); letter-spacing:var(--ls-wide)}
  .mh-sub{color:var(--hero-fg2); font-size:var(--fs-xs)}   /* 10px → 12px，与副文案档位一致 */
  .mh-btn{
    background:var(--hero-btn-bg);
    color:var(--hero-btn-fg);
    border:1px solid var(--hero-line);
  }
  .mh-btn:active{background:var(--hero-btn-bg2)}
}

/* ==========================================================================
   手机端排版与描边收口（2026-09-23 · 用户实拍反馈）
--------------------------------------------------------------------------
   用户看完手机端截图说「这块还是挺奇怪的」。逐条对着实测值定位，四个真问题：

   ① **层级倒置**：`.panel-h` 在手机上被后置的非 media 规则重置回 17px，
      与 app 标题 `.brand-txt b`（17px/600）完全同号同重 —— 模块标题和产品名
      平起平坐，页面没了主次。手机画布小，模块标题该比桌面再降一档。
   ② **数字↔标签贴在一起**：`.ds-big{gap:var(--sp-half)}` 实测只有 2px，
      数值和它的标签几乎连成一行，看不出分组。
   ③ **卡片内边距失衡**：`.ncard` 实测 padding 8px 10px，右侧数值列贴着文字。
   ④ **圆角/间距不统一**：`.panel` 在手机上走 `--r-lg`(12px)，与卡片/按钮的 8px
      并存；模块间距有的 8px 有的 20px，分层节奏乱。

   另修一处**上一轮引入的回归**：`--fs-16` 被收进 15px，但它是 iOS 防缩放
   专用档（Safari 聚焦 <16px 输入框会自动放大页面）——已在 :root 改回 16px。

   断点只用 768（selfcheck G0 允许集内）；不动任何 min-height/触控尺寸，
   V35 逐条实测出来的 44px 触控下限原样保留。
   ========================================================================== */
@media (max-width:768px){

  /* ① 模块标题降一档：17 → 15，与 app 标题拉开，页面才有主次 */
  .panel-h{
    font-size:15px; font-weight:600;
    padding:10px 12px; min-height:44px; gap:var(--sp-2);
    line-height:1.3;
  }
  /* 手机首屏问候条：姓名是主体，不该比模块标题还小 */
  .mh-hi{font-size:15px; font-weight:600; line-height:1.35}
  .mh-sub{margin-top:var(--sp-1); line-height:1.5; font-size:12px}

  /* ② 数字↔标签的呼吸：2px → 6px */
  .ds-big{gap:var(--sp-1h)}
  .ds-big b{font-size:20px; font-weight:500; line-height:1.15}
  .ds-big span{font-size:12px; font-weight:500; line-height:1.5}

  /* ③ 卡片内边距：8px 10px → 10px 12px，数值列不再贴边 */
  .ncard{padding:10px 12px; gap:var(--sp-2)}
  .zcard, .rcard{padding:10px 12px}

  /* ④ 圆角与模块节奏统一：全站 8px，模块间距 12px */
  .panel{border-radius:var(--r); margin-bottom:var(--sp-3); padding:0}
  .ncards, .rcards, .zcards{gap:var(--sp-3)}

  /* 登录页档案卡：标签 400 vs 数值 700 差了三档，视觉权重失衡（实拍走查 #3）。
     标签提到 500 与数值同重，靠亮度深浅分层级，不靠字重硬拉开。 */
  .login-meta span{font-weight:500}

  /* 手机折叠区里的指标标签被 .mf-b .ds-big span 用 --fs-2xs(11px) 压住，
     特异性高于上面的 .ds-big span —— 这里用同特异性、更靠后把它统一到 12px */
  .mf-b .ds-big span{font-size:12px; font-weight:500; line-height:1.5}
  .mf-b .ds-big b{font-size:20px; font-weight:500}

  /* 底部 Tab 图标尺寸显式统一（图标形状不同会显得大小不一） */
  .tabbar-item svg{width:22px; height:22px; flex:none}
  .tabbar-item{gap:var(--sp-pad-a)}
}

/* ==========================================================================
   A. 文字溢出收口（2026-09-23，用户实测反馈 + DOM 逐元素量测）
--------------------------------------------------------------------------
   用户报「文字超出容器边框」。用 getComputedStyle/scrollWidth 在 360/390/442/
   768/1024/1440 六档屏宽 × 三个页面逐元素实测，坐实了这几处：

     ① .kpi 卡片  —— scrollHeight 104 > clientHeight 88，overflow:hidden 直接
                    把内容切掉 16px；.kpi-body 还 spill 11px
     ② .mi-name / .mi-sub / .kpi-sub —— white-space:nowrap + ellipsis，
                    长姓名「阿卜杜热合曼·买买提江」溢出 70px 被省略号吃掉
     ③ 环形图中心 .dt 的百分比 —— 字号过大，顶到圆环进度条上
     ④ 图例行「已续约: 60 户」—— 右侧内边距≈0，字贴着容器边框
     ⑤ 数据条 .bar —— 溢出卡片圆角被裁
     ⑥ 1024px 下 table.tb.tb-keep 溢出容器 56px

   改法优先级（按用户要求）：先换行/断词 → 再调字号行高内边距 → 最后才省略。
   所以把「nowrap+省略号」一律换成「允许换行 + 最多 3 行兜底省略」。
   ========================================================================== */

/* ⑦ 断词兜底：长英文串 / 长编号 / 连续数字（如 WB-2026-0923-0000…）在
     nowrap 容器里会顶破边界。min-width:0 是必须的 —— flex/grid 子项默认
     min-width:auto，宁可溢出也不收缩。 */
.mi-name, .mi-sub, .mi-top, .kpi-sub, .kpi-label, .kpi-value, .nc-k, .nc-v,
.nc-h, .rc-s, .rc-s2, .rc-v, .det-v, .det-k, .legend, .tag, .tb td, .tb th,
.panel-h, .mh-hi, .mh-sub, .ph-sub, .empty, .dt b, .dt span, .today, .hint{
  overflow-wrap:break-word;
  word-break:break-word;
  min-width:0;
}

/* ② 取消 nowrap 截断：允许换行。极长时最多 3 行才省略（用户要求「不被裁切」，
     省略是最后手段）。-webkit-line-clamp 在 X5/微信内核可用，带前缀即合规。 */
.mi-name, .mi-sub, .kpi-sub, .kpi-label, .nc-k, .nc-h, .rc-s, .rc-s2,
.det-v, .legend, .mh-hi, .mh-sub, .today{
  white-space:normal;
  overflow-wrap:break-word;
  display:-webkit-box;
  -webkit-line-clamp:3;
  -webkit-box-orient:vertical;
  overflow:hidden;
  text-overflow:clip;
}

/* ① KPI 卡片不再纵向裁切：让内容把卡片撑高，而不是被 overflow:hidden 切掉 */
.kpi{height:auto; min-height:0; overflow:hidden}   /* overflow 留着给圆角收边 */
/* 真凶：.grid.mkpi .kpi 写死了 min-height:80px + max-height:88px，
   内容一多就被 overflow:hidden 切掉 16~23px（实测 scrollHeight 104~111）。 */
.grid.mkpi .kpi{max-height:none; height:auto}
.kpi-body{min-width:0; height:auto; overflow:visible}
.kpi-value{overflow-wrap:break-word}
.grid.g4.mkpi{grid-auto-rows:minmax(min-content, auto)}

/* ③ 环形图中心文字：内圆直径约 73px，文字安全区 68px —— 字号收到 20px，
     并给 8px 内缩，保证「100.0%」这种最长串也不压到圆环上。 */
.dt{padding:0 10px; text-align:center}
.dt b{font-size:20px; line-height:1.1; letter-spacing:-.3px; max-width:100%}
.dt span{font-size:11px; line-height:1.4; margin-top:2px}

/* ④ 图例行：右侧留出呼吸空间，不再贴边 */
.legend{padding:2px 8px 2px 0; line-height:1.6}
.donut-wrap{padding-right:var(--sp-3); padding-left:var(--sp-3)}

/* ⑤ 数据条：不许超出卡片可视区 */
.bar{max-width:100%; min-width:0}
.bar-row, .bl{min-width:0; overflow:hidden}

/* ⑥ 表格在中窄屏允许换行（桌面宽屏仍保持紧凑），确保文字完整显示 */
.tb td, .tb th{white-space:normal; overflow-wrap:break-word}
.tb td.num, .tb th.num{white-space:nowrap}   /* 数字列保持对齐不换行 */

/* 顶栏：窄屏下三段内容（品牌 / 搜索 / 头像）总宽超出 360px 会被挤成多行，
   而顶栏高度是写死的 —— 多出来的那行直接顶出边框、盖到下面内容上。
   改法：高度自适应 + 三段都可收缩（flex 子项默认 min-width:auto 宁可溢出
   也不收缩，必须显式给 min-width:0）。 */
.topbar{height:auto; min-height:0; overflow:visible}
.topbar .brand, .topbar .topbar-mid, .topbar .topbar-right{min-width:0}
.topbar-mid{flex:1 1 auto; min-width:0}
.topbar .brand-txt b{overflow-wrap:break-word}
@media (max-width:768px){
  .topbar{height:auto; min-height:52px}
}

/* ==========================================================================
/* ⑧ 手机端折叠区（details.mfold）：display:flex 会破坏 <details> 的原生折叠
     —— <summary> 和内容被并排塞进一行，内容区被压到只剩内边距（实测 .mf-b
     24px 宽 = 纯 12px×2 内边距，里面的卡片全部塌成一字一行）。
     改回 block / flex-direction:column，让 summary 与内容上下排，折叠才正常。 */
details.mfold{display:block; overflow:visible}
details.mfold > summary{
  display:flex; align-items:center; justify-content:space-between;
  gap:var(--sp-2); cursor:pointer; list-style:none; min-width:0;
}
details.mfold > summary::-webkit-details-marker{display:none}
details.mfold > summary > *{min-width:0}
details.mfold > .mf-b{min-width:0}

/* ⑨ 指标行（.nc-f = 标签 + 数值）：.nc-v 是 flex:none，一占就把 .nc-k 挤到
     只剩 5px 宽 —— 标签变成一字一行还被裁掉（实测 360px 下 .nc-k 5x61）。
     改法：行内可换行（挤不下就上下叠），标签给最小宽度，数值改为可收缩；
     网格列宽下限从 0 提到 110px，列永远窄不过一个能用的宽度。 */
.nc-f{flex-wrap:wrap; gap:2px var(--sp-2); min-width:0}
.nc-f .nc-k{flex:1 1 56px; min-width:56px}
.nc-f .nc-v{flex:0 1 auto; min-width:0; overflow-wrap:break-word}
.nc-g{grid-template-columns:repeat(auto-fit, minmax(110px, 1fr)); min-width:0}
.nc-g > *{min-width:0}
/* ⑩ 容器收口：子项的下外边距会把 scrollHeight 顶高 8px（文字并未被裁，
     但看上去像出框）。给容器补回这点高度差，边界就干净了。 */
.rcards, .ncards, .zcards{padding-bottom:var(--sp-2)}

/* ⑪ 密集数值行的呼吸感（视觉走查最后一条：数值挤在一起、辨识度差）。
     只调间距与标签可见性，不动字号与布局结构。 */
.ds-sum{gap:var(--sp-3) var(--sp-4)}
.ds-big{gap:var(--sp-1); padding:2px 0}
.nc-g{gap:var(--sp-2) var(--sp-3)}
.nc-f{gap:2px var(--sp-2); padding:2px 0}
