/* ══════════════════════════════════════════════════════════════
   NPFin.AI 薄版 · 全局样式（登录 / 经典 / Agent 三态共用）

   ── 2026-08-16 定版：设计方向「靛蓝 Azulou」 ────────────────────
   参照 Dribbble 的 Azulou ERP Dashboard（Raquel Guerra）。用户在三个
   候选方向里选定这一路，并要求全站视觉统一。它和上一版「双拼 Duotone」
   最根本的分歧是**主角区的做法**：

     旧：浅色工作区 + 每页一块深漆面页眉，靠明暗反差立主角。
     新：整屏统一在一层冷调靛蓝雾底上，主角靠**色相**和**面积**立 ——
         页眉块是一张浅靛蓝的软卡，不是一块黑漆板。

   为什么换掉深漆面：一屏里同时存在深板、白卡、雾底三种明度，块与块之间
   的关系要靠明度差去猜；而深板一旦装了图表，图表就得单独备一套深色调色，
   同一根「毛利率」曲线在总览页和毛利页是两个颜色。统一到一层底色之后，
   所有图表只剩一套颜色，读者在页与页之间不需要重新适应。

   这一版的四条形制（都能在 Azulou 那张稿子上指出来）：
   · **雾底 + 白卡**。底 #eef0fa 是带蓝的冷雾，不是灰。白卡浮在上面，
     靠柔阴影分层，边框退成极淡的一道（原来靠 hairline 划界，现在靠影）。
   · **大圆角**。面板 18px、控件 12px、药丸全圆。Azulou 的"互联网感"
     有一半来自这个 —— 但表格不跟着圆，账表的行还是直的。
   · **靛蓝当主色**。#4353d9 比原来的群青 #3a4fb8 更亮更饱和，用在可
     交互、主数据序列、当前态。紫 #6d5bd0 做第二序列。
   · **软色底块**。强调不用深色而用同色系的浅底（--brand-soft 一类），
     这样强调块和普通白卡在明度上仍是一档，页面不会被"劈开"。

   刻意**没有**抄 Azulou 的：它右侧那条常驻助手栏。那是布局改动，本轮
   范围限定在视觉统一（用户明确选的是"全站视觉统一"而不是"视觉+布局
   都重排"），Agent 仍是独立一态。

   继承自上一版、这次一个字没动的纪律：
   · 立邦红只出现在标识与当前导航项竖条两处，绝不与「跌」的红混用；
     红绿在本系统只表示涨跌，不拿去做装饰或状态底色。
   · KPI 是各自独立的卡 + gap，不接成一条（连一条会暗示不存在的关系）；
     每张卡底压一行口径（期间 · 范围），口径写在数字旁边。
   · 涨跌走浅底药丸并固定纵排。
   · 所有数值 tabular-nums 走等宽；口径区永远 overflow:visible、无
     max-height、不可折叠。
   · 无构建 / 无 CDN / 无外部字体是硬约束，中文回落 PingFang。
   ══════════════════════════════════════════════════════════════ */
:root{
  /* 结构性 token */
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:20px; --sp-6:24px; --sp-8:32px;
  /* 圆角比上一版整体大一档：md 14→18、sm 8→12、xs 6→8 */
  --r-xs:8px; --r-sm:12px; --r-md:18px; --r-lg:22px; --r-pill:999px;
  --dur-fast:140ms; --dur-base:220ms; --ease:cubic-bezier(.22,1,.36,1);
  --mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,"Liberation Mono",monospace;

  /* 冷雾工作区。底色带蓝（不是中性灰）—— 白卡放上去才有"浮"的感觉，
     同时整屏在色相上先统一一次，主角区就不必再靠明暗去抢。 */
  --bg:#eef0fa; --bg-2:#e2e6f6; --panel:#fff; --panel-2:#f7f8fd;
  --ink:#141a2e; --ink2:#565f7d; --ink3:#8b93ad;
  --line:#e8ebf7; --line-2:#d5dbf0;

  /* 页眉软卡（原深漆面）。token 名沿用 --dk-* 不改：classic.js 里有
     内联的 var(--dk-ink3)，重命名要同步改 JS，收益为零。语义已经从
     "dark 深色态"变成"页眉块专用的一档"，值全部重挂到浅靛蓝上。 */
  --dk-1:#e9edfd; --dk-2:#e1e7fb;
  --dk-ink:#141a2e; --dk-ink2:#525b79; --dk-ink3:#7d86a3;
  --dk-line:rgba(67,83,217,.14); --dk-line2:rgba(67,83,217,.24);
  --dk-acc:#4353d9; --dk-bad:#d1483a;

  /* 立邦红：只用于标识与当前项竖条，不参与数据语义 */
  --np-red:#d42a20;

  /* 靛蓝：可交互 / 主数据序列 */
  --brand:#4353d9; --brand-hover:#3644bd; --brand-soft:#eef0ff; --brand-border:#c5cdfa;

  /* 有含义的颜色（在冷底上重新配过：暖绿暖红压在蓝雾上会发脏） */
  --good:#12866a; --bad:#d1483a; --warn:#94661a;
  --warn-soft:#fdf4e3; --warn-line:#ecd9b0;
  --deny-line:#f2c9c1; --deny-soft:#fdf1ef;
  --good-soft:#e8f5f0; --good-line:#b8ded1;

  /* 颜料组（图表 / 色签；红绿留给涨跌） */
  --pg-ultra:#4353d9; --pg-ochre:#b5761a; --pg-slate:#5b6789;
  --pg-mauve:#6d5bd0; --pg-virid:#12866a; --pg-ink:#141a2e;

  --grad-brand:var(--np-red);
  /* 阴影带蓝 rgba(28,38,90,…)：冷底上配中性灰阴影会发灰发脏，
     和暖底必须配暖阴影是同一个道理。这一版分层主要靠影，不靠边框。 */
  --shadow-sm:0 1px 2px rgba(28,38,90,.05),0 2px 8px rgba(28,38,90,.045);
  --shadow-md:0 4px 12px rgba(28,38,90,.08),0 18px 40px rgba(28,38,90,.12);
  --panel-bg:#fff;
}
*{box-sizing:border-box}
/* overflow-x:hidden 会让 body 变成滚动容器、position:sticky 全部失效（实测）；
   clip 只裁剪不滚动，横向防溢出与 sticky 顶栏两者兼得 */
html,body{max-width:100%;overflow-x:clip}
body{margin:0;font:13.5px/1.7 -apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;
     background:var(--bg);color:var(--ink);-webkit-font-smoothing:antialiased}
button,input,select,textarea{font-family:inherit}
.tnum{font-variant-numeric:tabular-nums;font-family:var(--mono)}
svg{display:block;max-width:100%}
.view[hidden]{display:none!important}
:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:3px}

/* ── 数据来源标识（原来是压在头顶的红条幅，现在收成头部一枚小 chip） ──
   为什么改：横幅每屏都在喊，喊到第三天就没人读了，只剩「这系统看着像个半成品」
   这一个效果。标识真正该在的地方是数字离开系统的出口 —— Excel 导出首行的警示
   与尾部口径声明一行没动。屏幕上留一枚可 hover 看详情的 chip 就够。 */
.srcchip{display:inline-flex;align-items:center;gap:6px;flex:none;font-size:11px;color:var(--ink3);
         border:1px solid var(--line);border-radius:var(--r-pill);padding:4px 10px;background:var(--panel-2);
         white-space:nowrap;cursor:default;letter-spacing:.02em}
.srcchip .dotm{width:5px;height:5px;border-radius:50%;background:var(--ink3);flex:none}
.srcchip.syn{color:var(--warn);border-color:var(--warn-line);background:var(--warn-soft)}
.srcchip.syn .dotm{background:var(--warn)}
.srcchip.live{color:var(--good);border-color:var(--good-line);background:var(--good-soft)}
.srcchip.live .dotm{background:var(--good)}

/* ── 业务线开关（页眉） ──────────────────────────────────────
   与身份 chip 一样是**全局状态**，不是页面筛选器，所以长在页眉而不是
   工作区里。色签用紫棠：与导航「平台图谱」那组的紫同源，读者已经把这个
   颜色和「谁能看什么」联系在一起了。
   只有一条线授权时是 .solo：不给下拉箭头 —— 一个只有一个选项的下拉框
   是在假装他有得选。 */
.buchip{display:inline-flex;align-items:center;gap:7px;flex:none;font-size:11.5px;
        color:var(--ink2);border:1px solid var(--line-2);border-radius:var(--r-pill);
        padding:3px 10px 3px 9px;background:var(--panel);white-space:nowrap}
.buchip i{width:7px;height:7px;border-radius:2px;background:var(--pg-mauve);flex:none}
.buchip.solo{color:var(--ink2);background:var(--panel-2);padding:4px 11px 4px 10px;
             letter-spacing:.02em;cursor:default}
.buchip select{font-size:11.5px;font-weight:600;color:var(--ink);border:0;background:transparent;
               padding:2px 2px 2px 0;cursor:pointer;max-width:150px}
.buchip select:focus{outline:2px solid var(--brand-border);outline-offset:2px;border-radius:4px}

/* ══ 登录页 ══════════════════════════════════════════════════
   跟着全站一起从深色翻到靛蓝雾底。左侧介绍区铺一层比工作区更饱和的
   靛蓝渐变（登录页是全系统唯一可以用大面积色的地方 —— 它不承载数字，
   不存在"色底干扰读数"的问题），右侧登录卡是一张纯白软卡。
   进系统之后底色降到 --bg 那层淡雾，明度是连续的，不会"啪"地一亮。 */
.lg{min-height:100vh;display:grid;grid-template-columns:1.05fr .95fr;
    background:radial-gradient(1150px 720px at 4% -14%,#c9d3fb 0%,rgba(201,211,251,0) 60%),
               radial-gradient(880px 600px at 34% 108%,#d3c9f7 0%,rgba(211,201,247,0) 56%),
               radial-gradient(900px 620px at 99% 10%,#dfe6fd 0%,rgba(223,230,253,0) 52%),
               var(--bg);color:var(--ink)}
.lg-brand{padding:64px 56px;display:flex;flex-direction:column;justify-content:center;gap:26px;max-width:640px;margin-left:auto}
.lg-logo{display:flex;align-items:center;gap:12px}
.lg-logo .mark{width:42px;height:42px;border-radius:12px;background:var(--np-red);display:grid;place-items:center;
               color:#fff;font-weight:700;font-size:16px;letter-spacing:.02em;
               box-shadow:0 4px 12px rgba(212,42,32,.26)}
.lg-logo .nm{font-size:18px;font-weight:650;letter-spacing:.02em}
.lg-logo .nm small{display:block;font-size:11px;font-weight:400;color:var(--ink3);letter-spacing:.12em;margin-top:2px}
.lg h1{font-size:32px;line-height:1.4;margin:0;font-weight:700;letter-spacing:-.01em}
.lg h1 .acc{color:var(--brand)}
.lg .lead{font-size:13.5px;color:var(--ink2);line-height:1.95;margin:0}
.lg-pillars{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:6px}
/* 四张要点卡：半透明白面，让底下那层渐变透一点上来 —— 全实白会把
   左半边切成四个孤立的方块，透一点它们才像浮在同一片底上 */
.lg-p{border:1px solid rgba(255,255,255,.9);border-radius:var(--r-sm);padding:14px 16px;
      background:rgba(255,255,255,.55);box-shadow:0 2px 10px rgba(28,38,90,.05)}
.lg-p .t{font-weight:600;font-size:13px;display:flex;gap:9px;align-items:center}
.lg-p .t .ic{width:18px;height:18px;border-radius:5px;background:var(--brand-soft);display:grid;place-items:center;
             font-size:11px;color:var(--brand)}
.lg-p .d{font-size:11.5px;color:var(--ink2);margin-top:6px;line-height:1.75}
.lg-form{display:flex;align-items:center;justify-content:flex-start;padding:64px 56px}
.lg-card{width:100%;max-width:400px;border-radius:var(--r-md);padding:30px 28px 24px;
         background:var(--panel);border:1px solid var(--line);box-shadow:var(--shadow-md)}
.lg-card h2{margin:0 0 4px;font-size:18px;font-weight:650}
.lg-card .sub{font-size:12px;color:var(--ink3);margin-bottom:22px}
.lg-field{margin-bottom:14px}
.lg-field label{display:block;font-size:11px;color:var(--ink3);margin-bottom:7px;letter-spacing:.06em}
.lg-field select,.lg-field input{width:100%;height:44px;border-radius:var(--r-sm);border:1px solid var(--line-2);
    background:var(--panel-2);color:var(--ink);padding:0 13px;font-size:13.5px;outline:none;
    transition:border-color var(--dur-fast),box-shadow var(--dur-fast),background var(--dur-fast)}
.lg-field select:focus,.lg-field input:focus{border-color:var(--brand);background:var(--panel);
    box-shadow:0 0 0 3px rgba(67,83,217,.14)}
.lg-scope{font-size:11px;color:var(--ink3);margin-top:7px;line-height:1.7;min-height:18px}
.lg-err{font-size:12.5px;color:var(--bad);background:var(--deny-soft);border:1px solid var(--deny-line);
        border-radius:var(--r-xs);padding:8px 11px;margin-bottom:12px;display:none}
.lg-err.on{display:block}
/* 提交键是全站唯一一处大面积立邦红：它是"进入立邦系统"这个动作本身，
   属于标识范畴，不是数据语义。红绿的涨跌含义不受影响。 */
.lg-submit{width:100%;height:46px;border:0;border-radius:var(--r-sm);cursor:pointer;font-size:14px;font-weight:650;
           color:#fff;background:var(--np-red);box-shadow:0 4px 14px rgba(212,42,32,.28);
           transition:filter var(--dur-fast),box-shadow var(--dur-fast)}
.lg-submit:hover:not(:disabled){filter:brightness(1.06);box-shadow:0 6px 18px rgba(212,42,32,.34)}
.lg-submit:disabled{opacity:.55;cursor:wait;box-shadow:none}
.lg-demo{margin-top:20px;padding-top:16px;border-top:1px solid var(--line);font-size:11px;
         color:var(--ink3);line-height:1.95}
.lg-demo code{background:var(--brand-soft);padding:1px 6px;border-radius:5px;
              font-family:var(--mono);font-size:10.5px;color:var(--brand)}
.lg-authnote{margin-top:10px;font-size:11px;color:var(--warn);line-height:1.75}
@media(max-width:920px){
  .lg{grid-template-columns:1fr}
  .lg-brand{padding:40px 24px 8px;max-width:none;margin:0}
  .lg h1{font-size:24px}
  .lg-pillars{grid-template-columns:1fr}
  .lg-form{padding:24px 24px 48px;justify-content:center}
}

/* ══ 经典模式外壳 ═══════════════════════════════════════════
   浅色工作区 + 白色导航轨。轨不做深色：财务是长时间左右扫视，
   高对比竖条在余光里一直「跳」，一天下来累。当前项改用浅色底抬起来
   + 立邦红竖条标位置。 */
.cl{display:grid;grid-template-columns:230px minmax(0,1fr);min-height:100vh}
.cl-side{background:var(--panel);border-right:1px solid var(--line);padding:18px 12px 20px;
         display:flex;flex-direction:column;gap:1px;position:sticky;top:0;align-self:start;
         max-height:100vh;overflow-y:auto}
.cl-brand{display:flex;gap:11px;align-items:center;padding:2px 8px 20px}
.cl-brand .mark{width:30px;height:30px;border-radius:8px;color:#fff;display:grid;place-items:center;
                font-weight:700;font-size:12px;flex:none;letter-spacing:.03em;
                background:linear-gradient(160deg,#e8453a,var(--np-red));
                box-shadow:0 3px 10px rgba(212,42,32,.28)}
.cl-brand .nm{font-weight:650;font-size:13.5px;line-height:1.25}
.cl-brand .nm small{display:block;font-weight:400;font-size:9.5px;color:var(--ink3);letter-spacing:.16em;margin-top:3px}
.cl-sec{font-size:9.5px;color:var(--ink3);padding:16px 10px 7px;letter-spacing:.18em}
/* 导航项：颜料色签替代 emoji —— 色卡的索引语汇，不靠图标撑场面 */
.cl-item{display:flex;align-items:center;gap:10px;border:0;background:transparent;width:100%;text-align:left;
         padding:8px 10px;border-radius:var(--r-xs);font-size:12.5px;color:var(--ink2);cursor:pointer;
         position:relative;transition:background var(--dur-fast),color var(--dur-fast)}
.cl-item .ic{width:9px;height:9px;border-radius:2px;flex:none;font-size:0;line-height:0;
             background:var(--pg,var(--ink3));opacity:.85;box-shadow:0 0 0 1px rgba(255,255,255,.7)}
.cl-item:hover{background:var(--panel-2);color:var(--ink)}
.cl-item:hover .ic,.cl-item.on .ic{opacity:1}
/* 当前项：靛蓝软底药丸 + 立邦红竖条。红条是上一版就定下的规矩（标识色
   标位置），软底是这一版新加的 —— Azulou 的当前态是一整枚有色药丸，
   光靠一根 3px 的竖条在浅底上撑不起"我在这儿"。 */
.cl-item.on{background:var(--brand-soft);color:var(--brand);font-weight:650}
.cl-item.on::before{content:'';position:absolute;left:-12px;top:6px;bottom:6px;width:3px;
                    background:var(--np-red);border-radius:0 3px 3px 0}
.cl-foot{margin-top:auto;padding:16px 10px 0;font-size:10px;color:var(--ink3);line-height:1.9;
         border-top:1px solid var(--line)}

.cl-main{min-width:0;display:flex;flex-direction:column;background:var(--bg)}
.cl-head{height:54px;background:var(--panel);border-bottom:1px solid var(--line);
         display:flex;align-items:center;gap:9px;padding:0 24px;position:sticky;top:0;z-index:30;
         box-shadow:0 1px 3px rgba(28,38,90,.05)}
.cl-crumb{font-size:11.5px;color:var(--ink3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;letter-spacing:.03em}
.cl-crumb b{color:var(--ink2);font-weight:600}
.spacer{margin-left:auto}
.mode-seg{display:flex;border:1px solid var(--line-2);border-radius:var(--r-pill);padding:2px;background:var(--panel-2);flex:none}
.mode-seg button{border:0;border-radius:var(--r-pill);padding:4px 13px;font-size:12px;cursor:pointer;
                 background:transparent;color:var(--ink3);display:flex;align-items:center;gap:6px}
.mode-seg button:hover{color:var(--ink)}
.mode-seg button.on{background:var(--brand);color:#fff;font-weight:600;cursor:default;
                    box-shadow:0 2px 8px rgba(67,83,217,.30)}
.mode-seg button.on .dot{background:#fff}
.mode-seg .dot{width:5px;height:5px;border-radius:50%;background:var(--brand);flex:none}
.modetog{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--ink3);flex:none;
         border:1px solid var(--line-2);border-radius:var(--r-pill);padding:4px 10px;cursor:pointer;
         background:var(--panel)}
.modetog:hover{color:var(--ink)}
.modetog .dotm{width:5px;height:5px;border-radius:50%;background:var(--warn)}
.modetog.live .dotm{background:var(--good)}
.uchip{display:flex;align-items:center;gap:9px;border:1px solid var(--line-2);background:#fff;
       border-radius:var(--r-pill);padding:3px 12px 3px 3px;cursor:pointer;font-size:12px;color:var(--ink2);
       flex:none;position:relative}
.uchip:hover{border-color:var(--ink3)}
.uchip .av{width:26px;height:26px;border-radius:50%;color:#fff;display:grid;place-items:center;
           font-size:11px;font-weight:650;background:linear-gradient(160deg,#6a78e8,var(--brand));
           box-shadow:inset 0 1px 0 rgba(255,255,255,.35)}
.uchip .scope{font-size:10px;color:var(--ink3);letter-spacing:.02em}
.umenu{position:absolute;top:calc(100% + 8px);right:0;background:#fff;border:1px solid var(--line);
       border-radius:var(--r-sm);box-shadow:var(--shadow-md);min-width:250px;padding:6px;display:none;z-index:60}
.umenu.on{display:block}
.umenu .mi{display:block;width:100%;text-align:left;border:0;background:transparent;padding:9px 11px;
           border-radius:var(--r-xs);font-size:13px;color:var(--ink2);cursor:pointer}
.umenu .mi:hover{background:var(--panel-2);color:var(--ink)}
.umenu .sep{height:1px;background:var(--line);margin:5px 4px}
.umenu .note{font-size:10.5px;color:var(--ink3);padding:7px 11px;line-height:1.75;border-top:0;margin-top:0}
.umenu .note b{color:var(--warn);font-weight:600}

.cl-body{padding:22px 24px 60px;max-width:1360px;width:100%;margin:0 auto}

/* ══ 签名件：靛蓝页眉软卡 ═══════════════════════════════════
   每页一块。总览页里它装主指标 + 趋势图（.cl-title.hero），其余页只装
   标题、说明与筛选，压成一条 —— 一页一个主角，不多不少。

   2026-08-16：从深漆面翻成浅靛蓝软卡。主角地位现在靠**色相**给 ——
   整页只有这一块是有色的，其余全是白卡压在雾底上，一眼就知道看哪。
   附带解决的老问题：块里的图表不必再单独备一套深色调色，全站图表
   回到同一套颜色。左上角那道 3px 靛蓝竖条是"本页主角"的标记。 */
.cl-title{display:flex;align-items:flex-end;gap:14px;flex-wrap:wrap;margin:0 0 16px;
          background:linear-gradient(150deg,var(--dk-1),var(--dk-2));
          border:1px solid var(--dk-line2);border-radius:var(--r-md);padding:18px 22px;
          position:relative;overflow:hidden;
          box-shadow:0 2px 10px rgba(28,38,90,.06),0 14px 34px rgba(28,38,90,.08)}
.cl-title::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--brand)}
.cl-title h2{font-size:23px;margin:0;font-weight:650;letter-spacing:-.025em;color:var(--dk-ink)}
.cl-title .sub{font-size:11.5px;color:var(--dk-ink2);line-height:1.65;padding-bottom:3px}
.cl-title .spacer{margin-left:auto}
/* 页眉软卡里的控件：底色已经是浅靛蓝了，普通 chip 那套 --brand-soft
   压上去几乎看不出边界，所以这里的已选态改用**实白面**抬起来，
   未选态退成半透明白。明暗关系与浅底工作区正好互为反转。 */
.cl-title .filters .fl,
.cl-title .filters select{background:var(--panel);border-color:var(--brand-border);color:var(--brand)}
.cl-title .filters .fl{color:var(--ink2)}
.cl-title .filters select:has(option[value=""]:checked){background:rgba(255,255,255,.45);
                                                        border-color:var(--dk-line2);color:var(--dk-ink3)}
.cl-title .filters .fl:has(+ select option[value=""]:checked){background:rgba(255,255,255,.45);
                                                              border-color:var(--dk-line2);color:var(--dk-ink3)}
.cl-title .filters select:hover{border-color:var(--brand)}
.cl-title .filters .fl:has(+ select:hover){border-color:var(--brand)}
.cl-title .fclear{color:var(--dk-ink3)}
.cl-title .fclear:hover{color:var(--dk-bad)}
.cl-title .chip{background:rgba(255,255,255,.7);border-color:var(--dk-line2);color:var(--ink2)}
.cl-title .chip:hover{background:var(--panel);color:var(--brand);border-color:var(--brand-border)}
.cl-title .unitseg{border-color:var(--dk-line2);background:rgba(255,255,255,.55)}
.cl-title .unitseg button{background:transparent;color:var(--dk-ink2)}
.cl-title .unitseg button.on{background:var(--brand);color:#fff;font-weight:650}

/* 总览页的完整主角区 */
.cl-title.hero{display:grid;grid-template-columns:330px minmax(0,1fr);gap:0;padding:0;align-items:stretch}
.cl-title.hero .hero-lf{padding:20px 24px 22px;border-right:1px solid var(--dk-line);
                        display:flex;flex-direction:column;min-width:0}
.cl-title.hero .hero-rt{padding:14px 20px 6px;min-width:0}
.cl-title.hero h2{font-size:21px}
.hero-eb{font-size:10px;letter-spacing:.2em;color:var(--dk-acc);font-weight:600;margin-top:14px}
.hero-big{font-size:66px;line-height:.92;font-weight:600;margin-top:10px;letter-spacing:-.05em;
          font-family:var(--mono);font-variant-numeric:tabular-nums;color:var(--dk-ink);word-break:break-all}
.hero-big small{font-size:22px;letter-spacing:0;font-family:inherit;color:var(--dk-ink3);
                margin-left:4px;font-weight:500}
.hero-nm{font-size:12px;color:var(--dk-ink2);margin-top:11px}
.hero-dl{display:flex;gap:20px;margin-top:12px;padding-top:12px;border-top:1px solid var(--dk-line);flex-wrap:wrap}
.hero-dl div{font-size:10px;color:var(--dk-ink3);letter-spacing:.08em}
.hero-dl b{display:block;font-size:15px;font-weight:650;margin-top:3px;font-family:var(--mono);letter-spacing:-.02em}
/* 翻到浅底之后涨跌回到全站那一对 --good/--bad：深底上要提亮的浅绿
   （原 #4fbf8b）压在浅靛蓝上会糊，而且它和报表里其余的绿不是一个色 */
.hero-dl b.up{color:var(--good)}.hero-dl b.down{color:var(--bad)}.hero-dl b.flat{color:var(--dk-ink2)}
.hero-vd{margin-top:auto;padding-top:14px;font-size:11px;color:var(--dk-ink2);line-height:1.8}
.hero-vd em{font-style:normal;color:var(--dk-bad);font-weight:650}
@media(max-width:1000px){
  .cl-title.hero{grid-template-columns:1fr}
  .cl-title.hero .hero-lf{border-right:0;border-bottom:1px solid var(--dk-line)}
}

/* ── 筛选 chip ────────────────────────────────────────────────
   原来是「灰标签 + 一个下拉」重复四遍，扫一眼只看得到四个一样的方框，
   看不出哪个筛了、筛的是什么。照 Data Table SaaS 那张改成药丸：
   标签与取值合成一枚 chip，**选了的点亮、没选的静音**，一排扫过去
   立刻知道当前口径。

   为什么不换成自定义下拉：原生 select 自带键盘、搜索首字母、移动端
   转轮，换成 div 全要自己重写还容易漏无障碍。所以只换外观 ——
   `.fl` 和 `select` 是相邻兄弟，用负 margin 抵掉 flex 的 gap 拼成一枚
   连续药丸，中间那道边去掉。

   已选/未选靠 :has() 判：带空选项（「全部渠道」）且它正被选中 = 没筛。
   不支持 :has() 的浏览器全部落到「已选」样式，只是少一层强调，不坏。 */
.filters{display:flex;gap:7px;flex-wrap:wrap;align-items:center}
.filters select{font-size:12px;padding:5px 22px 5px 8px;border:1px solid var(--line-2);
                border-left:0;border-radius:0 var(--r-pill) var(--r-pill) 0;
                background:var(--brand-soft);color:var(--ink);cursor:pointer;font-weight:600}
.filters .fl{font-size:10.5px;color:var(--ink2);letter-spacing:.08em;margin-right:-7px;
             border:1px solid var(--line-2);border-right:0;border-radius:var(--r-pill) 0 0 var(--r-pill);
             padding:5px 5px 5px 11px;background:var(--brand-soft);line-height:1.35}
.filters .fl,.filters select{border-color:var(--brand-border)}
/* 未筛：整枚 chip 静音 */
.filters select:has(option[value=""]:checked){background:var(--panel);color:var(--ink3);
                                              font-weight:400;border-color:var(--line-2)}
.filters .fl:has(+ select option[value=""]:checked){background:var(--panel);color:var(--ink3);
                                                    border-color:var(--line-2)}
.filters select:hover{border-color:var(--ink3)}
.filters .fl:has(+ select:hover){border-color:var(--ink3)}
/* 一键清空：只有当前页确实筛了东西才出现 */
.fclear{font-size:11px;color:var(--ink3);border:0;background:none;cursor:pointer;
        padding:5px 6px;text-decoration:underline;text-underline-offset:3px}
.fclear:hover{color:var(--bad)}
.fclear[hidden]{display:none}

/* 面板：白面 + 大圆角 + 柔阴影。边框退到极淡的一道，分层主要交给影 ——
   雾底上白卡本身就有明度差，再画一圈实边就成了"贴纸"。 */
.panel{background:var(--panel-bg);border:1px solid var(--line);border-radius:var(--r-md);
       box-shadow:var(--shadow-sm);padding:20px 22px;margin-bottom:16px}
.panel h3{margin:0 0 15px;padding-bottom:11px;border-bottom:1px solid var(--line);
          font-size:13px;font-weight:650;display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.panel h3 .hint{font-size:10.5px;color:var(--ink3);font-weight:400;letter-spacing:0}
/* 图表按 viewBox 等比放大，面板一宽图就被拉成一片空旷；给个上限并居中 */
.panel svg{width:100%;max-width:1000px;margin:2px auto 0}
/* minmax(0,1fr) 不是洁癖：1fr 的下限是轨道内容的 min-content，而一张十列的
   宽表 min-content 就是它自己的全宽（.tblwrap 的 overflow 只让它自己滚，
   不缩它对父级的最小宽度贡献）。实测 1024 下总览两栏被撑到 1088，整个
   .cl-main 跟着横向溢出 —— 与 .cl / .kgrid 用的是同一条写法。 */
.grid2{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:16px}
@media(max-width:900px){.grid2{grid-template-columns:minmax(0,1fr)}}

/* ══ 交互图层（chart.js）══════════════════════════════════════
   原来的图是一段拉伸的 SVG 字符串，鼠标放上去只有浏览器原生气泡。
   这里给它补上一套 BI 该有的读法：十字游标 / 读数卡 / 色卡图例 / 点期下钻。

   读数卡为什么钉住不飘：跟随指针的气泡永远压在正在读的那根柱上，
   而且每动一下整块要重排。钉在绘图区角上、过中线翻边，读数稳、指针净。
   卡片排版照立邦自己的色卡 —— 一行一枚实色小方块 + 序列名 + 右对齐数值，
   不用虚线小图标去暗示线型（那种图标在 11px 上根本分不出实线虚线）。 */
.npc{position:relative;margin:2px 0 0}
.npc-plot{position:relative;width:100%;cursor:crosshair;border-radius:var(--r-xs)}
.npc.pick .npc-plot{cursor:pointer}
.npc-plot:focus-visible{outline:2px solid var(--brand);outline-offset:3px}
.npc-plot svg{width:100%;max-width:none;margin:0;display:block}
.npc-bar,.npc-step{transition:opacity var(--dur-fast) var(--ease)}
.npc-plot:hover .npc-bar{opacity:.82}

/* 读数卡 */
.npc-read{position:absolute;top:8px;z-index:3;min-width:154px;max-width:min(300px,62%);
          background:var(--panel);border:1px solid var(--line-2);border-radius:var(--r-sm);
          box-shadow:var(--shadow-md);padding:8px 10px 7px;pointer-events:none;
          animation:npcIn var(--dur-fast) var(--ease)}
@keyframes npcIn{from{opacity:0;transform:translateY(-3px)}to{opacity:1;transform:none}}
.npc-read[hidden]{display:none}
.npc-read .pd{font-family:var(--mono);font-size:10.5px;letter-spacing:.08em;color:var(--ink3);
              padding-bottom:6px;margin-bottom:6px;border-bottom:1px solid var(--line)}
.npc-read .rw{display:flex;align-items:center;gap:7px;font-size:11.5px;line-height:1.9;white-space:nowrap}
.npc-read .rw i{width:9px;height:9px;border-radius:2px;flex:none}
.npc-read .rw .nm{color:var(--ink2);overflow:hidden;text-overflow:ellipsis}
.npc-read .rw b{margin-left:auto;font-family:var(--mono);font-variant-numeric:tabular-nums;
                font-size:12px;font-weight:650;letter-spacing:-.02em}
.npc-read .rw b.na{color:var(--ink3);font-weight:500}
.npc-read .ft{font-size:10px;color:var(--ink3);margin-top:6px;padding-top:5px;border-top:1px solid var(--line);line-height:1.55}
.npc-read .ft.act{color:var(--brand)}
/* 页眉软卡里的那张（总览页主图）：底色是浅靛蓝，读数卡改用实白面
   压上去 —— 半透明面在有色底上会把序列色块也染一层，色卡就不准了。 */
.npc.dk .npc-read{background:var(--panel);border-color:var(--brand-border);box-shadow:var(--shadow-md)}

/* 色卡图例：点一下开关一条序列 */
.npc-legend{display:flex;flex-wrap:wrap;align-items:center;gap:6px 4px;margin-top:9px;font-size:11px}
.npc-legend[hidden]{display:none}
.npc-sw{display:inline-flex;align-items:center;gap:6px;border:1px solid transparent;background:none;
        color:var(--ink2);border-radius:var(--r-pill);padding:3px 9px 3px 7px;font-size:11px;
        cursor:pointer;transition:background var(--dur-fast),border-color var(--dur-fast),opacity var(--dur-fast)}
button.npc-sw:hover{background:var(--bg-2);border-color:var(--line-2)}
.npc-sw i{width:10px;height:10px;border-radius:2px;flex:none}
.npc-sw em{font-style:normal;color:var(--ink3);font-size:10px}
.npc-sw.off{opacity:.42}
.npc-sw.off i{background:none!important;box-shadow:inset 0 0 0 1.5px var(--line-2)}
.npc-note{color:var(--ink3);font-size:10.5px;margin-left:auto;padding-left:10px;text-align:right}
.npc.dk .npc-sw{color:var(--dk-ink2)}
.npc.dk button.npc-sw:hover{background:rgba(255,255,255,.7);border-color:var(--dk-line2)}
.npc.dk .npc-sw.off i{box-shadow:inset 0 0 0 1.5px var(--dk-line2)}
.npc.dk .npc-note{color:var(--dk-ink3)}
@media(prefers-reduced-motion:reduce){
  .npc-read{animation:none}
  .npc-bar,.npc-step{transition:none}
}

/* ── 可排序表头 ────────────────────────────────────────────────
   箭头默认不显形，hover 出灰箭头，排上了才出实心箭头 —— 表头一排常驻
   的双向小三角是纯噪声，账表本来就够密了。 */
.tbl th.s{cursor:pointer;user-select:none}
.tbl th.s>span{display:inline-flex;align-items:center;gap:4px}
.tbl th:first-child.s>span{flex-direction:row}
.tbl th.s:not(:first-child)>span{flex-direction:row-reverse}
.tbl th.s .sar{width:0;height:0;border-left:3.5px solid transparent;border-right:3.5px solid transparent;
               border-top:4.5px solid var(--ink3);opacity:0;transition:opacity var(--dur-fast)}
.tbl th.s:hover{color:var(--ink)}
.tbl th.s:hover .sar{opacity:.45}
.tbl th.s[data-dir] {color:var(--brand)}
.tbl th.s[data-dir] .sar{opacity:1;border-top-color:var(--brand)}
.tbl th.s[data-dir="asc"] .sar{border-top:0;border-bottom:4.5px solid var(--brand)}

/* ── 叠图开关：拆解表第一列那枚圆点 ─────────────────────────────
   点亮之后，该成员的历史序列（服务端单独算的）叠到上面的趋势图上，
   圆点填的就是它在图上的那道颜料色。 */
.tbl th.cmpth{width:44px;text-align:center;font-size:10px;letter-spacing:.06em}
.tbl td.cmpcell{width:44px;text-align:center;padding-left:0;padding-right:0}
.cmpbtn{width:15px;height:15px;border-radius:50%;border:1.5px solid var(--line-2);background:none;
        cursor:pointer;padding:0;display:inline-block;vertical-align:middle;
        transition:border-color var(--dur-fast),background var(--dur-fast),box-shadow var(--dur-fast)}
.cmpbtn:hover{border-color:var(--brand)}
.cmpbtn.on{background:var(--cw,var(--brand));border-color:var(--cw,var(--brand));
           box-shadow:0 0 0 3px color-mix(in srgb,var(--cw,var(--brand)) 20%,transparent)}
.tbl tr.cmp-on td{background:var(--brand-soft)}
.tbl tr.cmp-on:hover td{background:#e7ebfd}
.cmp-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;font-size:11px;color:var(--ink3);
         margin:-4px 0 11px;padding-bottom:10px;border-bottom:1px dashed var(--line)}
.cmp-bar .chip{padding:3px 10px;font-size:11px}
.cmp-full{color:var(--warn);background:var(--warn-soft);border:1px solid var(--warn-line);
          border-radius:var(--r-xs);padding:2px 9px}
.cmp-full[hidden]{display:none}

/* ── 取数骨架屏 ───────────────────────────────────────────────
   原来是一张只写「正在取数…」的白卡：页面先塌成一小块，数据回来再突然
   撑开，读起来像出错了。骨架把版位先占住，并且一个数字都不放 —— 占位条
   是灰块，不是假数据。 */
.skwrap{animation:skIn var(--dur-base) var(--ease)}
@keyframes skIn{from{opacity:0}to{opacity:1}}
.sk{display:block;border-radius:var(--r-xs);
    background:linear-gradient(90deg,var(--bg-2) 25%,#f0f3fd 42%,var(--bg-2) 60%);
    background-size:280% 100%;animation:skWave 1.35s linear infinite}
@keyframes skWave{from{background-position:120% 0}to{background-position:-60% 0}}
.sk-head{display:flex;align-items:baseline;gap:14px;margin:0 0 16px;padding:20px 22px;
         border-radius:var(--r-md);background:linear-gradient(150deg,var(--dk-1),var(--dk-2))}
.sk-head .sk{background:linear-gradient(90deg,rgba(67,83,217,.07) 25%,rgba(67,83,217,.14) 42%,rgba(67,83,217,.07) 60%);
             background-size:280% 100%}
.sk-t{width:132px;height:19px}
.sk-s{width:230px;height:11px}
.sk-h3{width:196px;height:12px;margin-bottom:16px}
.sk-plot{height:206px;border-radius:var(--r-sm)}
.sk-row{height:13px;margin-bottom:15px}
.sk-row:last-child{margin-bottom:2px;width:62%}
@media(prefers-reduced-motion:reduce){
  .sk,.skwrap{animation:none}
}

/* ══ 下钻卡片 ═══════════════════════════════════════════════════
   下钻 ≠ 导航。点一个数字想知道的是「它是哪来的」，人没打算离开这一屏 ——
   原来那一下把人甩到明细页，刚才在看的那张表、那一行为什么异常，全丢了。
   所以从右侧滑出一张卡片，底下那页留在原地看得见：**你还在这儿**。
   走右侧不走居中弹窗，是因为居中会正好盖住刚点的那张表；靠右推开，
   被下钻的行还在视野里，能对照着读。 */
#drill,.drillwrap{position:fixed;inset:0;z-index:60}
#drill .drill-bd,.drillwrap .drill-bd{position:absolute;inset:0;background:rgba(20,26,60,.34);
                 opacity:0;transition:opacity var(--dur-base) var(--ease)}
#drill.on .drill-bd,.drillwrap.on .drill-bd{opacity:1}
.drill-pn{position:absolute;top:0;right:0;bottom:0;width:min(660px,94vw);
          background:var(--panel-bg);border-left:1px solid var(--line-2);
          box-shadow:-18px 0 60px rgba(28,38,90,.16);display:flex;flex-direction:column;
          transform:translateX(100%);transition:transform var(--dur-base) var(--ease)}
#drill.on .drill-pn,.drillwrap.on .drill-pn{transform:none}
/* 卡头用深漆面：和每页那块主角区同一语汇，一眼知道这是「被点出来的那个数」 */
.drill-hd{background:linear-gradient(150deg,var(--dk-1),var(--dk-2));color:var(--dk-ink);border-bottom:1px solid var(--dk-line2);
          padding:18px 22px 20px;position:relative;flex:none}
.drill-eb{font-size:10px;letter-spacing:.16em;color:var(--dk-acc);text-transform:uppercase}
.drill-x{position:absolute;top:14px;right:16px;width:28px;height:28px;border-radius:var(--r-xs);
         background:rgba(255,255,255,.7);border:1px solid var(--dk-line2);color:var(--dk-ink2);
         cursor:pointer;font-size:13px;line-height:1}
.drill-x:hover{background:var(--panel);color:var(--brand)}
.drill-ttl{font-size:19px;font-weight:650;letter-spacing:-.02em;margin-top:9px}
.drill-sub{font-size:11.5px;color:var(--dk-ink2);margin-top:3px}
.drill-val{font-family:var(--mono);font-size:32px;font-weight:650;letter-spacing:-.04em;
           margin-top:10px;font-variant-numeric:tabular-nums;line-height:1.1}
.drill-val small{font-family:-apple-system,BlinkMacSystemFont,"PingFang SC",sans-serif;
                 font-size:12px;font-weight:500;color:var(--dk-ink3);margin-left:5px}
.drill-bd2{flex:1;overflow-y:auto;padding:20px 22px 28px}
.drill-sec{margin-bottom:26px}
.drill-sec:last-child{margin-bottom:0}
/* 编号在这里是真的有序：口径 → 明细行 → 上游系统，是一条追溯链，不是装饰 */
.drill-sec h4{font-size:12.5px;font-weight:650;margin:0 0 11px;display:flex;align-items:center;gap:9px}
.drill-sec h4 i{width:19px;height:19px;border-radius:50%;background:var(--brand);color:#fff;
                font-style:normal;font-size:10.5px;display:grid;place-items:center;flex:none;font-weight:700}
.drill-note{font-size:11.5px;color:var(--ink2);line-height:1.75;margin:0 0 10px}
.drill-note b{font-family:var(--mono);font-variant-numeric:tabular-nums}
.drill-tbl{font-size:11.5px}
.drill-tbl th,.drill-tbl td{padding:6px 8px;white-space:nowrap}
.drill-tbl td:not(:first-child){font-size:11px}
/* 单据清单：这张表的主角是单据号 —— 它是拿去 ERP 反查的那把钥匙，
   人扫这张表就是在找它。所以单据号列压深、加粗、走等宽（等宽是必须的：
   一串 10 位数字不对齐，肉眼根本比不出两个号差在哪一位）；
   其余标识列（日期/客户/SKU/凭证号）同样等宽但收到次级灰，让号码浮出来。 */
.drill-doc td.dno{font-family:var(--mono);font-variant-numeric:tabular-nums;
                  font-size:10.5px;color:var(--ink2);letter-spacing:-.01em}
.drill-doc td:first-child.dno{color:var(--ink);font-weight:650;font-size:11px}
.drill-doc tbody tr:hover td{background:var(--panel-2)}
.drill-acts{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}
.drill-acts .chip{font-size:11.5px;padding:5px 11px;text-decoration:none}
/* 血缘：一张上游表一条，字段挂在下面；没接上的表压一层暖底，别装作已经接好了 */
.drill-lin{list-style:none;margin:0;padding:0}
.drill-lin li{border:1px solid var(--line);border-radius:var(--r-sm);padding:10px 12px;
              margin-bottom:8px;background:var(--panel-2)}
.drill-lin li.pend{background:var(--warn-soft);border-color:var(--warn-line)}
.drill-lin .ln-h{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.drill-lin .ln-h b{font-size:12px;font-weight:650}
.drill-lin .ln-t{font-size:11px;color:var(--ink3)}
.drill-lin .ln-s{font-size:9.5px;color:var(--warn);background:#fff;border:1px solid var(--warn-line);
                 border-radius:var(--r-pill);padding:1px 7px;margin-left:auto}
.drill-lin .ln-c{margin-top:7px;display:flex;flex-wrap:wrap;gap:4px}
.drill-lin .ln-c code{font-size:10px;font-family:var(--mono);background:var(--bg-2);
                      color:var(--ink2);border-radius:3px;padding:1px 6px}
.drill-lin li.pend .ln-c code{background:#fff}
/* 数字上的下钻入口：原来是个 <a>，现在是按钮（它不导航，它就地展开） */
button.numlink{font:inherit;background:none;border:0;border-bottom:1px solid var(--brand-border);
               color:var(--brand);cursor:pointer;padding:0;font-family:var(--mono);
               font-variant-numeric:tabular-nums;font-size:12px}
button.numlink:hover{background:var(--brand-soft);border-bottom-color:var(--brand)}
@media(max-width:640px){
  .drill-pn{width:100vw}
  .drill-val{font-size:26px}
}
@media(prefers-reduced-motion:reduce){
  #drill .drill-bd,.drillwrap .drill-bd,.drill-pn{transition:none}
}

/* ── KPI 卡组：各自独立的白卡，靠 gap 分开 ────────────────────
   原来接成一整条（一块外框内用竖线分片）。问题是相邻两片看起来像有
   关系，实际上「不含税收入」和「吨价」之间什么关系都没有 —— 连一条
   就是在暗示一个不存在的结构。拆开之后每张卡是一个独立事实。
   族色从整片顶上的一道渐变收成左上角一枚小方块：4px 满宽的色条在
   八张卡并排时会连成一条彩虹，反而抢过数字。
   列数由 JS 按指标个数写进 --kn，永远单行、永不留空格。 */
.kgrid{display:grid;grid-template-columns:repeat(var(--kn,6),minmax(0,1fr));
       gap:12px;margin-bottom:16px}
/* 2026-08-16：卡面从纯白改成**按指标族**的一层极淡色晕（左上浓、向右下
   化开）。这是 Azulou 那路"彩色卡片"里唯一值得抄进报表的一条 —— 但只有
   在色相本身有含义时才成立：--pg 是指标族色（收入=靛蓝、价格=赭石、
   管控=紫……），色晕就是把左上角那枚小色签放大了一点，不是装饰。
   12% 是上限：再浓一档，卡上的等宽数字读起来就开始"发闷"了。 */
.ktile{padding:14px 15px 12px;position:relative;min-width:0;display:flex;flex-direction:column;
       background:linear-gradient(150deg,color-mix(in srgb,var(--pg,#fff) 12%,#fff) 0%,#fff 72%);
       border:1px solid var(--line);border-radius:var(--r-md);
       box-shadow:var(--shadow-sm)}
.ktile .l{font-size:10.5px;color:var(--ink3);display:flex;gap:6px;align-items:center;letter-spacing:.04em}
.ktile .l::before{content:'';width:8px;height:8px;border-radius:2px;flex:none;
                  background:var(--pg,var(--ink3))}
.ktile .v{font-family:var(--mono);font-size:21px;font-weight:650;letter-spacing:-.04em;margin-top:8px;
          font-variant-numeric:tabular-nums;line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ktile .v small{font-family:-apple-system,BlinkMacSystemFont,"PingFang SC",sans-serif;font-size:10.5px;
                font-weight:500;color:var(--ink3);letter-spacing:0;margin-left:3px}
.ktile .v.na{color:var(--ink3);font-weight:500;font-size:16px}
/* 涨跌药丸：一排数字里色块比彩色文字先被看到。
   同比/环比固定纵排一枚一行 —— 让它们横排时，卡窄一点就换行、宽一点又
   不换，五张卡并排会出现「有的一行有的两行」的参差。纵排看着占一行的
   高度，换来的是一整排卡节奏一致；底部口径行有 margin-top:auto 兜底，
   药丸数量不同也不会把卡底拉歪。 */
.ktile .d{font-size:10.5px;margin-top:7px;font-variant-numeric:tabular-nums;display:flex;
          flex-direction:column;gap:5px;min-height:20px;align-items:flex-start}
.ktile .d .dl{display:inline-flex;align-items:center;gap:5px;border-radius:var(--r-pill);
              padding:2px 9px 2px 7px;font-size:10.5px;line-height:1.55;border:1px solid transparent}
.ktile .d .dl.up{color:var(--good);background:var(--good-soft);border-color:var(--good-line)}
.ktile .d .dl.down{color:var(--bad);background:var(--deny-soft);border-color:var(--deny-line)}
.ktile .d .dl.flat{color:var(--ink3);background:var(--panel-2);border-color:var(--line)}
.ktile .d .dl em{font-style:normal;color:inherit;opacity:.72;font-size:9.5px;letter-spacing:.04em}
.ktile .sub{font-size:10px;color:var(--ink3);margin-top:4px;line-height:1.6}
.ktile .spark{margin-top:9px;height:30px}
/* 卡底口径行：期间与范围写在数字旁边，不让人抬头回去看筛选器 */
.ktile .cal{margin-top:auto;padding-top:9px;border-top:1px solid var(--line);
            font-size:9.5px;color:var(--ink3);letter-spacing:.03em;line-height:1.5;
            white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ktile.locked .v{color:var(--ink3)}
@media(max-width:1180px){.kgrid{grid-template-columns:repeat(auto-fit,minmax(168px,1fr))}}
.lock{font-size:9.5px;background:var(--deny-soft);color:var(--bad);border-radius:3px;padding:1px 6px;
      font-weight:600;border:1px solid var(--deny-line);letter-spacing:0}
.up{color:var(--good)}.down{color:var(--bad)}.flat{color:var(--ink3)}

/* 表格：按账表习惯 —— 极淡斑马纹防串行，数值等宽右对齐。
   2026-08：行高从 ~34px 提到 ~40px（Salepol 那一路的行距），斑马纹
   同步压到几乎看不见 —— 行距拉开之后串行本来就不容易发生，斑马纹
   只需要留一点点做保底，压得越淡，一屏数字读起来越静。 */
.tbl{width:100%;border-collapse:collapse;font-size:12.5px;font-variant-numeric:tabular-nums}
.tbl th{background:transparent;color:var(--ink3);font-weight:600;text-align:right;padding:0 12px 10px;
        border-bottom:1px solid var(--line-2);white-space:nowrap;font-size:10px;letter-spacing:.1em}
.tbl th:first-child,.tbl td:first-child{text-align:left}
.tbl td{padding:12px;border-bottom:1px solid var(--line);text-align:right;white-space:nowrap;color:var(--ink)}
.tbl td:not(:first-child){font-family:var(--mono);font-size:12px}
.tbl tbody tr:nth-child(even) td{background:#f8f9fe}
.tbl tbody tr:last-child td{border-bottom:0}
.tbl tr:hover td{background:#e7ebfd}
.tbl .na{color:var(--ink3)}
.tblwrap{overflow-x:auto}
.tbl .note{border-top:0;margin-top:4px;padding-top:0}
/* 占比格：条是**弹性**的，不是一根固定 62px 的短杠。取舍与总览那三张表
   （.mixsh）一模一样 —— 多出来的宽度进条长就是分辨率，散成列间距就是幻灯片。
   弹性条要有地方可弹，那是列几何的事：渲染出口按「这张表里有没有占比格」
   自动打 .tbl.tight 并把占比这一列标成 .flexcol，见文末「表格渲染层」。 */
.share-cell{display:flex;align-items:center;gap:9px}
.share-bar{flex:1 1 auto;min-width:36px;height:6px;border-radius:3px;background:var(--bg-2);overflow:hidden;
           box-shadow:inset 0 1px 1px rgba(28,38,90,.10)}
.share-bar i{display:block;height:100%;border-radius:3px;background:linear-gradient(90deg,#9aa5f2,var(--brand))}
/* 数字右端收口、宽度固定：表头「占比」压的是这个数，条只是它的注脚 */
.share-cell>em{font-style:normal;flex:none;min-width:46px;text-align:right}

/* 口径声明盒（经典模式版 —— 与 Agent 卡片同规则：不折叠、不截断） */
.caliber{font-size:11.5px;color:var(--ink3);background:transparent;border:1px solid var(--line);
         border-radius:var(--r-sm);padding:12px 14px;display:flex;gap:12px;align-items:flex-start;
         line-height:1.8;overflow:visible;word-break:break-word;margin-bottom:16px}
.caliber>b{color:var(--ink2);font-weight:650;white-space:nowrap;flex:none;font-size:10.5px;letter-spacing:.06em}
.caliber ul{margin:0;padding-left:15px;list-style:disc}
.caliber ul li{margin:3px 0;color:var(--ink2)}
.caliber .sev-warn{color:var(--warn);font-weight:600}
.caliber .sev-critical{color:var(--bad);font-weight:650}

/* 页面级拒答 / 阻断 / 空态 */
.pagecard{border:1px solid var(--line);border-radius:var(--r-md);
          background:var(--panel-bg);box-shadow:var(--shadow-sm);
          padding:28px 30px;max-width:680px;margin:40px auto;line-height:1.85}
.pagecard.deny{border-color:var(--deny-line);background:var(--deny-soft);box-shadow:var(--shadow-sm)}
.pagecard h3{margin:0 0 10px;font-size:17px;font-weight:650;letter-spacing:-.01em}
.pagecard p{color:var(--ink2);font-size:13px}
.pagecard .tag{display:inline-block;font-size:10.5px;padding:2px 9px;border-radius:var(--r-pill);
               font-weight:600;margin-bottom:12px;letter-spacing:.04em}
.pagecard .tag.d{background:var(--deny-soft);color:var(--bad);border:1px solid var(--deny-line)}
.pagecard .tag.n{background:var(--bg-2);color:var(--ink2)}
.pagecard code{background:var(--bg-2);padding:2px 6px;border-radius:4px;font-size:12px;font-family:var(--mono)}
.pagecard .acts{margin-top:16px;display:flex;gap:8px;flex-wrap:wrap}

/* 指标字典卡 */
.mcards{display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:14px}
.mcard{background:var(--panel-bg);box-shadow:var(--shadow-sm);
       border:1px solid var(--line);border-radius:var(--r-md);padding:17px 18px}
.mcard .hd{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.mcard .hd b{font-size:14px;font-weight:650}
.mcard .hd code{font-size:10.5px;color:var(--ink3);background:var(--bg-2);padding:1px 6px;border-radius:3px;
                font-family:var(--mono)}
.badge{font-size:10px;padding:1px 8px;border-radius:var(--r-pill);font-weight:600;letter-spacing:.03em}
.badge.cert{background:var(--good-soft);color:var(--good);border:1px solid var(--good-line)}
.badge.block{background:var(--deny-soft);color:var(--bad);border:1px solid var(--deny-line)}
.mcard .def{font-size:12.5px;color:var(--ink2);margin:10px 0 8px;line-height:1.75}
.mcard .fx{font-size:11px;background:var(--panel-2);border:1px solid var(--line);border-radius:var(--r-xs);
           padding:8px 10px;font-family:var(--mono);color:var(--brand);margin:8px 0;word-break:break-all;line-height:1.6}
.mcard .meta{font-size:10.5px;color:var(--ink3);display:flex;gap:12px;flex-wrap:wrap;margin:9px 0}
.mcard ul{margin:8px 0 0;padding-left:15px;font-size:11.5px;color:var(--ink2)}
.mcard ul li{margin:3px 0;line-height:1.7}

/* ── P1-2 明细透视 / 下钻 ─────────────────────────────────── */
.tbl td.neg{color:var(--bad);font-weight:600}                 /* 负数标红（显示层，不碰原值） */
.tbl tr.pv-total td{font-weight:700;background:var(--panel-2);border-bottom:1px solid var(--line-2)}
.tbl tr.pv-sub td:first-child{font-weight:600}
.tbl tr.pv-click{cursor:pointer}
.tbl tr.pv-click:hover td{background:var(--brand-soft)}
.pv-caret{display:inline-block;width:15px;color:var(--ink3);font-size:9px}
.pv-sublab{font-size:9.5px;color:var(--ink3);background:var(--bg-2);border-radius:3px;padding:0 5px;margin-left:6px;font-weight:400}
.pv-go{font-size:10.5px;color:var(--brand);margin-left:7px;opacity:0;transition:opacity var(--dur-fast)}
.tbl tr:hover .pv-go{opacity:1}
.unitseg{display:inline-flex;border:1px solid var(--line-2);border-radius:var(--r-xs);overflow:hidden;vertical-align:middle}
.unitseg button{border:0;background:var(--panel);padding:5px 11px;font-size:12px;cursor:pointer;color:var(--ink3);line-height:1.4}
.unitseg button:hover{color:var(--ink)}
.unitseg button.on{background:var(--brand);color:#fff;font-weight:600}
.crumbline{display:flex;align-items:center;gap:7px;font-size:12px;color:var(--ink3);margin:-8px 0 14px;flex-wrap:wrap}
.crumbline b{color:var(--ink)}
.crumbline a{color:var(--brand);text-decoration:none;cursor:pointer}
.crumbline a:hover{text-decoration:underline}
.crumbline .chip{padding:3px 10px;font-size:12px}
.numlink{color:var(--brand);text-decoration:none;border-bottom:1px solid var(--brand-border);cursor:pointer}
.numlink:hover{background:var(--brand-soft);border-bottom-color:var(--brand)}

/* 分页 */
/* ── 报表树（侧栏「我的」区）───────────────────────────────────
   星标 / 最近 / 我的视图三段，压在主题导航之上。视觉上刻意做得比主题
   导航**轻**：它是快捷方式，不是新的一级信息架构；做重了会变成两套
   导航打架，人反而要在两处找同一张报表。
   视图项右侧那枚小字标的是它属于哪张报表 —— 同名视图存在不同报表下时
   （「月报」在明细和透视各存一个），不标就分不出点哪个。 */
.cl-item.tr-i{font-size:12.5px;padding-top:6px;padding-bottom:6px}
.cl-item.tr-i .ic.star{width:auto;height:auto;background:none;font-size:10px;
                       color:var(--warn);opacity:1;line-height:1}
.cl-item.tr-i .ic.vw{border-radius:50%;background:var(--brand);opacity:.5}
.cl-item.tr-v{gap:8px}
.cl-item.tr-v em{font-style:normal;margin-left:auto;font-size:9.5px;color:var(--ink3);
                 letter-spacing:.02em;flex:none}
.cl-item.tr-v.stale{cursor:not-allowed}
.cl-item.tr-v.stale,.cl-item.tr-v.stale em{color:var(--ink3)}
.cl-item.tr-v.stale{text-decoration:line-through;text-decoration-color:var(--line-2)}

/* 星标按钮：长在面包屑旁边，星标的是「当前这张报表」，
   控件就该长在标题旁，不收进菜单 */
.starbtn{border:0;background:none;cursor:pointer;font-size:15px;line-height:1;
         color:var(--ink3);padding:4px 6px;border-radius:var(--r-xs);flex:none}
.starbtn:hover{color:var(--warn);background:var(--warn-soft)}
.starbtn.on{color:var(--warn)}
.starbtn:focus-visible{outline:2px solid var(--brand);outline-offset:1px}

/* ── 视图栏（命名视图）─────────────────────────────────────────
   一排 chip，每枚是一套存好的筛选。当前筛选正好等于某一枚时那枚点亮 ——
   人得知道自己站在哪，否则「我现在看的是不是月报那套条件」就又要逐个
   下拉去核对，等于白存。

   失效态（stale）不删也不藏：授权撤了之后视图还在，只是点不动，鼠标
   悬上去写明为什么。悄悄消失会让人以为自己没存过。 */
.viewbar{display:flex;align-items:center;gap:7px;flex-wrap:wrap;
         margin:0 0 12px;padding:9px 12px;background:var(--panel);
         border:1px solid var(--line);border-radius:var(--r-md)}
.viewbar:empty{display:none}
.vb-hd{font-size:10.5px;color:var(--ink3);letter-spacing:.1em;margin-right:2px}
.vb-none{font-size:11.5px;color:var(--ink3)}
.vb{display:inline-flex;align-items:stretch;border:1px solid var(--line-2);
    border-radius:var(--r-pill);overflow:hidden;background:var(--panel)}
.vb-go{border:0;background:none;cursor:pointer;font-size:12px;color:var(--ink2);
       padding:4px 4px 4px 12px;line-height:1.5;max-width:220px;overflow:hidden;
       text-overflow:ellipsis;white-space:nowrap}
.vb-x{border:0;background:none;cursor:pointer;color:var(--ink3);font-size:10px;
      padding:4px 9px 4px 5px;line-height:1.5}
.vb-x:hover{color:var(--bad)}
.vb:hover{border-color:var(--brand)}
.vb:hover .vb-go{color:var(--brand)}
.vb.on{border-color:var(--brand);background:var(--brand-soft)}
.vb.on .vb-go{color:var(--brand);font-weight:650}
.vb.stale{border-style:dashed;border-color:var(--line-2);background:var(--panel-2)}
.vb.stale .vb-go{color:var(--ink3);cursor:not-allowed;text-decoration:line-through}
.vb.stale:hover{border-color:var(--line-2)}
.vb-go:focus-visible,.vb-x:focus-visible{outline:2px solid var(--brand);outline-offset:-2px}
.vb-add{border:1px dashed var(--brand-border);background:none;color:var(--brand);
        border-radius:var(--r-pill);padding:4px 12px;font-size:12px;cursor:pointer;line-height:1.5}
.vb-add:hover:not(:disabled){background:var(--brand-soft)}
.vb-add:disabled{color:var(--ink3);border-color:var(--line-2);cursor:not-allowed}
.vb-new{display:inline-flex;gap:6px;align-items:center}
.vb-new input{font-size:12px;padding:4px 10px;border:1px solid var(--brand-border);
              border-radius:var(--r-pill);background:var(--panel);color:var(--ink);width:180px}
.vb-new input:focus{outline:2px solid var(--brand);outline-offset:1px}
.vb-new .chip{padding:4px 12px;font-size:12px;border-radius:var(--r-pill)}
.vb-err{font-size:11.5px;color:var(--bad);background:var(--deny-soft);
        border:1px solid var(--deny-line);border-radius:var(--r-xs);padding:3px 9px;
        flex-basis:100%;line-height:1.6}

/* ── 长表底部合计栏 ───────────────────────────────────────────
   粘在视口底：明细页一屏放不下 50 行，滚下去之后合计与翻页就跑没了，
   人只好滚回去看一眼再滚回来。sticky bottom 让它一直贴着视口底边，
   滚到面板末尾自然归位。数字来自服务端的全量 SUM（见 classic.js
   totalsBar 的注释），前端不加总。 */
.tfootbar{position:sticky;bottom:0;z-index:2;margin:12px -20px -18px;padding:11px 20px;
          display:flex;gap:16px;align-items:center;flex-wrap:wrap;
          background:var(--panel-2);border-top:1px solid var(--line-2);
          border-radius:0 0 var(--r-md) var(--r-md);
          box-shadow:0 -6px 16px -12px rgba(28,38,90,.40)}
/* 合计项能有十几个（明细列越全越多）。不换行、不裁剪 —— 换行会把这条
   常驻的栏撑成两行吃掉表格的地方，裁剪则会正好省掉要对的那一列。
   所以固定一行、超出横向滚动，栏高恒定，内容一个不少。 */
.tf-sums{display:flex;gap:0 18px;align-items:baseline;flex-wrap:nowrap;
         min-width:0;flex:1;overflow-x:auto;padding-bottom:2px}
.tf-hd{font-size:10.5px;color:var(--ink3);letter-spacing:.08em;white-space:nowrap}
.tf-i{display:inline-flex;flex-direction:column;gap:1px;flex:none}
.tf-i em{font-style:normal;font-size:9.5px;color:var(--ink3);letter-spacing:.03em;white-space:nowrap}
.tf-i b{font-size:13px;font-weight:650;letter-spacing:-.02em;color:var(--ink);white-space:nowrap}
.tf-i b.neg{color:var(--bad)}
.tfootbar .pager{margin-top:0;flex:none}
@media(max-width:760px){ .tfootbar{position:static;margin:12px -20px -18px} }

.pager{display:flex;gap:8px;align-items:center;justify-content:flex-end;margin-top:14px;font-size:12px;color:var(--ink3)}
.pager button{border:1px solid var(--line-2);background:var(--panel);border-radius:var(--r-xs);padding:5px 12px;
              cursor:pointer;font-size:12px;color:var(--ink2)}
.pager button:hover:not(:disabled){border-color:var(--ink3);color:var(--ink)}
.pager button:disabled{opacity:.35;cursor:default}

/* 通用 chip（两种模式共用） */
.chip{border:1px solid var(--line-2);background:var(--panel);border-radius:var(--r-xs);padding:6px 12px;font-size:12.5px;
      color:var(--ink2);cursor:pointer;line-height:1.5;text-align:left;transition:border-color var(--dur-fast),color var(--dur-fast)}
.chip:hover{border-color:var(--brand);color:var(--brand);background:var(--brand-soft)}
.chip.sug{border-style:dashed;color:var(--brand);border-color:var(--brand-border)}
.chip.blocked{color:var(--ink3);border-style:dotted;cursor:default}
.chip.blocked:hover{border-color:var(--line);color:var(--ink3);background:var(--panel)}
.chip.blocked em{font-style:normal;color:var(--warn)}
.chip.primary{background:var(--brand);color:#fff;border-color:var(--brand);
              font-weight:600;box-shadow:0 2px 8px rgba(67,83,217,.28)}
.chip.primary:hover{background:var(--brand-hover);color:#fff;border-color:var(--brand-hover)}

/* ══ 平台图谱三页（数据接入全景 / 报表中心 / 财务共享） ══════════
   这三页不出业务数字，出的是契约与对账结论。所以配色也刻意区别于报表页：
   不用红绿（红绿在报表页有「同比涨跌」的固定含义），只用中性色 + 颜料色，
   把红绿留给「对账没过 / 无来源」这一种真正的异常。 */

/* 链路条：源系统 → 宽表 → 指标 → 报表 */
.flow{display:flex;align-items:stretch;gap:10px;flex-wrap:wrap;margin-bottom:18px}
.fl-step{flex:1 1 190px;min-width:180px;background:var(--panel-bg);box-shadow:var(--shadow-sm);border:1px solid var(--line);
         border-radius:var(--r-md);padding:16px 18px;position:relative;overflow:hidden}
.fl-step::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--brand)}
.fl-step.in::before{background:var(--pg-slate)}
.fl-step.wh::before{background:var(--pg-mauve)}
.fl-step.sem::before{background:var(--pg-ultra)}
.fl-step.out::before{background:var(--pg-ink)}
.fl-step .n{font-family:var(--mono);font-size:27px;font-weight:600;line-height:1.15;letter-spacing:-.03em;
            font-variant-numeric:tabular-nums}
.fl-step .n small{font-size:12px;font-weight:500;color:var(--ink2);margin-left:7px;letter-spacing:0;font-family:inherit}
.fl-step .d{font-size:11px;color:var(--ink3);margin-top:7px;line-height:1.7}
.fl-ar{align-self:center;color:var(--ink3);font-size:14px;flex:none}

/* 对账结论条 */
.recon{border-radius:var(--r-sm);padding:12px 16px;font-size:12px;line-height:1.8;margin-bottom:18px;
       display:flex;gap:12px;align-items:baseline;flex-wrap:wrap}
.recon b{flex:none;font-size:12.5px}
.recon.ok{background:var(--good-soft);border:1px solid var(--good-line);color:#14584a}
.recon.ok b{color:var(--good)}
.recon.bad{background:var(--deny-soft);border:1px solid var(--deny-line);color:var(--bad)}

/* 四段链路 / 五道闸门：同一种编号块 */
.stages,.gates{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:12px}
.stg,.gt{display:flex;gap:12px;align-items:flex-start;border:1px solid var(--line);border-radius:var(--r-sm);
         padding:14px 15px;background:var(--panel)}
.stg .i,.gt .i{width:21px;height:21px;border-radius:var(--r-xs);background:var(--brand);color:#fff;
               display:grid;place-items:center;font-size:10.5px;font-weight:650;flex:none;margin-top:2px;
               font-family:var(--mono)}
.stg b,.gt b{font-size:13px;font-weight:650}
.stg .d,.gt .d{font-size:11.5px;color:var(--ink2);margin-top:5px;line-height:1.75}
.stg .disc{font-size:11px;color:var(--ink3);margin-top:6px;line-height:1.7;
           padding-left:10px;border-left:2px solid var(--line-2)}
.gt code{display:inline-block;margin-top:7px;font-size:10.5px;color:var(--ink3);background:var(--bg-2);
         padding:1px 6px;border-radius:3px;font-family:var(--mono)}

/* 源系统清单 */
.legend{display:flex;gap:8px 18px;flex-wrap:wrap;font-size:11px;color:var(--ink3);margin-bottom:14px}
.legend .lg-i{display:inline-flex;align-items:baseline;gap:6px}
.legend em{font-style:normal}
.st{font-size:10px;padding:1px 8px;border-radius:var(--r-pill);font-weight:600;flex:none;letter-spacing:.03em}
.st.ready{background:var(--good-soft);color:var(--good);border:1px solid var(--good-line)}
.st.partial{background:var(--warn-soft);color:var(--warn);border:1px solid var(--warn-line)}
.st.pending{background:var(--bg-2);color:var(--ink2)}
.sys{border:1px solid var(--line);border-radius:var(--r-sm);margin-bottom:12px;overflow:hidden;background:var(--panel-bg);box-shadow:var(--shadow-sm)}
.sys-hd{display:flex;align-items:center;gap:9px;flex-wrap:wrap;padding:11px 14px;background:var(--panel-2);
        border-bottom:1px solid var(--line)}
.sys-hd b{font-size:13px;font-weight:650}
.sys-hd .meta{font-size:11px;color:var(--ink3);margin-top:0}
.sys-hd .spacer{flex:1}
.sys-block{font-size:11.5px;color:var(--warn);background:var(--warn-soft);padding:7px 14px;
           border-bottom:1px solid var(--warn-line)}
.sys .tblwrap{padding:6px 14px 12px}
.sys .tbl th{padding-top:6px}
.tbl.src td{white-space:normal;vertical-align:top;font-family:inherit;font-size:12.5px}
.tbl.src td.mono,.tbl .mono{font-family:var(--mono);font-size:11.5px}
.tbl.src .note{font-size:11px;color:var(--ink3);line-height:1.7;margin-top:4px;font-weight:400;max-width:340px}
.tbl.src .cols code{display:inline-block;font-size:10.5px;background:var(--brand-soft);color:var(--brand);padding:1px 5px;
                    border-radius:3px;margin:1px 2px 1px 0;font-family:var(--mono)}
.tbl.src .cols code.bad{background:var(--deny-soft);color:var(--bad)}
.tbl .req{font-size:9.5px;color:var(--brand);background:var(--brand-soft);border-radius:var(--r-pill);padding:1px 6px;margin-left:6px}
.tbl .opt{font-size:9.5px;color:var(--ink3);background:var(--bg-2);border-radius:var(--r-pill);padding:1px 6px;margin-left:6px}
.tbl tr.uncov td{background:var(--deny-soft)}
.tbl .bad{color:var(--bad);font-weight:600}

/* 报表中心 */
.rcards{display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:14px}
.rcard{background:var(--panel-bg);box-shadow:var(--shadow-sm);border:1px solid var(--line);border-radius:var(--r-md);padding:17px 18px;
       display:flex;flex-direction:column;gap:8px}
.rcard.off{background:var(--panel-2)}
.rcard .hd{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.rcard .hd b{font-size:14px;font-weight:650}
.rcard .cad{font-size:10.5px;color:var(--ink2);background:var(--bg-2);border:1px solid var(--line);
            border-radius:var(--r-pill);padding:2px 9px;align-self:flex-start;letter-spacing:.03em}
.rcard .basis{font-size:11.5px;color:var(--ink2);line-height:1.75;background:var(--panel-2);
              border:1px solid var(--line);border-radius:var(--r-xs);padding:9px 10px}
.rcard .basis span{display:block;font-size:9.5px;color:var(--ink3);letter-spacing:.12em;margin-bottom:3px}
.rcard .cont{font-size:12px;color:var(--ink2);line-height:1.75}
.rcard .repl{font-size:11px;color:var(--ink3);line-height:1.7}
.rcard .aud{font-size:11px;color:var(--ink3);display:flex;gap:5px;flex-wrap:wrap;align-items:center}
.rcard .who{background:var(--bg-2);color:var(--ink2);border-radius:var(--r-pill);padding:1px 8px;font-size:10.5px}
.rcard .who.me{background:var(--brand-soft);color:var(--brand);font-weight:600}
.rcard .why{font-size:11.5px;color:var(--bad);background:var(--deny-soft);border:1px solid var(--deny-line);
            border-radius:var(--r-xs);padding:8px 10px;line-height:1.75}
.rcard .acts{display:flex;gap:8px;flex-wrap:wrap;margin-top:auto;padding-top:4px}

/* 财务共享：权限矩阵 */
.tbl.mtx th.v{text-align:center;font-size:10.5px;font-weight:600;min-width:72px;white-space:normal;line-height:1.45}
.tbl.mtx td{text-align:center;vertical-align:middle;font-family:inherit}
.tbl.mtx td:first-child{text-align:left;white-space:normal;min-width:170px}
.tbl.mtx td.y{color:var(--good);font-weight:700}
.tbl.mtx td.n{color:var(--ink3);font-weight:700;background:var(--panel-2)}
.tbl.mtx tr.me td{background:var(--brand-soft)}
.tbl.mtx tr.me td.n{background:#d9e0fb}
.tbl.mtx .note{font-size:11px;color:var(--ink3);font-weight:400;margin-top:4px}
.tbl.mtx .note code{font-size:10.5px;background:var(--bg-2);padding:0 4px;border-radius:3px;font-family:var(--mono)}
.mtx-note{font-size:11.5px;color:var(--ink2);line-height:1.8;margin-top:12px;
          padding-left:11px;border-left:2px solid var(--line-2)}

/* 财务共享：组织 × 业务线交叉矩阵
   每个角色一小张 5×3 的格盘。做成一组小倍数（small multiples）而不是一张
   大表，是因为要比的不是数值大小，而是**形状**：大区 BP 是一横条、业务线
   财务是一竖条、总部是满盘、销售岗只剩一格。形状并排才看得出差别。 */
.xgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px}
.xg{border:1px solid var(--line);border-radius:var(--r-sm);padding:12px 13px 10px;background:var(--panel-2)}
.xg.me{border-color:var(--brand-border);background:var(--brand-soft)}
.xg-t{display:flex;align-items:center;gap:7px;margin-bottom:9px;flex-wrap:wrap}
.xg-t b{font-size:12px;font-weight:650}
.xg-m{border-collapse:separate;border-spacing:3px;width:100%}
.xg-m th{font-size:9.5px;font-weight:500;color:var(--ink3);letter-spacing:.03em;
         text-align:right;padding:0 3px;white-space:nowrap}
.xg-m thead th{text-align:center;padding-bottom:2px}
.xg-m td{width:20px;height:16px;border-radius:3px}
.xg-m td.y{background:var(--pg-virid)}
.xg-m td.n{background:var(--line);opacity:.55}

/* 财务共享：角色卡片 */
.rolecards{display:grid;grid-template-columns:repeat(auto-fill,minmax(270px,1fr));gap:12px}
.rolec{border:1px solid var(--line);border-radius:var(--r-sm);padding:15px 16px;background:var(--panel-bg);box-shadow:var(--shadow-sm)}
.rolec.me{border-color:var(--brand-border);background:var(--brand-soft)}
.rolec .hd{display:flex;align-items:center;gap:8px;margin-bottom:9px}
.rolec .hd b{font-size:13px;font-weight:650}
.rolec .kv{font-size:11.5px;color:var(--ink2);line-height:1.9}
.rolec .kv span{display:inline-block;min-width:62px;color:var(--ink3)}
.rolec .scn{font-size:11.5px;color:var(--ink2);line-height:1.8;margin-top:9px;padding-top:9px;
            border-top:1px solid var(--line)}
.rolec .uses{display:flex;gap:5px;flex-wrap:wrap;margin-top:9px}
.rolec .uses .u{font-size:10.5px;background:var(--panel);border:1px solid var(--line);border-radius:var(--r-pill);
                padding:1px 8px;color:var(--ink2)}

/* 财务共享：审计条 / 禁看清单 */
.auditbar{display:flex;gap:14px;flex-wrap:wrap;align-items:baseline;margin-top:14px;padding:12px 14px;
          border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel-2);font-size:11.5px;
          color:var(--ink2)}
.auditbar>b{font-size:12px;color:var(--ink)}
.auditbar b.tnum{color:var(--ink);font-size:13px}
.auditbar em{font-style:normal;color:var(--ink3);flex-basis:100%;line-height:1.75}
.cost{display:flex;gap:8px;flex-wrap:wrap}
.cost .c{display:inline-flex;align-items:center;gap:8px;border:1px solid var(--line);border-radius:var(--r-pill);
         padding:3px 12px;background:var(--panel-2);font-size:12px}
.cost .c code{font-size:10.5px;color:var(--ink3);font-family:var(--mono)}

@media(max-width:760px){
  .flow{flex-direction:column}
  /* `.fl-step` 的 `flex:1 1 190px` 里那个 190px 是**主轴**基准，横排时是宽度；
     一旦翻成 column，主轴变竖，190px 就成了高度基准 —— 于是每张卡不管里面
     只有两行字都撑到 190px，底下拖一块空白（375 下实测内容 50px、卡 190px）。
     这里把基准交回给内容。 */
  .flow .fl-step{flex:0 0 auto}
  .fl-ar{display:none}
}

/* ══ Agent 模式 ═════════════════════════════════════════════
   外壳形制移植自 SRM 的 layouts/AgentLayout.vue：左轨（会话 + 配置面）＋
   中间对话流，桌面端 app 那一路。搬的是**形制与 CSS**，不是它那 4000 行业务 ——
   那边一条会话是「委派」（agent 会去发邮件、提审批，所以要有确认闸门与运行态徽标），
   这边一条会话是「问数」，不发起任何对外动作，于是没有 .run-badge 那一档。

   ── 暖中性画布 ───────────────────────────────────────────
   token 只在 .ag 内改写，全局那套「靛蓝 Azulou 冷雾」一个字不动。
   为什么这一屏可以跟经典模式不同气质：经典模式是**扫读报表**，一屏几十个数字，
   冷雾底把白卡衬出来；Agent 模式是**读长文**（结论段、口径声明、追问），
   冷灰在长文本阅读下更刺眼，暖中性（Claude / Codex 桌面端那一族）更耐看。
   这不是两套设计语言打架 —— 是同一套系统对两种任务的两种气质，
   SRM 的 tokens.css 开篇写的就是这件事。

   改写的只有**中性族**（底 / 面 / 线 / 墨）与阴影。刻意不动的两类：
   · 语义色（good/bad/warn/deny）：涨跌红绿在两个模式里必须是同一个红同一个绿，
     一根「毛利率」曲线不能因为换了壳就换个意思。
   · 颜料组（--pg-*）：图表在两边共用一套调色，读者在模式之间不需要重新适应。
   阴影必须跟着换：全局那套带蓝 rgba(28,38,90) 是为冷底配的，压在暖底上会发脏 ——
   与「冷底配中性灰阴影会发灰」是同一条道理，方向相反。 */
.ag{
  --bg:#faf9f5; --bg-2:#f0eee7; --panel:#fff; --panel-2:#f5f3ed; --panel-bg:#fff;
  --ink:#23221f; --ink2:#6f6d66; --ink3:#a3a099;
  --line:#e9e6dd; --line-2:#ddd9cd;
  --shadow-sm:0 1px 2px rgba(30,25,15,.05),0 2px 8px rgba(30,25,15,.045);
  --shadow-md:0 4px 12px rgba(30,25,15,.08),0 18px 40px rgba(30,25,15,.12);
  /* 左轨比画布再沉一档：它是"旁边那一栏"，不是内容 */
  --rail-bg:#f2f0ea;

  position:fixed;inset:0;display:grid;grid-template-columns:268px minmax(0,1fr);
  background:var(--bg);color:var(--ink);overflow:hidden}
.ag.rail-off{grid-template-columns:0 minmax(0,1fr)}

/* ── 左轨 ──────────────────────────────────────────────── */
.ag .rail{display:flex;flex-direction:column;min-width:0;background:var(--rail-bg);
          border-right:1px solid var(--line);overflow:hidden}
.ag.rail-off .rail{border-right:none}
.ag .rail-top{display:flex;align-items:center;gap:8px;padding:14px 12px 8px}
.ag .rail-brand{display:flex;align-items:center;gap:7px;min-width:0}
/* 立邦红只在这一处出现（标识），与经典模式同一条纪律 */
.ag .rail-mark{width:22px;height:22px;border-radius:6px;flex:none;background:var(--np-red);
               color:#fff;font-size:11px;font-weight:700;display:grid;place-items:center}
.ag .rail-name{font-size:13px;font-weight:650;color:var(--ink);white-space:nowrap}
.ag .rail-tag{font-size:10px;font-weight:700;letter-spacing:.05em;color:var(--brand);
              background:var(--brand-soft);padding:1px 5px;border-radius:4px}
.ag .rail-collapse{margin-left:auto;border:0;background:transparent;cursor:pointer;
                   color:var(--ink3);font-size:14px;padding:2px 5px;border-radius:6px}
.ag .rail-collapse:hover{background:rgba(0,0,0,.05);color:var(--ink)}

.ag .new-btn{margin:4px 12px 10px;padding:8px 11px;border-radius:10px;
             border:1px solid var(--line-2);background:var(--panel);
             display:flex;align-items:center;gap:7px;cursor:pointer;
             font:inherit;font-size:13px;font-weight:600;color:var(--ink);
             box-shadow:var(--shadow-sm);transition:border-color var(--dur-fast) var(--ease),
                                                    transform var(--dur-fast) var(--ease)}
.ag .new-btn:hover{border-color:#c9c4b5;transform:translateY(-1px)}
.ag .new-btn .plus{color:var(--brand);font-size:14px}
.ag .new-btn kbd{margin-left:auto;font-size:10px;color:var(--ink3);font-family:var(--mono);
                 background:transparent}

/* 搜索：会话超过一屏时唯一能用的找法，少于 7 条不出现（空着占位比没有更差） */
.ag .rail-find{padding:0 12px 8px}
.ag .rail-find-in{width:100%;box-sizing:border-box;padding:6px 9px;border-radius:8px;
                  border:1px solid var(--line-2);background:var(--panel);
                  font:inherit;font-size:12px;color:var(--ink);outline:0}
.ag .rail-find-in::placeholder{color:var(--ink3)}
.ag .rail-find-in:focus{border-color:var(--brand)}

.ag .rail-scroll{flex:1;overflow:auto;padding:0 8px 8px}
.ag .rail-empty{padding:14px 10px;font-size:11.5px;color:var(--ink3);line-height:1.7}
.ag .sess-group{font-size:11px;color:var(--ink3);padding:10px 8px 4px;letter-spacing:.02em}

.ag .sess-wrap{position:relative}
.ag .sess{position:relative;display:block;width:100%;text-align:left;border:0;background:transparent;
          cursor:pointer;padding:7px 26px 7px 9px;border-radius:8px;font:inherit}
.ag .sess-wrap:hover>.sess:not(.on){background:rgba(0,0,0,.045)}
.ag .sess.on{background:var(--panel);box-shadow:var(--shadow-sm)}
.ag .sess-title{display:block;font-size:12.5px;color:var(--ink);line-height:1.5;
                white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ag .sess-when{display:flex;align-items:center;flex-wrap:wrap;gap:5px;font-size:10.5px;
               color:var(--ink3);margin-top:2px;font-variant-numeric:tabular-nums}
/* 这条会话里有过拒答：只把计数标出来，不做成警示徽标 ——
   拒答是**系统按规矩办事**，不是出错，给它一个红标会让人以为哪里坏了。 */
.ag .sess-deny{color:var(--ink2)}
.ag .sess-more{position:absolute;top:6px;right:5px;width:22px;height:22px;border:0;
               background:transparent;border-radius:6px;cursor:pointer;color:var(--ink3);
               font-size:16px;line-height:1;display:flex;align-items:center;justify-content:center;
               opacity:0;transition:opacity .12s}
.ag .sess-wrap:hover .sess-more,
.ag .sess-wrap.menu .sess-more{opacity:1}
.ag .sess-more:hover{background:rgba(0,0,0,.09);color:var(--ink)}
.ag .sess-rename{display:block;width:100%;box-sizing:border-box;margin:1px 0;padding:6px 9px;
                 border-radius:8px;border:1px solid var(--brand);background:var(--panel);
                 font:inherit;font-size:12.5px;color:var(--ink);outline:0}

/* ⋯ 浮层菜单。定位由 JS 量出来写进 style（fixed 定位，跟着行走） */
.ag .sess-menu-mask{position:fixed;inset:0;z-index:60}
.ag .sess-menu{position:fixed;z-index:61;min-width:150px;background:var(--panel);
               border:1px solid var(--line);border-radius:10px;padding:5px;
               box-shadow:0 10px 28px rgba(30,25,15,.16)}
.ag .sess-menu-item{display:flex;align-items:center;width:100%;border:0;background:transparent;
                    cursor:pointer;text-align:left;padding:7px 10px;border-radius:7px;
                    font:inherit;font-size:12.5px;color:var(--ink)}
.ag .sess-menu-item:hover{background:rgba(0,0,0,.05)}
.ag .sess-menu-item.danger{color:var(--bad)}
.ag .sess-menu-item.danger:hover{background:var(--deny-soft)}
.ag .sess-menu-sep{height:1px;background:var(--line);margin:4px 6px}

/* ── 左下账户与配置面 ─────────────────────────────────────
   每行一模一样：同高、同字号、同 16px 图标槽、同 hover 底色。
   身份是这一屏最要紧的一件事（可见范围决定了能问什么），所以头像行里
   name 与 scope 都摆出来，不折进菜单。 */
.ag .rail-foot{position:relative;padding:8px;border-top:1px solid var(--line)}
.ag .ag-who{display:flex;align-items:center;gap:8px;width:100%;border:0;background:transparent;
            cursor:pointer;padding:6px 8px;border-radius:9px;text-align:left;font:inherit}
.ag .ag-who:hover,.ag .ag-who.on{background:rgba(0,0,0,.045)}
.ag .who-av{width:26px;height:26px;border-radius:8px;flex:none;display:grid;place-items:center;
            background:#e2ddd0;color:#4a463c;font-size:12px;font-weight:600}
.ag .who-meta{min-width:0;display:flex;flex-direction:column}
.ag .who-name{font-size:12.5px;color:var(--ink);line-height:1.35;white-space:nowrap;
              overflow:hidden;text-overflow:ellipsis}
.ag .who-role{font-size:10.5px;color:var(--ink3);white-space:nowrap;overflow:hidden;
              text-overflow:ellipsis}
.ag .who-caret{margin-left:auto;color:var(--ink3);font-size:12px}
.ag .cfg-pop{position:absolute;left:8px;right:8px;bottom:56px;background:var(--panel);
             border:1px solid var(--line-2);border-radius:12px;padding:5px;
             box-shadow:0 14px 38px rgba(30,25,15,.16);z-index:30}
.ag .cfg-pop[hidden]{display:none}
.ag .cfg-t{font-size:10.5px;color:var(--ink3);padding:5px 9px 4px;letter-spacing:.02em}
.ag .cfg-sep{height:1px;background:var(--line);margin:4px 6px}
/* button 与将来可能出现的 a 共用这一条：text-decoration / font / color 显式写死，
   全局样式表给 a 加了下划线与链接色，不写死就会出现"半个菜单带下划线" */
.ag .cfg-item{display:flex;align-items:center;gap:8px;width:100%;min-height:30px;border:0;
              background:transparent;cursor:pointer;text-align:left;padding:6px 9px;
              border-radius:7px;font:inherit;font-size:12.5px;color:var(--ink);
              text-decoration:none}
.ag .cfg-item:hover{background:rgba(0,0,0,.05);color:var(--ink);text-decoration:none}
.ag .cfg-ic{width:16px;height:16px;flex:none;display:grid;place-items:center;color:var(--ink3);
            font-size:12px}
.ag .cfg-note{margin-left:auto;font-size:10.5px;color:var(--ink3)}
.ag .cfg-note.syn{color:var(--warn)}
.ag .cfg-note.live{color:var(--good)}

/* ── 中间：对话流 ──────────────────────────────────────────
   四行网格：顶栏 / 身份条 / 滚动区 / 输入区。
   ⚠️ 滚动交给中间那一行（minmax(0,1fr) + overflow:auto），不再让 body 滚 ——
   左轨要常驻，body 一滚它就跟着走了。 */
.ag .stage{display:grid;grid-template-rows:auto minmax(0,1fr) auto;
           /* 列也要显式写死 minmax(0,1fr)：只写行的话隐式列是 auto，会被最宽的那一行
              （顶栏）撑成 max-content —— 375 下顶栏 920px，整个舞台跟着横向溢出。
              .stage 自己 min-width:0 拦不住这个，因为撑开的是它内部的隐式列。 */
           grid-template-columns:minmax(0,1fr);min-width:0;overflow:hidden}
.ag .stage-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:10px 20px;
               background:var(--panel);border-bottom:1px solid var(--line)}
.ag .bar-icon{border:0;background:transparent;cursor:pointer;color:var(--ink3);font-size:14px;
              padding:2px 6px;border-radius:6px;flex:none}
.ag .bar-icon:hover{background:rgba(0,0,0,.05);color:var(--ink)}
.ag .stage-title{font-size:14px;font-weight:650;letter-spacing:-.01em;min-width:0;
                 white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ag .stage-sub{font-size:11px;color:var(--ink3);white-space:nowrap}

.ag #whoami{background:var(--panel-2);border-bottom:1px solid var(--line);padding:10px 20px;
            font-size:12px;color:var(--ink2);line-height:1.8}
.ag .stage-scroll{overflow:auto}   /* 滚动由 scrollToTurn 逐次指定 auto/smooth，
                                      这里不设 scroll-behavior —— 设了之后"瞬时补正"
                                      也会被平滑掉，和正在变高的容器打架 */
/* 遮罩只在窄屏抽屉态下存在；桌面端左轨常驻，不需要它 */
.ag .rail-scrim{display:none}
.ag-main{max-width:880px;margin:0 auto;padding:22px 20px 8px}

/* ── 窄屏：左轨改成抽屉 ────────────────────────────────────
   268px 的常驻栏在 375 下要吃掉 71% 的宽。与经典模式侧栏同一个落法：
   平时收起，点 ☰ 盖出来，点遮罩关掉。 */
@media(max-width:860px){
  .ag,.ag.rail-off{grid-template-columns:minmax(0,1fr)}
  .ag .rail{position:fixed;left:0;top:0;bottom:0;width:min(280px,86vw);z-index:50;
            border-right:1px solid var(--line);box-shadow:var(--shadow-md);
            transform:translateX(-102%);transition:transform var(--dur-base) var(--ease)}
  .ag:not(.rail-off) .rail{transform:none}
  .ag:not(.rail-off) .rail-scrim{display:block;position:fixed;inset:0;z-index:49;
                                 background:rgba(30,25,15,.34)}
  .ag .stage-bar{padding:10px 14px}
  .ag .stage-sub{display:none}
  .ag-main{padding:18px 14px 8px}
}

.who{font-size:11px;color:var(--ink3);text-align:right;margin:0 4px 5px 0}
.ask{display:flex;justify-content:flex-end;margin-bottom:14px}
.ask span{background:var(--brand);color:#fff;padding:9px 14px;border-radius:12px 12px 3px 12px;max-width:78%;
          font-size:13.5px;word-break:break-word}
.turn{margin-bottom:28px}
.thinking{display:flex;gap:7px;align-items:center;color:var(--ink3);font-size:12.5px;padding:10px 2px}
.dot{width:5px;height:5px;border-radius:50%;background:var(--brand);animation:bounce 1s infinite}
.dot:nth-child(2){animation-delay:.15s}.dot:nth-child(3){animation-delay:.3s}
@keyframes bounce{0%,60%,100%{opacity:.25;transform:translateY(0)}30%{opacity:1;transform:translateY(-4px)}}

/* Agent 答案卡片（六段式，与旧版一字不差的约束落点） */
.card{border:1px solid var(--line);border-radius:var(--r-md);background:var(--panel-bg);box-shadow:var(--shadow-sm)}
.card.warnbox{border-color:var(--warn-line);background:var(--warn-soft)}
.card.denybox{border-color:var(--deny-line);background:var(--deny-soft)}
.card.neutralbox{border-color:var(--line);background:var(--panel-2)}
.card-h{padding:16px 18px 14px;border-bottom:1px solid var(--line);background:var(--panel-2);position:relative;
        border-radius:11px 11px 0 0}
.card.warnbox .card-h{background:var(--warn-soft);border-color:var(--warn-line)}
.card.denybox .card-h{background:var(--deny-soft);border-color:var(--deny-line)}
.card.neutralbox .card-h{background:var(--bg-2)}
.tag{display:inline-block;font-size:10.5px;padding:2px 9px;border-radius:var(--r-pill);background:var(--brand-soft);
     color:var(--brand);font-weight:600;margin-bottom:8px;letter-spacing:.04em}
.tag.w{background:var(--warn-soft);color:var(--warn);border:1px solid var(--warn-line)}
.tag.d{background:var(--deny-soft);color:var(--bad);border:1px solid var(--deny-line)}
.tag.n{background:var(--bg-2);color:var(--ink2)}
.corner{position:absolute;top:14px;right:16px;font-size:10px;padding:2px 7px;border-radius:3px;
        background:var(--bg-2);color:var(--ink3);font-weight:600}
.corner.deg{background:var(--warn-soft);color:var(--warn)}
.concl{font-size:15.5px;font-weight:650;line-height:1.6;margin:0;padding-right:64px;word-break:break-word;letter-spacing:-.01em}
.card-b{padding:18px}
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(124px,1fr));gap:1px;background:var(--line);
      border:1px solid var(--line);border-radius:var(--r-sm);overflow:hidden;margin-bottom:16px}
.kpi{background:var(--panel);padding:12px 14px;position:relative}
.kpi .l{font-size:11px;color:var(--ink3);letter-spacing:.03em}
.kpi .v{font-family:var(--mono);font-size:19px;font-weight:600;letter-spacing:-.03em;margin-top:5px;
        font-variant-numeric:tabular-nums;word-break:break-all}
.kpi .v.sm{font-size:17px}.kpi .v.xs{font-size:15px}
.kpi .v.na{color:var(--ink3);font-weight:500}
.kpi .d{font-size:11.5px;margin-top:3px;font-variant-numeric:tabular-nums}
.kpi .sub{font-size:10.5px;color:var(--ink3);margin-top:3px;line-height:1.55}
.calmiss{background:var(--deny-soft);border:1px solid var(--deny-line);color:var(--bad);border-radius:var(--r-sm);
         padding:12px 14px;font-size:13px;line-height:1.75;margin-bottom:16px}
.calmiss b{font-weight:700}
.card .caliber{margin-bottom:16px}
.wbanner{font-size:12px;border-radius:var(--r-xs);padding:8px 12px;margin-bottom:10px;line-height:1.75}
.wbanner.warn{background:var(--warn-soft);border:1px solid var(--warn-line);color:var(--warn)}
.wbanner.info{background:var(--panel-2);border:1px solid var(--line);color:var(--ink2)}
.wbanner.crit{background:var(--deny-soft);border:1px solid var(--deny-line);color:var(--bad)}
/* ══ 人工差异分析 ═══════════════════════════════════════════
   位置固定在每页最后一块面板与口径声明之间 —— 先看完数，再写判断，
   写完往下就是口径。左侧那道紫棠竖条是与业务线开关同一个语汇：
   这块内容是**按业务线隔离**的。
   刻意不做成弹窗：写差异分析时要一直看得见上面那些数。 */
.cmt{background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--pg-mauve);
     border-radius:var(--r-sm);padding:14px 16px 12px;margin-bottom:16px}
.cmt-load{font-size:12px;color:var(--ink3)}
.cmt-hd{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:9px}
.cmt-hd b{font-size:13px;letter-spacing:.01em}
.cmt-scope{font-size:11px;color:var(--ink3)}
.cmt-meta{margin-left:auto;font-size:11px;color:var(--ink3);font-variant-numeric:tabular-nums}
/* 类名不叫 .empty：全站已有一个 .empty 空态卡片（886 行），撞名会把这行
   小字撑成一张卡。 */
.cmt-meta.blank{color:var(--warn)}
.cmt-meta.err{color:var(--bad)}
.cmt-in{width:100%;box-sizing:border-box;font:inherit;font-size:13px;line-height:1.8;color:var(--ink);
        border:1px solid var(--line-2);border-radius:var(--r-xs);padding:10px 12px;background:var(--panel-2);
        resize:vertical}
.cmt-in:focus{outline:0;border-color:var(--brand-border);background:var(--panel);
              box-shadow:0 0 0 3px var(--brand-soft)}
.cmt-ft{display:flex;align-items:center;gap:12px;margin-top:9px}
.cmt-hint{font-size:10.5px;color:var(--ink3);line-height:1.6}
.cmt-ft .chip{margin-left:auto;flex:none}
/* 闭环三字段一行：责任人 / 行动项 / 下次复盘期。
   紧贴正文下方、在页脚提示之上 —— 这三样是正文的属性，不是另一件事，
   所以不给它们单独一块面板（试过，一分块就变成「还有一个表要填」）。
   行动项占满剩余宽度：它是三者里唯一要读内容的，另两个是选出来的。 */
.cmt-loop{display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px;margin-top:9px}
.cmt-lb{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--ink3);white-space:nowrap}
.cmt-lb.wide{flex:1 1 320px;min-width:0}
.cmt-loop select,.cmt-loop input{font:inherit;font-size:12px;color:var(--ink);
  border:1px solid var(--line-2);border-radius:var(--r-xs);padding:6px 8px;background:var(--panel-2)}
.cmt-loop select{font-variant-numeric:tabular-nums;max-width:220px}
.cmt-loop input{flex:1 1 auto;min-width:0;white-space:normal}
.cmt-loop select:focus,.cmt-loop input:focus{outline:0;border-color:var(--brand-border);
  background:var(--panel);box-shadow:0 0 0 3px var(--brand-soft)}
/* 上期待复盘：上一期挂在这一格、约定本期回看的行动项。
   用的是全站既有的提醒语汇（warn 琥珀底），**不是**红绿 —— 红绿只表示涨跌，
   一条「该回答的事」不是跌。放在整块最上面：先看到上个月说要做什么，
   再往下看这个月的数和判断，顺序就是人回答问题的顺序。 */
.cmt-due{background:var(--warn-soft);border:1px solid var(--warn-line);
         border-radius:var(--r-xs);padding:10px 12px 2px;margin-bottom:12px}
.cmt-due>b{font-size:12px;color:var(--warn);letter-spacing:.01em}
.cmt-due>.n{margin-left:6px;font-size:11px;color:var(--warn);font-variant-numeric:tabular-nums}
.cmt-due>.h{display:block;font-size:10.5px;color:var(--ink2);line-height:1.6;margin:3px 0 8px}
.cmt-due-it{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 10px;
            padding:8px 0;border-top:1px solid var(--warn-line)}
.cmt-due-it .p{font-size:11px;color:var(--ink3);font-variant-numeric:tabular-nums}
.cmt-due-it .a{flex:1 1 240px;font-size:12.5px;color:var(--ink);line-height:1.7}
.cmt-due-it .o{font-size:11px;color:var(--ink2)}
/* 挂在自己名下的那条加重一档：一屏里最先该被认出来的就是「这条是我的」 */
.cmt-due-it .o.mine{color:var(--warn);font-weight:600}
.cmt-due-it .b{flex:1 1 100%;margin:0;font-size:11px;color:var(--ink3);line-height:1.7}

/* ══ 月度汇报包 ═════════════════════════════════════════════ */
.rp-acts{display:flex;align-items:center;gap:8px;justify-content:flex-end;flex-wrap:wrap}
.rp-acts .fl{font-size:10.5px;color:var(--dk-ink3);letter-spacing:.08em}
.rp-acts select{font-size:12px;padding:5px 10px;border:1px solid var(--dk-line2);border-radius:var(--r-xs);
                background:var(--panel);color:var(--brand)}
.rp-acts .chip{background:rgba(255,255,255,.7);border-color:var(--dk-line2);color:var(--ink2)}

.reasons{margin:14px 0 0;padding:0;list-style:none}
.reasons li{display:flex;gap:12px;padding:10px 0;border-top:1px solid var(--line);font-size:13px;align-items:flex-start}
.reasons li:first-child{border-top:0}
.reasons .amt{flex:none;width:86px;font-weight:600;font-family:var(--mono);font-variant-numeric:tabular-nums;text-align:right}
.reasons .txt{color:var(--ink2);word-break:break-word}
.reasons .txt b{color:var(--ink);font-weight:650}
.acts{display:flex;flex-wrap:wrap;gap:7px;margin-top:16px;padding-top:14px;border-top:1px solid var(--line);align-items:center}
.acts.bare{border-top:0;padding-top:0;margin-top:10px}
.acts .gl{font-size:11px;color:var(--ink3);flex:none;margin-right:2px}
.note{font-size:11.5px;color:var(--ink3);margin-top:14px;padding-top:11px;border-top:1px solid var(--line);line-height:1.75}
.note b{color:var(--warn)}
.altbox{margin-top:16px;padding-top:14px;border-top:1px solid var(--line)}
.altbox .q{font-size:15px;font-weight:650;line-height:1.6;margin:0 0 10px}
.altbox .acts .chip{font-size:13px;padding:6px 13px}
.meta{font-size:10.5px;color:var(--ink3);margin-top:12px;font-variant-numeric:tabular-nums}
.empty{color:var(--ink2);font-size:13.5px;background:var(--panel-bg);box-shadow:var(--shadow-sm);border:1px solid var(--line);border-radius:var(--r-md);
       padding:20px 22px;line-height:1.85}
.empty h2{font-size:15px;margin:0 0 8px;font-weight:650}
.empty code{background:var(--bg-2);padding:1px 5px;border-radius:3px;font-size:12px;font-family:var(--mono)}
/* 输入区。从 position:fixed 改成网格里的一行 —— 左轨常驻之后 body 不再滚，
   fixed 会横跨整屏压到左轨上；而"贴底"这件事现在由 .stage 的行网格保证。
   顶上留一道向上的渐隐，让滚上来的卡片从它下面淡出去，不是硬切一刀。 */
.composer{padding:14px 20px;background:var(--bg);border-top:1px solid var(--line);position:relative}
.composer::before{content:'';position:absolute;left:0;right:0;bottom:100%;height:28px;
                  background:linear-gradient(180deg,rgba(250,249,245,0),var(--bg));pointer-events:none}
.cwrap{max-width:880px;margin:0 auto;background:var(--panel-bg);box-shadow:var(--shadow-sm);border:1px solid var(--line-2);
       border-radius:var(--r-md);padding:11px 13px}
.cwrap:focus-within{border-color:var(--ink3)}
.cwrap textarea{width:100%;border:0;outline:0;resize:none;font:inherit;font-size:14px;line-height:1.6;
                max-height:120px;color:var(--ink);background:transparent}
.crow{display:flex;align-items:center;gap:8px;margin-top:6px;flex-wrap:wrap}
.crow .hint{font-size:10.5px;color:var(--ink3)}
.send{margin-left:auto;background:var(--brand);color:#fff;border:0;border-radius:var(--r-xs);padding:7px 16px;font-size:13px;
      font-weight:600;cursor:pointer}
.send:hover:not(:disabled){background:var(--brand-hover)}
.send:disabled{background:var(--line-2);color:var(--ink3);cursor:not-allowed}
.qseed{display:flex;flex-wrap:wrap;gap:6px;max-width:880px;margin:0 auto 8px}
.qseed button{border:1px dashed var(--brand-border);background:var(--panel);color:var(--brand);border-radius:var(--r-pill);
              padding:4px 11px;font-size:12px;cursor:pointer}
.qseed button:hover{background:var(--brand-soft)}

/* ══ P1-3 T+1 异常预警区（总览页顶部，严重度分色） ═══════════
   原来六张满幅琥珀卡把整个首屏吃掉了，读起来像事故现场。
   改成发丝线分隔的行 + 一枚小严重度标 —— 信息一条不少，但不再压过报表本体。

   ── 2026-08 修订：结论在前，明细折叠 ─────────────────────────
   上一版还是「行不占地方就没问题」的思路，结果 21 条同构预警平铺下来，
   首屏读起来是一份 lint 报告。这一版的版式服务于一个判断：**一屏里，
   一个发现只配占一句话的位置**。所以：
   · 每簇一句结论（.al-say）是这一区唯一的阅读焦点；
   · 明细整段折进 .al-det，展开前一个像素都不占；
   · 严重度仍只走既有的 .al-sev 药丸，簇标题不铺色底 ——
     红绿在本系统只表示涨跌，不拿来当状态底色（这条比「好看」优先）。

   ── 2026-08-16 视觉审计后的修订 ───────────────────────────────
   上一版把 21 条收成了一句话，内容上对了，但那句话仍**排版成一条说明文字**：
   14px，压在一张和下面「渠道结构」一模一样的白卡上。审计的原话是「它没有
   与内容相称的视觉重量，全靠位置在撑」—— 眼睛第一站是 35.0%，第二站是图和
   KPI，这句最该被读到的结论排到第四。两处改法：

   1. **字号提到 16.5px**，让它成为整页第二大的字（第一大是 35.0%）。
      结论句就该按「读句子」排版，不是按「读标注」排版。
   2. **卡面改成与页眉软卡同一层浅靛蓝**，下面的数据卡继续纯白。由此确立
      一条全站规则：**有色底 = 结论，纯白 = 数据**。页眉（本页主角）与
      预警（本页结论）是同一件事的两半，读者看到同一种底色就知道它们一伙；
      再往下的表格是另一类东西。
      刻意**不**给它加页眉那道 3px 靛蓝竖条 —— 那道竖条的含义是「本页主角」，
      一页只能有一个，两处都加就等于没有。
   3. 卡后留 26px（数据区之间是 16px），把「结论区 / 数据区」断开。整页原来
      是等距 16px 的一条卡片流，没有一处告诉读者「换段了」。 */
.al-panel{margin-bottom:26px;background:linear-gradient(150deg,var(--dk-1),var(--dk-2));
          border-color:var(--dk-line2)}
/* 有色底上的分隔线与描边要跟着换一档，否则发丝线在浅靛蓝上会消失 */
.al-panel .al-cl,.al-panel .al-row{border-top-color:var(--dk-line)}
.al-panel .al-cov{border-color:var(--dk-line2)}
.al-panel .al-card:hover{background:rgba(255,255,255,.55)}
.al-panel h3,.al-panel .al-head{color:var(--dk-ink)}
.al-head{display:flex;align-items:baseline;gap:10px;margin:0 0 4px;font-size:13.5px;font-weight:650}
.al-head .hint{font-size:11px;color:var(--ink3);font-weight:400}
.al-count{margin-left:auto;font-size:11px;color:var(--ink3);font-weight:400;white-space:nowrap;
          font-variant-numeric:tabular-nums}
.al-cards{display:flex;flex-direction:column;gap:0}
.al-card{display:flex;align-items:baseline;gap:12px;border:0;border-top:1px solid var(--line);border-radius:0;
         background:transparent;padding:11px 8px;font-size:12.5px;line-height:1.7;text-decoration:none;
         color:var(--ink2);cursor:pointer;margin:0 -8px}
.al-card:hover{background:var(--panel-2)}
.al-sev{flex:none;font-size:10px;font-weight:600;padding:1px 8px;border-radius:var(--r-pill);letter-spacing:.04em}
/* 预警幅度条：六个大区的差距靠长度一眼比出来，不用读数字 */
.al-mag{width:80px;height:6px;border-radius:3px;background:var(--bg-2);overflow:hidden;flex:none;
        box-shadow:inset 0 1px 1px rgba(28,38,90,.10)}
.al-mag i{display:block;height:100%;border-radius:3px;background:linear-gradient(90deg,#eda393,var(--bad))}
.al-card.warn .al-sev{background:var(--warn-soft);color:var(--warn);border:1px solid var(--warn-line)}
.al-card.crit .al-sev{background:var(--deny-soft);color:var(--bad);border:1px solid var(--deny-line)}
.al-card.crit .al-msg{color:var(--ink)}
.al-msg{flex:1;min-width:0}
.al-att{font-size:11px;color:var(--ink3);margin-top:3px}
.al-attnote{color:var(--ink3)}
.al-go{flex:none;color:var(--brand);font-size:11.5px;white-space:nowrap;opacity:0;transition:opacity var(--dur-fast)}
.al-card:hover .al-go{opacity:1}
.al-none{font-size:12.5px;color:var(--good);background:var(--good-soft);border:1px solid var(--good-line);
         border-radius:var(--r-xs);padding:10px 13px;margin-top:10px}

/* ── 聚类：一句结论 + 折叠明细 ───────────────────────────────── */
.al-groups{display:flex;flex-direction:column;gap:2px}
.al-cl{border-top:1px solid var(--line);padding:12px 0 13px}
.al-cl:first-child{border-top:0;padding-top:6px}
/* 簇头一行小字：严重度药丸 / 规则名 / 覆盖度 / 条数。全部走既有词汇，
   这一行是「元数据」，字号压到 11px，不跟结论句抢。 */
.al-cl-top{display:flex;align-items:center;gap:8px;margin-bottom:6px;flex-wrap:wrap}
.al-cl.warn .al-sev{background:var(--warn-soft);color:var(--warn);border:1px solid var(--warn-line)}
.al-cl.crit .al-sev{background:var(--deny-soft);color:var(--bad);border:1px solid var(--deny-line)}
.al-cl-rule{font-size:11.5px;color:var(--ink2);font-weight:600}
/* 覆盖度：面 / 点判定的**依据**摆在结论旁边，读者不用信结论也能自己数。
   等宽数字（.tnum）保证 12/15 和 4/15 竖着看是对齐的。 */
.al-cov{font-size:11px;color:var(--ink3);border:1px solid var(--line);border-radius:var(--r-pill);
        padding:1px 9px;white-space:nowrap}
.al-cl-n{margin-left:auto;font-size:11px;color:var(--ink3);white-space:nowrap}
/* 落单标：不是「其他」，而是「这条没有同伙」—— 用靛蓝描边而不是红，
   落单是一种**结构判定**，不是一种严重度。 */
.al-lone{font-size:10px;font-weight:600;color:var(--brand);background:var(--brand-soft);
         border:1px solid var(--brand-border);border-radius:var(--r-pill);padding:1px 8px;letter-spacing:.04em}
/* 结论句：这一区唯一按「读」来排版的东西 */
/* 结论句：整页第二大的字（第一大是页眉那个 66px 主指标）。
   78ch 是可读行长的上限 —— 再宽，眼睛回到行首会串行。 */
.al-say{margin:0;font-size:16.5px;line-height:1.7;color:var(--ink);font-variant-numeric:tabular-nums;
        max-width:74ch;letter-spacing:-.003em}
.al-more{margin-top:8px;display:inline-flex;align-items:center;gap:5px;border:1px solid var(--line-2);
         background:var(--panel);color:var(--ink2);border-radius:var(--r-pill);padding:3px 12px;
         font-size:11.5px;cursor:pointer;font-family:inherit;
         transition:border-color var(--dur-fast),color var(--dur-fast)}
.al-more:hover{border-color:var(--ink3);color:var(--ink)}
.al-more:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.al-caret{display:inline-block;font-size:9px;line-height:1;transition:transform var(--dur-base) var(--ease)}
.al-more.on .al-caret{transform:rotate(180deg)}
.al-det{margin-top:6px}
/* 展开后的一条明细：可点的行 + 它自己的口径盒。
   口径盒不设 max-height、不 overflow:hidden —— 折的是明细，不是口径。 */
.al-row{border-top:1px solid var(--line)}
.al-row .al-card{border-top:0}
.al-row .caliber{margin:0 0 12px;padding:9px 12px;font-size:11px;line-height:1.7}

/* ══ 报价分析（P2-1）══════════════════════════════════════════
   qa-* 异常定价清单：负毛利整行淡红底；类型徽标区分两类判定。
   sim-* 模拟结果卡：与 KPI 磁贴同语言，但独立成类（模拟数与实际数
   在视觉上不该混用同一套磁贴——这是「事前推演」不是「报表数字」）。 */
tr.qa-row{cursor:pointer}
tr.qa-row:hover td{background:var(--brand-soft)}
tr.qa-neg td{background:var(--deny-soft)}
tr.qa-neg:hover td{background:#fbe6e1}
.qa-flag{display:inline-block;font-size:10px;padding:1px 7px;border-radius:var(--r-pill);white-space:nowrap;
         background:var(--warn-soft);color:var(--warn);border:1px solid var(--warn-line);margin:1px 4px 1px 0}
.qa-flag.neg{background:var(--deny-soft);color:var(--bad);border-color:var(--deny-line)}
/* 敏感性模拟的滑杆：默认原生控件是整页唯一没被收拾过的地方，
   收成与 chip / 表格同一套发丝线语言 */
.cl input[type=range]{-webkit-appearance:none;appearance:none;background:transparent;height:20px;cursor:pointer;
                      vertical-align:middle}
.cl input[type=range]::-webkit-slider-runnable-track{height:3px;border-radius:2px;background:var(--line-2)}
.cl input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:15px;height:15px;
    border-radius:50%;background:var(--panel);border:2px solid var(--brand);margin-top:-6px;
    transition:transform var(--dur-fast)}
.cl input[type=range]:hover::-webkit-slider-thumb{transform:scale(1.12)}
.cl input[type=range]::-moz-range-track{height:3px;border-radius:2px;background:var(--line-2)}
.cl input[type=range]::-moz-range-thumb{width:13px;height:13px;border-radius:50%;background:var(--panel);
    border:2px solid var(--brand)}
.cl input[type=number],.cl input[type=text]{border:1px solid var(--line-2);border-radius:var(--r-xs);padding:5px 9px;
    font-size:12.5px;color:var(--ink);background:var(--panel);font-family:var(--mono)}
.cl input[type=number]:focus,.cl input[type=text]:focus{outline:none;border-color:var(--ink3)}
.sim-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px;margin:12px 0}
.sim-tile{border:1px dashed var(--line-2);border-radius:var(--r-sm);padding:12px 14px;background:var(--panel-2)}
.sim-tile .l{font-size:11px;color:var(--ink3);letter-spacing:.03em}
.sim-tile .v{font-family:var(--mono);font-size:18px;font-weight:600;margin-top:5px;letter-spacing:-.02em}
.sim-tile .d{font-size:11.5px;color:var(--ink2);margin-top:3px}

/* ══ 模式切换过场幕布 ═══════════════════════════════════════
   从 SRM 的 components/ModeTransition.vue 移植（scoped style 整块搬过来，
   .mt--toAgent 这类双横线类名一并保留，好让两边对着看时能逐条对上）。
   DOM 由 assets/modefx.js 每次播放时重建 —— 元素常驻的话关键帧不会重放。

   ⚠️ 下面这些绝对毫秒的 animation-delay 与 modefx.js 的 TIMING / PARTICLE_MS
   是一条链上的：粒子跑完才开幕，文案要在环收拢之后、开幕之前露脸。改任何
   一个数都要回到 modefx.js 文件头那张时间表核一遍。 */
.mt{position:fixed;inset:0;z-index:100000;overflow:hidden;cursor:pointer;user-select:none;
    background:transparent;isolation:isolate}
#modefx[hidden]{display:none}
.mt-canvas{position:absolute;inset:0;width:100%;height:100%;z-index:2;pointer-events:none}
@keyframes mt-fade-out{from{opacity:1}to{opacity:0}}

/* ── 进入 Agent 模式 —— 粒子聚环开幕 ────────────────────────
   编排（刻意把「火花」与「文字」在时间与空间上都分开，避免挤在一起显乱）：
     0        变暗失焦开始（cover），末尾在幕后换壳
     300ms    中央模式牌弹入 —— 火花从它身上炸开的「种子」
     0→1900ms 火花：炸开 → 聚成亮环 → 收拢向心消散（环半径 132px）
     1450ms   文案在**环外下方**浮现 —— 此时环已收拢，两者不抢画面
     2200ms   开幕（open）：柔光一闪，变暗与模糊归零，新界面聚焦成形 */

/* 冰玻璃：冷调「变暗」底 —— 火花是 additive 亮光，只有压暗背景才能真正「炸亮」。
   底色用本系统的靛蓝压深，不是 SRM 那支偏紫的夜蓝。 */
.mt-glass{position:absolute;inset:0;
  background:linear-gradient(160deg,rgba(20,26,58,.76),rgba(11,15,36,.84) 60%,rgba(16,20,48,.8));
  backdrop-filter:blur(0px) saturate(1);-webkit-backdrop-filter:blur(0px) saturate(1);
  opacity:0;animation:mt-glass-in 440ms cubic-bezier(.4,0,.2,1) forwards}
@keyframes mt-glass-in{
  0%{opacity:0;backdrop-filter:blur(0px) saturate(1);-webkit-backdrop-filter:blur(0px) saturate(1)}
  100%{opacity:1;backdrop-filter:blur(20px) saturate(1.1);-webkit-backdrop-filter:blur(20px) saturate(1.1)}}
.mt--toAgent.mt--open .mt-glass{animation:mt-glass-out 600ms cubic-bezier(.22,1,.36,1) forwards}
@keyframes mt-glass-out{
  0%{opacity:1;backdrop-filter:blur(20px) saturate(1.1);-webkit-backdrop-filter:blur(20px) saturate(1.1)}
  100%{opacity:0;backdrop-filter:blur(0px) saturate(1);-webkit-backdrop-filter:blur(0px) saturate(1)}}

/* 极光微光：给暗底一点冷色。靛蓝 + 紫棠，与颜料组同源 */
.mt-aurora{position:absolute;inset:-15%;
  background:radial-gradient(36% 44% at 30% 34%,rgba(67,83,217,.26),transparent 68%),
             radial-gradient(42% 48% at 72% 66%,rgba(109,91,208,.22),transparent 70%);
  filter:blur(30px);opacity:0;animation:mt-aurora-in 620ms ease-out 180ms forwards}
@keyframes mt-aurora-in{from{opacity:0}to{opacity:.8}}
.mt--toAgent.mt--open .mt-aurora{animation:mt-fade-out 520ms ease-in forwards}

/* 中央模式牌：图标压在光环圆心（45% 与 sparkField 的 centerYRatio 是同一个数） */
.mt-focus{position:absolute;left:50%;top:45%;translate:-50% -50%;width:0;height:0;z-index:4}
.mt-chip-text{position:absolute;left:0;right:0;
  /* 图标中心在 45%，半高 28px、光环半径 70px —— 贴着光环外缘起排 */
  top:calc(45% + 78px);text-align:center;z-index:4;padding:0 20px}
.mt-chip-glow{position:absolute;left:0;top:0;width:140px;height:140px;margin:-70px 0 0 -70px;
  border-radius:50%;
  background:radial-gradient(closest-side,rgba(120,146,255,.5),rgba(109,91,208,.2) 55%,transparent 74%);
  filter:blur(4px);opacity:0;
  animation:mt-chip-glow-in 600ms ease-out 330ms forwards,
            mt-chip-glow-pulse 1.8s ease-in-out 900ms infinite alternate}
@keyframes mt-chip-glow-in{from{opacity:0}to{opacity:1}}
@keyframes mt-chip-glow-pulse{from{filter:blur(4px) brightness(1)}to{filter:blur(9px) brightness(1.25)}}
.mt-chip-icon{position:absolute;left:0;top:0;display:flex;align-items:center;justify-content:center;
  width:56px;height:56px;margin:-28px 0 0 -28px;border-radius:16px;
  background:linear-gradient(150deg,#fff,#e2e7ff 42%,#a9b3f5 80%,#6d5bd0);
  box-shadow:0 10px 30px rgba(28,38,90,.5),0 0 34px rgba(120,146,255,.55),
             inset 0 1px 2px rgba(255,255,255,.8);
  opacity:0;animation:mt-chip-pop 560ms cubic-bezier(.34,1.56,.64,1) 300ms forwards}
.mt-chip-icon svg{fill:var(--brand)}
@keyframes mt-chip-pop{
  0%{opacity:0;transform:scale(.4)}60%{opacity:1;transform:scale(1.1)}100%{opacity:1;transform:scale(1)}}
.mt-chip-label{font-size:20px;font-weight:700;letter-spacing:.08em;text-indent:.08em;
  background:linear-gradient(100deg,#eef1ff,#c2ccff 45%,#d6ccfa);
  -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;
  text-shadow:0 2px 18px rgba(120,146,255,.4);
  opacity:0;animation:mt-chip-text 520ms cubic-bezier(.22,1,.36,1) 1450ms forwards}
.mt-chip-sub{margin-top:8px;font-size:12.5px;letter-spacing:.14em;text-indent:.14em;
  color:rgba(200,209,245,.85);
  opacity:0;animation:mt-chip-text 540ms cubic-bezier(.22,1,.36,1) 1580ms forwards}
@keyframes mt-chip-text{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
.mt--toAgent.mt--open .mt-focus,
.mt--toAgent.mt--open .mt-chip-text{animation:mt-fade-out 520ms ease-in forwards}

/* 开幕柔光 */
.mt-flash{position:absolute;inset:0;z-index:3;pointer-events:none;opacity:0;
  background:radial-gradient(circle at 50% 45%,rgba(255,255,255,.9) 0%,rgba(214,222,255,.4) 26%,transparent 60%)}
.mt--toAgent.mt--open .mt-flash{animation:mt-flash-go 600ms ease-out forwards}
@keyframes mt-flash-go{
  0%{opacity:0;transform:scale(.92)}35%{opacity:.85}100%{opacity:0;transform:scale(1.2)}}

/* ── 返回经典模式 —— 光粒归位成工作台线框 ─────────────────────
   与去程同构：先遮住 → 主戏 → 开幕，只是主戏是「聚拢成秩序」而不是「炸开成光环」。
     0        浅色冰玻璃升起（cover），末尾在幕后换壳
     100ms    秩序网格浮起，给线框一层底衬
     0→1240ms 粒子：四面涌入 → 归位成线框 → 流光扫过点亮 → 松开散去
     620ms    文案在**线框正下方**浮现（top 由 computeLatticeFrame 算，与画布共用几何）
     1360ms   开幕（open）：柔光一闪，冰玻璃与模糊归零，经典界面显现 */
.mt-frost{position:absolute;inset:0;z-index:0;
  background:radial-gradient(46% 60% at 26% 30%,rgba(67,83,217,.28),transparent 70%),
             radial-gradient(50% 62% at 78% 68%,rgba(109,91,208,.24),transparent 72%),
             radial-gradient(40% 50% at 62% 20%,rgba(91,103,137,.18),transparent 74%),
             linear-gradient(180deg,rgba(246,247,253,.95),rgba(226,230,246,.97));
  backdrop-filter:blur(0px) saturate(1);-webkit-backdrop-filter:blur(0px) saturate(1);
  opacity:0;animation:mt-frost-in 360ms cubic-bezier(.4,0,.2,1) forwards,
                      mt-frost-drift 3.4s ease-in-out 300ms infinite alternate}
@keyframes mt-frost-in{
  0%{opacity:0;backdrop-filter:blur(0px) saturate(1);-webkit-backdrop-filter:blur(0px) saturate(1)}
  100%{opacity:1;backdrop-filter:blur(16px) saturate(1.06);-webkit-backdrop-filter:blur(16px) saturate(1.06)}}
@keyframes mt-frost-drift{from{background-position:0 0,0 0,0 0,0 0}to{background-position:3% -2%,-3% 2%,2% 1%,0 0}}
.mt--toClassic.mt--open .mt-frost{animation:mt-frost-out 480ms cubic-bezier(.22,1,.36,1) forwards}
@keyframes mt-frost-out{
  0%{opacity:1;backdrop-filter:blur(16px) saturate(1.06);-webkit-backdrop-filter:blur(16px) saturate(1.06)}
  100%{opacity:0;backdrop-filter:blur(0px) saturate(1);-webkit-backdrop-filter:blur(0px) saturate(1)}}

/* 秩序网格：线框的底衬，也是「回到有结构的工作区」这层意思。
   遮罩收在中央，避免铺满全屏显得脏。 */
.mt-grid{position:absolute;inset:0;z-index:1;
  background-image:linear-gradient(to right,rgba(67,83,217,.11) 1px,transparent 1px),
                   linear-gradient(to bottom,rgba(67,83,217,.11) 1px,transparent 1px);
  background-size:46px 46px;
  mask-image:radial-gradient(56% 58% at 50% 43%,#000 0%,transparent 74%);
  -webkit-mask-image:radial-gradient(56% 58% at 50% 43%,#000 0%,transparent 74%);
  opacity:0;animation:mt-grid-in 640ms cubic-bezier(.22,1,.36,1) 100ms forwards}
@keyframes mt-grid-in{from{opacity:0;transform:scale(1.07)}to{opacity:1;transform:scale(1)}}
.mt--toClassic.mt--open .mt-grid{animation:mt-fade-out 400ms ease-in forwards}

/* 文案：排在线框正下方；top 走内联样式（几何由 computeLatticeFrame 单点给出） */
.mt-copy-classic{position:absolute;left:0;right:0;z-index:4;text-align:center;padding:0 20px}
.mt-title-classic{font-size:clamp(20px,2.6vw,30px);font-weight:700;letter-spacing:.18em;
  /* 补掉末字之后那一格字距，否则整行会左偏半格 —— 视觉居中要的是这个 */
  text-indent:.18em;
  background:linear-gradient(120deg,var(--brand),#5566e6 50%,var(--pg-mauve));
  background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;
  opacity:0;animation:mt-classic-copy 460ms cubic-bezier(.22,1,.36,1) 620ms forwards}
.mt-sub-classic{margin-top:8px;font-size:12.5px;letter-spacing:.24em;text-indent:.24em;
  color:rgba(70,80,120,.72);
  opacity:0;animation:mt-classic-copy 460ms cubic-bezier(.22,1,.36,1) 740ms forwards}
@keyframes mt-classic-copy{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}
.mt--toClassic.mt--open .mt-copy-classic{animation:mt-fade-out 380ms ease-in forwards}

/* 开幕柔光：对应去程的 .mt-flash，浅底上收敛一档，别闪瞎 */
.mt-sheen{position:absolute;inset:0;z-index:3;pointer-events:none;opacity:0;
  background:radial-gradient(circle at 50% 43%,rgba(255,255,255,.95) 0%,rgba(226,231,252,.5) 28%,transparent 62%)}
.mt--toClassic.mt--open .mt-sheen{animation:mt-sheen-go 520ms ease-out forwards}
@keyframes mt-sheen-go{
  0%{opacity:0;transform:scale(.94)}30%{opacity:.75}100%{opacity:0;transform:scale(1.16)}}

/* 跳过提示 */
.mt-skip{position:absolute;right:22px;bottom:18px;z-index:5;font-size:12px;letter-spacing:.14em;
  color:rgba(206,214,245,.5);opacity:0;animation:mt-skip-in 360ms ease-out 620ms forwards}
.mt--toClassic .mt-skip{color:rgba(70,80,130,.5)}
@keyframes mt-skip-in{from{opacity:0}to{opacity:1}}

@media (prefers-reduced-motion:reduce){
  /* modefx.js 在这个偏好下根本不播（直接换壳），这里是双保险 */
  #modefx{display:none!important}
  *{animation:none!important;transition:none!important}
}

@media(max-width:860px){
  /* 侧栏与页眉在这个宽度下的落法全部搬到文件末尾「窄屏适配」块里 ——
     那里从「横向平铺」改成了抽屉，两处各写一半必然打架。这里只留工作区。 */
  .cl{grid-template-columns:minmax(0,1fr);min-height:auto}
  .cl-body{padding:20px 16px 48px}
  .cl-title h2{font-size:21px}

  .concl{padding-right:0}
  .corner{position:static;display:inline-block;margin-bottom:6px}
  .qseed{flex-wrap:nowrap;overflow-x:auto;padding-bottom:4px;-webkit-overflow-scrolling:touch}
  .qseed button{white-space:nowrap;flex:none}
  .reasons .amt{width:74px}
}

/* ══ 财务报表（三大报表 / 分部拆分表）══════════════════════════════════
   账表的排版规矩和分析页不一样：分析页要突出一两个结论，账表要让人**逐行
   核**。所以这里刻意反着来 —— 不加卡片、不加色块、不加图，只把层级、
   合计行与不可用状态做清楚，其余全部让路给数字本身。 */

/* 报表切页：三张表是同一份数据的三种排版，用分段按钮而不是三个侧栏项 ——
   看完利润表接着看现金流是同一件事的连续动作，不该走一趟导航。 */
.sttabs{display:inline-flex;gap:2px;padding:3px;margin-bottom:14px;
        background:var(--bg-2);border-radius:var(--r-pill)}
.sttab{border:0;background:transparent;color:var(--ink2);cursor:pointer;
       padding:6px 18px;border-radius:var(--r-pill);font-size:12.5px;font-weight:600;
       transition:background var(--dur-fast),color var(--dur-fast)}
.sttab:hover{color:var(--ink)}
.sttab.on{background:var(--panel);color:var(--brand);box-shadow:var(--shadow-sm)}

.stbar{margin-bottom:12px}
.stbar .spacer{flex:1}
.scopechip{font-size:11.5px;color:var(--ink);background:var(--brand-soft);
           border:1px solid var(--brand-border);border-radius:var(--r-pill);padding:4px 12px;font-weight:600}
.stbar .hint{font-size:10.5px;color:var(--ink3)}

/* 恒等式校验条：平的时候一枚小对勾就够，破的时候必须刺眼。
   **不允许「不显示」这个中间态** —— 校验跑了没跑、结果如何，页面上要能看见。 */
.idn{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:12px}
.idn-i{display:inline-flex;align-items:center;gap:6px;font-size:11px;
       border-radius:var(--r-pill);padding:4px 11px;border:1px solid transparent}
.idn-i>i{font-style:normal;font-size:10px;line-height:1}
.idn-i.ok{background:var(--good-soft);border-color:var(--good-line);color:var(--good)}
.idn-i.bad{background:var(--deny-soft);border-color:var(--deny-line);color:var(--bad);font-weight:650}
.idn-i.na{background:var(--panel-2);border-color:var(--line);color:var(--ink3)}

/* 报表行：层级靠缩进，合计靠字重与上边框 —— 不用底色。
   账表里每加一块底色，就少一分「这一列数字是一条竖线」的可读性。 */
.sttbl td:first-child{color:var(--ink2)}
.sttbl .stln.lv0>td{font-weight:700;color:var(--ink);border-top:1.5px solid var(--ink);
                    border-bottom:0;background:transparent}
.sttbl .stln.lv1>td{font-weight:650;color:var(--ink)}
.sttbl .stln.lv1>td:first-child{padding-left:0}
.sttbl .stln.lv2>td:first-child{padding-left:18px;font-weight:400}
.sttbl .stln.b>td{background:var(--panel-2)}
.sttbl .stln.lv0>td,.sttbl tbody tr.stln.lv0:nth-child(even) td{background:transparent}
.sttbl tr.stsec td{background:transparent;border-bottom:1px solid var(--line-2);
                   color:var(--ink3);font-size:10px;letter-spacing:.12em;font-weight:700;
                   padding-top:18px;padding-bottom:6px}
.sttbl .sptot{border-left:1px solid var(--line-2);font-weight:650}
.sttbl .rsn{font-style:normal;color:var(--ink3);font-size:10.5px;font-weight:400}
.tbl td.rsn{white-space:normal;text-align:left;color:var(--ink3);font-size:11px;line-height:1.6}

/* 分析口径条（毛利率 / 净利率）：它们不是准则报表行，所以摆在表外，
   而不是混进行次序里冒充一行会计科目。 */
.stder{display:flex;flex-wrap:wrap;gap:26px;margin-top:16px;padding-top:14px;
       border-top:1px solid var(--line)}
.stder-i{display:flex;flex-direction:column;gap:3px}
.stder-i em{font-style:normal;font-size:10.5px;color:var(--ink3);letter-spacing:.06em}
.stder-i b{font-size:16px;color:var(--ink);font-weight:650}

/* 拆分维度切换 */
.segbtn{display:inline-flex;border:1px solid var(--line-2);border-radius:var(--r-pill);overflow:hidden}
.segbtn button{border:0;background:var(--panel);color:var(--ink2);cursor:pointer;
               padding:5px 14px;font-size:12px;font-weight:600}
.segbtn button+button{border-left:1px solid var(--line-2)}
.segbtn button.on{background:var(--brand-soft);color:var(--brand)}


/* ══ 同步运行台 ═══════════════════════════════════════════════
   这一页的视觉只干一件事：**让「真的跑过的」和「还没接的」一眼分得开**。
   两块的左侧色条不同色（实绩=群青，未接入=琥珀），未接入行整行压灰并把
   阻塞点写在最右列 —— 灰不是「次要」，是「这里没有数据在流动」。
   刻意没做的：不给未接入的表任何绿色、对勾或进度条。这一页上唯一的绿
   只属于 schema drift 的「两个方向都干净」，而那一条是每次现算的。 */
.sy-lead{display:flex;gap:12px;align-items:baseline;flex-wrap:wrap;margin:0 0 16px;
         background:var(--warn-soft);border:1px solid var(--warn-line);border-left:3px solid var(--warn);
         border-radius:var(--r-sm);padding:12px 16px}
.sy-lead b{flex:none;font-size:12.5px;color:var(--warn)}
.sy-lead span{font-size:12px;line-height:1.8;color:#6b5314}

.sy-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:10px;margin-bottom:18px}
.sy-tile{background:var(--panel-bg);border:1px solid var(--line);border-radius:var(--r-md);
         padding:13px 15px;position:relative;overflow:hidden}
.sy-tile::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--line-2)}
.sy-tile.real::before{background:#3a4fb8}
.sy-tile.off::before{background:var(--warn)}
.sy-tile.ok::before{background:var(--good)}
.sy-tile.bad::before{background:var(--bad)}
.sy-tile .l{font-size:10.5px;color:var(--ink3);letter-spacing:.04em}
.sy-tile .v{font-size:25px;font-weight:600;letter-spacing:-.03em;line-height:1.2;margin-top:5px;color:var(--ink)}
.sy-tile .v small{font-size:11.5px;font-weight:500;color:var(--ink2);margin-left:6px;letter-spacing:0}
.sy-tile.off .v{color:var(--warn)}
.sy-tile.bad .v{color:var(--bad)}
.sy-tile .d{font-size:10.5px;color:var(--ink3);line-height:1.7;margin-top:6px}

/* 两张表都要能换行：任务说明与阻塞点是整句话，nowrap 会把它们撑出屏幕 */
.tbl.sy-bat td,.tbl.sy-src td{white-space:normal;vertical-align:top;font-family:inherit;font-size:12.5px}
.tbl.sy-bat td:nth-child(4),.tbl.sy-bat td:nth-child(5){font-family:var(--mono);white-space:nowrap}
.tbl.sy-bat .note,.tbl.sy-src .note{font-size:10.5px;color:var(--ink3);line-height:1.7;margin-top:4px;
                                    font-weight:400;max-width:360px}
.tbl.sy-src .note.bad{color:var(--bad)}
.tbl.sy-bat td small{font-size:10px;color:var(--ink3);margin-left:3px}
.tbl.sy-bat tr.fail td{background:var(--deny-soft)}
/* 未接入整行压灰：色度降下去，读者的眼睛自然落到上半页真在跑的那几行 */
.tbl.sy-src tr.off td{background:var(--panel-2);color:var(--ink2)}
.tbl.sy-src tr.off td b{color:var(--ink2)}
.tbl.sy-src .sy-blk{color:var(--warn);max-width:260px}

.sy-st{display:inline-block;font-size:10.5px;padding:2px 9px;border-radius:var(--r-pill);white-space:nowrap;
       border:1px solid var(--good-line);background:var(--good-soft);color:var(--good)}
.sy-st.failed{border-color:var(--deny-line);background:var(--deny-soft);color:var(--bad)}
.sy-st.skipped{border-color:var(--line-2);background:var(--bg-2);color:var(--ink3)}

.sy-sla{display:inline-block;font-size:10.5px;padding:2px 9px;border-radius:var(--r-pill);white-space:nowrap;
        border:1px solid var(--line-2);background:var(--bg-2);color:var(--ink3)}
.sy-sla.on_time{border-color:var(--good-line);background:var(--good-soft);color:var(--good)}
.sy-sla.late{border-color:var(--deny-line);background:var(--deny-soft);color:var(--bad)}
/* 未接入用琥珀而不是红：它不是故障，是还没开始 —— 两者要分得开 */
.sy-sla.not_connected{border-color:var(--warn-line);background:var(--warn-soft);color:var(--warn)}
.sy-assume{display:inline-block;font-size:9.5px;color:var(--warn);background:var(--warn-soft);
           border:1px solid var(--warn-line);border-radius:var(--r-pill);padding:1px 6px;margin-left:6px}

.sy-foot{font-size:10.5px;color:var(--ink3);line-height:1.75;margin-top:10px}
.sy-none{font-size:12px;line-height:1.8;border-radius:var(--r-sm);padding:13px 16px;display:flex;gap:9px;
         align-items:baseline;flex-wrap:wrap}
.sy-none.ok{background:var(--good-soft);border:1px solid var(--good-line);color:#2a5a45}
.sy-none.warn{background:var(--warn-soft);border:1px solid var(--warn-line);color:#6b5314}
.sy-none .ck{font-size:16px;color:var(--good);font-weight:700}

/* drift 非 0 时要刺眼：整块红底、列名等宽加粗、severity 单独一枚徽章 */
.sy-drift{display:flex;flex-direction:column;gap:10px}
.sy-drift .dr{border-radius:var(--r-sm);padding:12px 14px;border:1px solid var(--deny-line);
              background:var(--deny-soft)}
.sy-drift .dr.warn{border-color:var(--warn-line);background:var(--warn-soft)}
.sy-drift .hd{display:flex;gap:9px;align-items:center;flex-wrap:wrap}
.sy-drift .hd code{font-family:var(--mono);font-size:12.5px;font-weight:600;color:var(--bad);
                   background:#fff;border:1px solid var(--deny-line);border-radius:3px;padding:1px 7px}
.sy-drift .dr.warn .hd code{color:var(--warn);border-color:var(--warn-line)}
.sy-drift .hd .k{font-size:11.5px;font-weight:600;color:var(--ink)}
.sy-drift .hd .sev{font-size:9.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--bad);
                   border:1px solid var(--deny-line);border-radius:var(--r-pill);padding:1px 7px;background:#fff}
.sy-drift .dr.warn .hd .sev{color:var(--warn);border-color:var(--warn-line)}
.sy-drift .hd .src{font-size:10.5px;color:var(--ink3);margin-left:auto}
.sy-drift p{font-size:11.5px;color:var(--ink2);line-height:1.8;margin:7px 0 0}
/* ══ 质感整改 ══════════════════════════════════════════════════
   靶子是用户的一句原话：「整个系统透着浓浓的 PPT 感觉」。

   这一轮**没有**再动色板 —— 靛蓝 Azulou 的每个 token 原样保留；也没有
   重做上一轮已经解决的两件事（预警 21 条同构长句已由服务端聚类收敛，
   页眉深漆面已换成浅靛蓝软卡并把结论层与数据层分开）。

   在那之上还剩四条，都是**版位**问题不是配色问题，共同点是「按幻灯片的
   规矩排，不是按账表的规矩排」：
     ① 卡片按同排最高的那张拉齐 —— 短的那张底下拖一块空框
     ② 长表沿用短表的行距 —— 二十行的透视一屏装不下，逐行核账变成翻页
     ③ 宽表列名不折行 —— 十一列撑到横向溢出，被切掉的正好是立论那一列
     ④ 卡底那行口径被裁掉三分之二，七张卡重复七次读不完的灰字
   外加一处「最大的面积装着空气」：一套糊全站的骨架屏（落地时整页往下弹
   一次）。
   （本轮原本还有一处：月度汇报包页眉右半那块空面积，当时用五个模块磁贴
   填上。后来整页被重排成一份连续文档，那半边和磁贴一起不存在了，对应的
   .rp-mods / .rp-figs 规则已删 —— 见下文「月度汇报包重排成一份材料」。）
   ══════════════════════════════════════════════════════════════ */

/* ── ① 网格不再按最高的那张拉齐 ─────────────────────────────────
   总览页「渠道结构」5 行、「品类拆解」10 行，grid 默认 stretch 把左边那张
   白卡撑到 583px —— 与右边一样高，底下 230px 是空的。
   空白不是留白：留白是有节奏的间隔，这是一块被撑出来的空框，正是幻灯片
   版式的味道（每页两个占位框，谁短谁留白）。卡片按自己的内容收边，
   栏与栏之间靠 gap 分开就够了。 */
.grid2,.mcards,.rcards,.rolecards,.xgrid,.stages,.gates{align-items:start}

/* ── ② 长表收行高：密度跟着行数走，不是一个行高走天下 ──────────────
   把行高提到 ~46px 是对的 —— 对**五行的拆解表**是对的，那个尺度上留白
   换来的是「一屏数字读起来静」。
   同一套行距落到明细透视（20 行）和费用逐月拼接明细（19 行）上就翻脸了：
   一屏十来行，而账表最基本的用法是一眼扫完一年十二个月。
   所以密度按长度分档：行数 ≥ 12 的表自动加 .dense（JS 在 paint 出口统一
   打，见 classic.js densify），行高收到 ~32px；斑马纹同时补回一点 ——
   行距一紧，串行的风险就回来了，斑马纹得跟着补。
   字号一档都不缩：账表读的就是数字本身，缩字号是把省地方省到读者头上。 */
.tbl.dense th{padding-bottom:8px}
.tbl.dense td{padding:6px 12px;line-height:1.55}
.tbl.dense tbody tr:nth-child(even) td{background:#f8f9fd}

/* ── ③ 宽表：与其提示「右边还有内容」，不如先让它不用横滚 ─────────
   毛利分析十一列，实测 1280 下横向溢出 44px —— 被切在屏外的正好是最后
   那列「差值」，而两口径差值就是这一页的立论点。溢出的主要来源是
   「毛利率(扣返利前)」这类长列名被 nowrap 撑成一条 130px 的横杆；
   允许折成两行，一列省下 50–60px，十一列刚好收得回来。
   列名一个字都不缩写：「扣返利前 / 扣返利后」是这套系统最容易出人命的
   一处口径区别，省字省不得。
   真滚不下的时候滚动条常驻可见 —— 触控板上自动隐藏的滚动条等于没有提示。 */
.tbl.wide th{white-space:normal;line-height:1.4;min-width:56px}
.tbl.wide th,.tbl.wide td{padding-left:9px;padding-right:9px}
.tblwrap{scrollbar-width:thin}
.tblwrap::-webkit-scrollbar{height:9px}
.tblwrap::-webkit-scrollbar-track{background:var(--panel-2);border-radius:5px}
.tblwrap::-webkit-scrollbar-thumb{background:var(--line-2);border-radius:5px}
.tblwrap::-webkit-scrollbar-thumb:hover{background:var(--ink3)}

/* ── ④ KPI 卡底的口径行：先让它读得完 ──────────────────────────
   「口径写在数字旁边、不让人抬头回去看筛选器」这条没错，错在实测是把
   309px 的文字塞进 99px 的格子：屏幕上永远是「期间 2026-07 · 华…」，
   68% 被省略号吃掉。一行读不完的字，既没起到它要起的作用，又每张卡都占掉
   一行加一道分隔线 —— 七张卡就是七行读不完的灰字加七道横线。
   收短由 JS 做（见 classic.js kcal / kcalFull，全名进 title，且页眉与
   底部口径盒里逐字列着，一个字没少）；这里去掉那道分隔线 ——
   卡片本身已经有边框和留白，再加一道线是第三层分隔。 */
.ktile .cal{padding-top:8px;border-top:0;text-overflow:clip;font-size:10px;letter-spacing:.02em}
/* 卡内纵向节奏按「关系远近」给，不是均匀铺开：数和它的涨跌是一组，贴紧；
   口径是脚注，margin-top:auto 推到底（原规则已有，这里只收间距）。 */
.ktile{padding:13px 14px 11px}
.ktile .v{margin-top:6px}
.ktile .d{margin-top:6px}
.ktile .spark{margin-top:8px;opacity:.85}

/* ── 骨架屏与目标版式同构 ──────────────────────────────────────
   骨架屏存在的全部意义是「落地时别弹」。原来一套骨架糊全站：矮页眉 + 一张图
   + 六行表；而总览页真实版式是 300px 页眉软卡 + 结论卡 + 七张 KPI 卡 +
   两栏表 —— 版位对不上，数据一回来整页往下弹一次，读起来像出错了。 */
/* 高度是照着落地后的实测值定的，不是拍的：页眉软卡 399px、结论卡 233px、
   KPI 行 191px（1280 宽、总部身份、七个指标）。骨架对不上就等于没骨架。 */
.sk-head.tall{min-height:399px;align-items:flex-start;flex-direction:column;gap:16px;padding:24px}
.sk-big{width:230px;height:60px}
.sk-concl{min-height:233px}
.sk-concl .sk-row:last-child{width:78%}
.sk-kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(148px,1fr));gap:12px;margin-bottom:16px}
.sk-kpi{height:191px;border-radius:var(--r-md)}
@media(prefers-reduced-motion:reduce){ .sk-kpi,.sk-big{animation:none} }

/* ══ 报表上传 ══════════════════════════════════════════════════
   报表中心的上传区 + 结构识别确认视图 + 模板列表。

   这一块的视觉任务只有一个：**让「哪几条是机器定的、哪几条要你定」
   一眼分得开**。所以只用两档 —— 自动采纳走常规白卡，待确认走琥珀软底
   （--warn-soft）。没有第三档，也不用红：待确认不是错误，是「系统不敢
   替你定」，染成红色会把人吓成「出问题了」，然后所有人都只想把它点掉。

   置信度用一根细条 + 一个两位小数，**不做「高/中/低」分级** ——
   0.86 和 0.90 之间隔着自动采纳线，分级会把这条线抹掉，而这条线正是
   这一整块东西的立身之本。
   ══════════════════════════════════════════════════════════════ */

/* ── 上传区 ─────────────────────────────────────────────────── */
.up-panel{margin-bottom:var(--sp-4)}
.updrop{border:1.5px dashed var(--brand-border);border-radius:var(--r-md);
        background:var(--brand-soft);padding:26px 20px;text-align:center;
        transition:background var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease)}
.updrop.on{background:#e4e8ff;border-color:var(--brand)}
.updrop .ic{font-size:26px;line-height:1;color:var(--brand);margin-bottom:6px}
.updrop .t{font-size:14px;color:var(--ink);display:flex;align-items:center;
           justify-content:center;gap:8px;flex-wrap:wrap}
.updrop .s{margin-top:8px;font-size:12px;color:var(--ink3)}
.upnote{margin-top:10px;padding:9px 12px;border-radius:var(--r-sm);
        background:var(--panel-2);border:1px solid var(--line);
        font-size:12.5px;color:var(--ink2);line-height:1.65}
.upnote.bad{background:var(--deny-soft);border-color:var(--deny-line);color:var(--bad)}
.upnote.ok{background:var(--good-soft);border-color:var(--good-line);color:var(--good)}
.linkbtn{background:none;border:0;padding:0;color:var(--brand);cursor:pointer;
         font-size:inherit;text-decoration:underline;text-underline-offset:2px}

/* ── 置信度条 ───────────────────────────────────────────────── */
.cf{display:inline-flex;align-items:center;gap:6px;vertical-align:middle}
.cf .tr{display:block;flex:none;width:52px;height:5px;border-radius:var(--r-pill);
        background:var(--line-2);overflow:hidden}
.cf i{display:block;height:100%;border-radius:var(--r-pill);background:var(--good)}
.cf.low i{background:var(--warn)}
.cf b{font:600 11.5px/1 var(--mono);font-variant-numeric:tabular-nums;color:var(--good)}
.cf.low b{color:var(--warn)}
.cf.none{color:var(--ink3);font-family:var(--mono)}

/* ── 证据列表 ───────────────────────────────────────────────── */
.ev{margin:6px 0 0;padding-left:14px;list-style:none}
.ev li{position:relative;font-size:12px;line-height:1.7;color:var(--ink2);margin:2px 0}
.ev li::before{content:"·";position:absolute;left:-11px;color:var(--brand);font-weight:700}
.ev li b{color:var(--ink)}

/* 结论条的第三档：待确认。**不复用 .recon.bad** —— 那是红的，
   而「有 4 项要你确认」不是错误，是系统不敢替你定。染成红色，人会先
   慌一下再想办法把它点掉，而这一页要的恰恰是他慢下来看一眼。 */
.recon.pend{background:var(--warn-soft);border:1px solid var(--warn-line);color:#6b4a13}
.recon.pend b{color:var(--warn)}

/* ── 待人工确认清单 ─────────────────────────────────────────── */
.pend{background:var(--warn-soft);border-color:var(--warn-line)}
.pd{padding:10px 0;border-top:1px dashed var(--warn-line)}
.pd:first-of-type{border-top:0}
.pd-t{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.pd-t b{font-size:13.5px}
.pd-r{margin-top:3px;font-size:12.5px;color:var(--warn);line-height:1.7}

/* ── 整表结论（表头行 / 期间轴 / 合计行） ───────────────────── */
.vd{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:var(--sp-4)}
.v1{background:var(--panel-2);border:1px solid var(--line);border-radius:var(--r-sm);
    padding:12px 14px}
.v1 .k{font-size:11.5px;color:var(--ink3);letter-spacing:.04em}
.v1 .n{margin-top:2px;font-size:15px;font-weight:600;display:flex;align-items:center;
       gap:8px;flex-wrap:wrap}

/* ── 左原表 / 右逐列 ─────────────────────────────────────────
   并排是有意的：右边的证据说「第 D 列第 4 行」，人得能立刻扭头看到那一格。
   窄屏塌成上下两块 —— 塌了之后证据与原表隔了一屏，但总比横向滚动强。 */
.upgrid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
        gap:var(--sp-4);align-items:start}
@media(max-width:1080px){.upgrid{grid-template-columns:1fr}}

.pvwrap{max-height:520px;overflow:auto}
.pvtbl{font-size:12px}
.pvtbl td,.pvtbl th{white-space:nowrap;max-width:180px;overflow:hidden;
                    text-overflow:ellipsis}
.pvtbl .rn{width:52px;color:var(--ink3);font-family:var(--mono);
           font-variant-numeric:tabular-nums;text-align:right}
.pvtbl .rn .tt{display:inline-block;margin-left:4px;padding:0 4px;border-radius:var(--r-xs);
               background:var(--brand-soft);color:var(--brand);font-size:10px;font-family:inherit}
/* 表头行：这一行是整份识别的支点，给它一档软底，让人一眼看到判在哪 */
.pvtbl tr.hdr td{background:var(--brand-soft);font-weight:600;color:var(--ink)}
/* 合计行：左侧一道竖线 + 淡底。**不能和数据行长得一样** ——
   长得一样，人就会把它当数据行，而「按大区求和翻一倍」正是这么来的 */
.pvtbl tr.tot td{background:var(--warn-soft)}
.pvtbl tr.tot td:first-child{box-shadow:inset 3px 0 0 var(--warn)}
.pvtbl td.k-number{font-family:var(--mono);font-variant-numeric:tabular-nums;text-align:right}
.pvtbl td.k-date{font-family:var(--mono);color:var(--pg-mauve)}
.pvtbl td.k-empty{color:var(--ink3)}
.pvnote{margin-top:8px;font-size:12px;color:var(--ink2);line-height:1.7}

/* ── 逐列识别结果 ───────────────────────────────────────────── */
.cols{max-height:820px;overflow:auto}
.colc{border:1px solid var(--line);border-radius:var(--r-sm);padding:11px 13px;
      margin-top:10px;background:var(--panel-2)}
.colc:first-of-type{margin-top:0}
/* 待确认：琥珀软底 + 左侧一道竖线。这是这一页唯一要人动手的地方 */
.colc.low{background:var(--warn-soft);border-color:var(--warn-line);
          box-shadow:inset 3px 0 0 var(--warn)}
.cc-h{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.cc-h .lt{display:inline-flex;align-items:center;justify-content:center;
          min-width:22px;height:22px;padding:0 5px;border-radius:var(--r-xs);
          background:var(--ink);color:#fff;font:600 11px/1 var(--mono)}
.cc-h b{font-size:13.5px}
.cc-r{margin-top:4px;font-size:12px;color:var(--ink2);line-height:1.7}
/* 「候选最高 0.93」：分数照给，但先用一行小字说清它不是一条已生效的判定 */
.cand{display:inline-flex;align-items:center;gap:5px;font-size:11px;color:var(--ink3)}
.cand.none{color:var(--ink3);font-style:normal}
.cc-p{margin-top:9px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.cc-p label{font-size:11.5px;color:var(--ink3)}
.rlsel,.cbsel{max-width:100%;padding:5px 8px;border:1px solid var(--line-2);
              border-radius:var(--r-xs);background:#fff;color:var(--ink);font-size:12.5px}
.cbsel{min-width:210px;flex:1}
.colc.low .rlsel,.colc.low .cbsel{border-color:var(--warn-line)}

/* ── 存为模板 / 模板列表 ───────────────────────────────────── */
.svrow{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.txt{flex:1;min-width:240px;padding:8px 11px;border:1px solid var(--line-2);
     border-radius:var(--r-sm);background:#fff;color:var(--ink);font-size:13.5px}
.tpl .note{font-size:11.5px;color:var(--ink3);margin-top:2px}
.tpl .tag{margin-right:4px}
.tpl-none{font-size:12.5px;color:var(--ink2);line-height:1.7}
.dash{color:var(--ink3)}

/* ══ 收入分析深化（量 / 价 / 结构 + 贡献排行）══════════════════
   版式沿用「结论层与数据层分开」那次修订：结论行是软卡（靛蓝底、
   大字号），瀑布与表是数据层（白底、等宽数字、右对齐）。
   三种行在榜单里必须一眼分得开 —— 明细行 / 分段带 / 表尾合计，
   否则「其余 236 个合计」会被当成第 17 个客户读进去。
   ══════════════════════════════════════════════════════════════ */
.rv-panel .npc{margin-top:var(--sp-3)}
/* 控件条：基期与条数是这一块的前提，放在标题下、结论上 */
.rv-ctl{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap;margin-bottom:var(--sp-3)}
.rv-ctl .fl{font-size:11.5px;color:var(--ink3)}
.rv-ctl select{padding:5px 9px;border:1px solid var(--line-2);border-radius:var(--r-xs);
               background:#fff;color:var(--ink);font-size:12.5px}

/* 结论层 */
.rv-lead{background:var(--brand-soft);border:1px solid var(--brand-border);
         border-radius:var(--r-sm);padding:var(--sp-4) var(--sp-4) var(--sp-3)}
.rv-lead-h{font-size:16px;line-height:1.7;color:var(--ink)}
.rv-lead-h b{font-weight:650;font-variant-numeric:tabular-nums}
.rv-lead-h b.up{color:var(--good)}.rv-lead-h b.down{color:var(--bad)}
.rv-lead .rv-base{margin-left:var(--sp-3);font-size:12px;color:var(--ink3);white-space:nowrap}
.rv-lead-s{margin-top:var(--sp-2);font-size:12.5px;line-height:1.8;color:var(--ink2)}
.rv-lead-s b{color:var(--ink);font-weight:600}

/* 数据层：因子表与榜单共用一套数字列样式 */
.rv-tbl td.num,.rv-tbl th.num{text-align:right;font-family:var(--mono);
                              font-variant-numeric:tabular-nums;white-space:nowrap}
.rv-tbl th.num{font-family:inherit}
.rv-tbl td.num.up{color:var(--good)}.rv-tbl td.num.down{color:var(--bad)}
.rv-tbl .rv-note{font-size:11.5px;color:var(--ink3);line-height:1.65}
.rv-tbl .rv-attr{font-size:12px;color:var(--ink2)}
/* 残差行：灰底一道竖线。它不是第四个因子，绝不能长得像因子行 */
.rv-tbl tr.rv-resid td{background:var(--panel-2);color:var(--ink2)}
.rv-tbl tr.rv-resid td:first-child{box-shadow:inset 3px 0 0 var(--ink3)}
/* 合计行：琥珀软底，与透视表的总计行同一套语汇 */
.rv-tbl tr.rv-total td{background:var(--warn-soft);font-weight:600}
.rv-tbl tr.rv-total td:first-child{box-shadow:inset 3px 0 0 var(--warn)}
.rv-tbl tr.rv-others td{background:var(--panel-2);color:var(--ink2)}
/* 分段带：增收前 N / 减收前 N。做成小标题条而不是普通行 */
.rv-tbl tr.rv-band td{background:var(--bg-2);font-size:11.5px;font-weight:600;
                      color:var(--ink2);letter-spacing:.02em;padding-top:7px;padding-bottom:7px}
.rv-tbl tr.rv-up td:first-child{box-shadow:inset 2px 0 0 var(--good)}
.rv-tbl tr.rv-down td:first-child{box-shadow:inset 2px 0 0 var(--bad)}
/* 新增 / 停止：这两个标记是「变动率为 —」的理由，必须挨着成员名 */
.rv-tag{display:inline-block;margin-left:6px;padding:1px 6px;border-radius:var(--r-pill);
        font-size:10.5px;font-weight:600;line-height:1.6}
.rv-tag.new{background:var(--good-soft);color:var(--good);border:1px solid var(--good-line)}
.rv-tag.lost{background:var(--deny-soft);color:var(--bad);border:1px solid var(--deny-line)}

/* 覆盖率说明：分解覆盖了多少收入本身就是结论，不是脚注 */
.rv-cov{margin-top:var(--sp-3);display:flex;flex-direction:column;gap:5px;
        font-size:11.5px;line-height:1.75;color:var(--ink3)}
.rv-cov .rv-cov-ok{color:var(--good)}
.rv-cov .rv-cov-x{color:var(--warn);background:var(--warn-soft);
                  border:1px solid var(--warn-line);border-radius:var(--r-xs);padding:6px 9px}
.rv-cov .rv-cov-life{color:var(--ink2)}
/* ══ 汇报包文档化 ══════════════════════════════════════════════
   靶子是视觉审计的一句话：「月度汇报包本质上是一份文档，却被排成 5 张同构
   卡 —— 每块三个数 + 一段话 + 一个按钮，五块结构完全一样，读到第三块就已经
   不知道自己在读什么了。」

   病根不是间距，是**块与块之间只有布局关系、没有叙事关系**。所以这一块做的
   不是收边距，是把「五张卡」重排成「一份材料」：

     报告头（封面信息 + 目录）→ 一张纸 → 纸上按总述/分项分组的各节
     每节：节号 + 小标题 → 本节回答什么 → 关键数字排成一句话 → 人写的正文
           → 本节约定（责任人/行动项/复盘期）→ 署名

   这一块**叠在**「质感整改」之上，不推翻它：靛蓝页眉软卡（.cl-title）、
   白面大圆角、雾底、涨跌只用红绿这几条一个都没动；只有 rp-figs / rp-fig /
   rp-cmt / rp-loop / rp-mods / rp-mod / rp-note 那套旧类名随五张卡一起作废，
   规则已删（.rp-acts 留着：新的报告头工具条还在用）。
   ══════════════════════════════════════════════════════════════ */

/* ── 报告头 ────────────────────────────────────────────────────
   仍是全站签名件那块靛蓝软卡（.cl-title 的底、边、圆角、左侧竖条全部继承），
   只把内部布局从「左右两栏的看板」换成「自上而下的封面」：
   文种 → 标题 → 封面字段 → 完成度一句话 → 目录。
   原来那个 66px 的「3 / 5」被拿掉了：它是看板指标，而读者要的是「哪两节
   是空的」—— 名字比分数有用，分数还得回头自己数是哪几块。 */
.rpt-head{display:block;padding:18px 24px 20px}
.rpt-top{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.rpt-kind{font-size:10px;letter-spacing:.22em;color:var(--dk-acc);font-weight:600}
/* 期间与导出是**工具**不是材料内容，所以退到右上角一条，不参与封面的阅读流 */
.rpt-top .rp-acts{margin-left:auto}
.rpt-head h2{font-size:25px;margin:10px 0 0;letter-spacing:-.03em;line-height:1.3}
.rpt-head .na{color:var(--dk-ink3)}
.rpt-head .dim{color:var(--dk-ink3);font-weight:400}

/* 封面字段：期间 / 范围 / 编制人 / 数据截至。
   横排一列一格、靠细竖线分隔 —— 与账表页眉那种「一排筛选器」的区别在于
   它们没有交互：这是材料的属地信息，不是让你去调的旋钮。 */
.rpt-cover{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));
           gap:0 22px;margin:14px 0 0;padding-top:13px;border-top:1px solid var(--dk-line)}
.rpt-cover>div{min-width:0;padding:2px 0 2px 14px;border-left:1px solid var(--dk-line)}
.rpt-cover>div:first-child{padding-left:0;border-left:0}
.rpt-cover dt{font-size:10px;letter-spacing:.12em;color:var(--dk-ink3)}
.rpt-cover dd{margin:4px 0 0;font-size:12.5px;color:var(--dk-ink);line-height:1.7;
              word-break:break-word}

/* 完成度：一句话，缺的那几节加重。琥珀是全站「还没做完」的语汇，
   不是红 —— 空着不是错误，是材料还没写完。 */
.rpt-state{margin:14px 0 0;padding-top:12px;border-top:1px solid var(--dk-line);
           font-size:12px;line-height:1.9;color:var(--dk-ink2)}
.rpt-state b{color:var(--warn);font-weight:650;margin-left:4px}
.rpt-state .dim{margin-left:6px}

/* 目录。竖排的一列，不是五个并排的方块：并排方块是「五个同级对象」，
   竖排带序号才是「一份材料的目录」，而且顺序感一眼就在。 */
.rpt-toc{margin-top:14px;padding-top:12px;border-top:1px solid var(--dk-line)}
.rpt-toc .cap{font-size:10px;letter-spacing:.22em;color:var(--dk-ink3)}
.rpt-toc ol{list-style:none;margin:4px 0 0;padding:0}
.rpt-toc li+li button{border-top:1px dotted var(--dk-line)}
.rpt-toc button{display:flex;width:100%;align-items:baseline;gap:12px;padding:6px 2px;
                background:none;border:0;font:inherit;cursor:pointer;text-align:left;
                border-radius:var(--r-xs)}
.rpt-toc button:hover{background:rgba(255,255,255,.55)}
.rpt-toc .no{flex:none;width:1.4em;font-size:11px;color:var(--dk-acc);font-weight:600}
/* 标题与状态之间拉一道引点线（目录的传统做法）：两端相距一千像素时，
   没有这根线，读者对不上「第四节」和右边那个「尚无人撰写」。 */
.rpt-toc .tx{flex:1;min-width:0;display:flex;align-items:baseline;gap:10px;
             font-size:12.5px;color:var(--dk-ink)}
.rpt-toc .tx::after{content:'';flex:1;align-self:center;border-bottom:1px dotted var(--dk-line2);
                    opacity:.7}
.rpt-toc .st{flex:none;font-size:10.5px;color:var(--dk-ink3);letter-spacing:.02em}
/* 三档状态靠字色分，不加图标：已写静音、空缺琥珀加重、越权灰。
   琥珀那一档是这份目录唯一需要被立刻看见的东西。 */
.rpt-toc .gap .tx{color:var(--dk-ink)}
.rpt-toc .gap .st{color:var(--warn);font-weight:650}
.rpt-toc .off .tx,.rpt-toc .off .st{color:var(--dk-ink3)}

/* ── 一张纸，纸上分节 ──────────────────────────────────────────
   原来是五张独立白卡叠着走。白卡在这套视觉里代表「一个独立对象」，五张并排
   就等于宣布这五块互不相干 —— 于是读者读到第三块时确实不知道自己在读什么。
   合成一张纸之后，节与节只靠一道发丝线和留白分开：同一份材料的第三节。 */
.rpt-paper{background:var(--panel-bg);border:1px solid var(--line);border-radius:var(--r-md);
           box-shadow:var(--shadow-sm);padding:6px 30px 22px;margin-bottom:16px}
/* 层级标题（总述 / 分项说明）：只在换档时出现一次，给这一叠节一个总—分的
   骨架。五节平铺就是原来那五张卡的另一种画法。 */
.rpt-tier{font-size:10px;letter-spacing:.24em;color:var(--brand);font-weight:600;
          margin-top:22px;padding-bottom:2px}
.rpt-tier:first-child{margin-top:14px}
.rpt-sec{padding:14px 0 20px;border-top:1px solid var(--line)}
.rpt-tier+.rpt-sec{border-top:0;padding-top:6px}
/* 正文测量宽度收在 78ch 上下：一份材料的行长超过这个数，眼睛回行就会串行。
   数字块不受这条约束（它们自己就短），所以只压在文本类元素上。 */
.rpt-sec>h3,.rpt-sec>.rpt-focus,.rpt-sec>.rpt-lede,.rpt-sec>.rpt-body,
.rpt-sec>.rpt-pact,.rpt-sec>.rpt-gap{max-width:78ch}
.rpt-sec h3{margin:0;font-size:17px;font-weight:650;letter-spacing:-.01em;color:var(--ink);
            display:flex;align-items:baseline;gap:2px}
.rpt-sec h3 .no{flex:none;color:var(--brand);font-weight:650}
.rpt-sec h3 .no::after{content:'、'}
/* 空缺的那一节，连节号都换成琥珀：从目录扫到正文，同一档颜色一路指着它 */
.rpt-sec.gap h3 .no{color:var(--warn)}
.rpt-focus{margin:5px 0 0;font-size:11.5px;color:var(--ink3);line-height:1.7}
.rpt-focus::before{content:'本节回答：'}

/* ── 关键数字：一句话，不是三个方块 ────────────────────────────
   「不含税收入 17.29 亿元（同比 +4.4%、环比 −8.2%）」本来就是一句事实。
   拆成三个磁贴之后，读者要自己在心里把它接回去，五节读下来接十五次。
   数字本身仍然等宽加重 —— 内联不等于把数字埋进句子里找不着。
   对比数不上涨跌色：这里是叙述不是状态灯，何况好坏由正文判断
   （费用率的 + 和收入的 + 不是一回事，同一个符号说明不了问题）。 */
.rpt-lede{margin:13px 0 0;font-size:13.5px;line-height:2.05;color:var(--ink2)}
/* 一个「指标 + 数 + 对比」是一个不可拆的短语：中文可以在任意字之间换行，
   于是「销售费用率」和「12.1%」被拆到两行、「（环比 −0.04pt）」独自起一行，
   读者得把一句话在两行之间拼回去。整段短语 nowrap，换行只发生在分号处。 */
.rpt-lede .fg{white-space:nowrap}
.rpt-lede b{font-family:var(--mono);font-size:15px;font-weight:600;color:var(--ink);
            letter-spacing:-.01em;font-variant-numeric:tabular-nums;margin:0 1px}
.rpt-lede .c{font-size:12px;color:var(--ink3)}
.rpt-lede .c .d{font-variant-numeric:tabular-nums;color:var(--ink2)}
.rpt-lede i{font-style:normal;color:var(--ink3);margin:0 1px}
.rpt-lede .na{color:var(--ink3)}
.rpt-lede .dim{color:var(--ink3);font-size:11.5px}
/* 数字出处压在句尾一行小字：材料里每一句数都得能追回它是哪一页算的 */
.rpt-lede .src{display:block;margin-top:5px;font-size:10.5px;color:var(--ink3);letter-spacing:.02em}
.rpt-lede.none{color:var(--ink3)}

/* ── 人写的正文 ────────────────────────────────────────────────
   首行缩进两字：这是中文材料里「这一段是正文」最省事也最准的信号，
   同时把它和上面那句系统生成的导语在视觉上分开 —— 一份材料里，
   哪句是算出来的、哪句是人写的，不能靠读者去猜。 */
.rpt-body{margin:12px 0 0;font-size:13.5px;line-height:2.05;color:var(--ink)}
.rpt-body p{margin:0 0 9px;text-indent:2em}
.rpt-body p:last-child{margin-bottom:0}

/* ── 本节约定 + 署名 ───────────────────────────────────────────
   三个闭环字段跟在正文末尾，像署名前的一行落款，而不是正文上方一格键值表 ——
   它们是这段判断的归属，不是又一栏要填的东西。左侧那道紫棠竖条与差异分析
   编辑器同一个语汇：这块内容是按业务线隔离的人写的东西。
   一个字段都没被排版挤掉：责任人、行动项、下次复盘期照旧全在。 */
.rpt-pact{margin:12px 0 0;padding:9px 13px;background:var(--panel-2);
          border-left:2px solid var(--pg-mauve);border-radius:0 var(--r-xs) var(--r-xs) 0;
          font-size:12px;line-height:1.9;color:var(--ink2)}
.rpt-pact b{font-size:10px;letter-spacing:.12em;color:var(--ink3);font-weight:600;margin-right:9px}
.rpt-pact em{font-style:normal;color:var(--ink);font-weight:600}
.rpt-pact.none em{color:var(--ink3);font-weight:400}
.rpt-by{margin:8px 0 0;font-size:11px;color:var(--ink3);font-variant-numeric:tabular-nums;
        display:flex;align-items:baseline;gap:10px}
/* 「回那一页改」做成文字链而不是按钮：在一份材料里，编辑入口不该比内容还显眼 */
.rpt-by .lnk{margin-left:auto;flex:none;border:0;background:none;font:inherit;font-size:11px;
             color:var(--brand);cursor:pointer;text-decoration:underline;text-underline-offset:3px;
             padding:0}
.rpt-by .lnk:hover{color:var(--brand-hover)}

/* ── 空位：材料哪里是空的，要一眼看见 ──────────────────────────
   原来这里是一行灰色的「（未填写）」，摆在正文位上几乎看不见 —— 而拿这份
   东西去开会，最先要知道的就是哪几节还没人写。
   用全站「待办」那套琥珀 + 虚线：虚线是「这块还空着」，不是红 ——
   空着不是错误，是还没写。 */
.rpt-gap{margin:13px 0 0;padding:14px 16px;background:var(--warn-soft);
         border:1px dashed var(--warn-line);border-radius:var(--r-sm)}
.rpt-gap b{display:block;font-size:13px;color:var(--warn);font-weight:650;letter-spacing:.01em}
.rpt-gap p{margin:5px 0 11px;font-size:11.5px;color:var(--ink2);line-height:1.8}
@media(max-width:900px){
  .rpt-paper{padding:6px 18px 20px}
  .rpt-cover>div{padding-left:0;border-left:0}
}
/* ══ 总览版位 ══════════════════════════════════════════════════
   接着「质感整改」往下做，治的是同一类毛病的最后一处：**五行的表铺满
   一整幅**。实测（本机，总部身份）：大区拆解的行宽 1440 下 1101px、
   1280 下 941px、1180 下 841px；「华东大区」四个字读完到第一个数字之间
   分别隔着 300 / 238 / 200px 空白，占比条飘在面板 59% / 57% / 55% 处。
   同一页上的渠道结构与品类拆解（列结构一模一样）只有 450–520px 宽、空白
   50–80px —— 一页里同一种表排出两种读法，宽的那张就是幻灯片版位。
   量的时候还带出一处旧账：那两张并排的表在 1180 下把版心撑到 1302px，
   而 html 是 overflow-x:clip，多出来的 122px 不给滚动条、直接裁掉 ——
   被裁掉的正是品类表的毛利率列。这一轮顺带把它收进版心。

   审计给了两条路，都没照单收：
   · (a) 数字列收成右侧一个紧密块。在 1147px 的面板里单做这一件事，只是把
     300px 的空白从列与列之间挪到名字与数字块之间（粗算 ~550px），行更难
     读了，而空白一寸没少。列聚拢是对的，但前提是面板本身别那么宽。
   · (b) 给它找个陪衬填掉半幅。这一页能填的只有编出来的数或装饰件 ——
     那正是要治的病本身。
   走第三条：把第三张表**收回同一个版位**，陪衬就是本来就在这一页上的
   另外两张表。左栏两张五行表（大区在上、渠道在下），右栏一张十行的品类表，
   两栏高度天然接近（5+5 行 vs 10 行），谁都不必被拉宽。

   为什么这样能同时要「读行」和「读列」：财务 BP 用这张表是两步 ——
   先扫一列找出哪个大区不对劲，再读那一行看它的上下文。五行的表扫列本来
   就便宜，贵的是回程：1101px 的行宽超出一次注视的跨度，在毛利率列上发现
   异常之后得横着找回 1100px 才知道是谁。把行收到 ~500px，一行重新变成
   一个视觉单位，两件事就不再互相为难 —— 只有在坚持铺满一整幅时，(a)
   那个取舍才是真取舍。

   光换构图不够：三张表的固有宽度是 423 / 450 / 490px（实测 min-content），
   两栏并排在 1280 下每栏只给得出 439px —— 品类那张会长出横向滚动条。
   所以同时改列几何，两处：
   ① 表的外沿贴齐面板内容边（首列去掉左内边距、末列去掉右内边距）。
      原来表比标题多缩进 12px，是一道谁都没打算要的错位；顺手省 24px。
   ② 占比这一列从第三位移到行尾，条改成弹性（见 classic.js mixShare）。
      它是这一行里唯一的图，不是数：数挨在一起排成紧密块，图去行尾把面板
      多出来的宽度吃掉。多出来的宽度进了条长就是分辨率，散成列间距就是
      幻灯片 —— 这也是为什么三张表要一样宽：条只有同一个刻度才能互相比。
   第 ② 条还兜住了栅格塌成一栏的那一档（1180 及以下）：那时行确实是满幅的，
   但名字到第一个数字仍然只有 83px，余下的 440px 全变成条长 —— 满幅的
   五行表不再是被拉开的表格，而是一张带数字栏的条形图。
   实测（同一台机器、同一身份）：大区拆解名字到第一个数字的空白
   300 / 238 / 200px → 83 / 83 / 83px（1440 / 1280 / 1180），
   行宽 1101 / 941 / 841px → 520 / 520 / 841px，三张表的列一模一样。 */
/* auto-fit + 481px 下限：够摆两栏就两栏，不够就整整齐齐塌成一栏 ——
   481 = 表最窄能站住的 435px + 面板左右内边距 46px，低于它硬摆两栏，
   五列的短表就要长横滚（1180 下栏宽 887，两栏各只剩 389px）。塌成一栏
   之后行是满幅的，但因为占比条吃掉了余量，名字到第一个数字的距离不变。 */
/* minmax 的下限要用 min() 夹住：裸写 481px 时，视口比 481 还窄的设备上轨道
   不会塌栏，而是把整页顶宽 —— 「总览版位」与「窄屏适配」两处改动各自都对，
   叠在一起才露出来（375 下实测 body 被顶到 493）。min(481px,100%) 让它在
   放得下时照旧按 481 起跳，放不下就退回容器宽度。 */
.ovmix{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(481px,100%),1fr));gap:16px;align-items:start}
.ovmix-c{display:flex;flex-direction:column;gap:16px;min-width:0}
/* 表贴齐面板内容边、列内边距收到 9px —— 这一段列几何已经抽成通用的
   .tbl.tight（见文末「表格渲染层」），渲染出口按「表里有没有占比格」自动打，
   所以这里不再重述一遍。.mix 剩下的只有总览这三张表**自己**的那部分：
   钉死的列宽下限（下面几条 nth-child）。 */
/* 三张表钉在同一套列宽上，不各排各的。两个理由都不是对称癖：
   ① 左栏上下叠着大区与渠道两张卡，列宽各算一套的话两张卡的数字列会差
      十几个像素，读第二张时眼睛要重新找一次落点；
   ② 占比条只有同一个刻度才能跨表比 —— 三张表的分母是同一个合计数，
      条长各按各的容器算，36.8% 会画得比 42.5% 还长。
   取的是三张表实测内容宽的上界（品类名最长的那一档），所以正常数据下谁也
   撑不开。真出现更长的名字，只有那一张会自己撑宽、和另两张错开十几像素 ——
   这是 min-width 而不是写死 width 的代价，换来的是名字永不被截断：
   品类名是身份，截一个字就不再是那个品类了。 */
.tbl.mix th:nth-child(1){min-width:106px}
.tbl.mix th:nth-child(2){min-width:100px}
.tbl.mix th:nth-child(3){min-width:64px}
.tbl.mix th:nth-child(4){min-width:64px}
/* 占比列「把这一行剩下的宽度全部领走」那条也搬去了 .tbl.tight th.flexcol：
   原来写的是 th:last-child（靠「占比恒在末列」这个巧合成立），现在列序号由
   渲染出口量出来标 —— 费用结构表的占比在第三列，拆解表在第四／五列，
   同一根条要在三种表上都能弹，就不能再赌它排在哪儿。 */
.mixsh{display:flex;align-items:center;gap:10px}
.mixsh>i{flex:1 1 auto;min-width:36px;height:6px;border-radius:3px;background:var(--bg-2);
         overflow:hidden;display:block}
.mixsh>i>b{display:block;height:100%;border-radius:3px;
           background:linear-gradient(90deg,#9aa5f2,var(--brand))}
/* 数字仍旧右端收口、宽度固定：表头「占比」压的是这个数，条只是它的注脚 */
.mixsh>em{font-style:normal;flex:none;min-width:46px;text-align:right}
/* ══ 窄屏适配 ══════════════════════════════════════════════════
   这一版之前，十四个页面没有一个在 375 下认真看过。实测出来的三条硬伤，
   按「一条比一条更结构性」排：

     ① **body 在全部十四页横向溢出**（375 下 body.scrollWidth 恒为 658）。
        源头只有一个：页眉七件套（面包屑 · 星标 · 业务线 · 数据源 · 经典/Agent ·
        真假后端 · 用户）挤在一条 nowrap 的 flex 上，min-content 就是 658。
        .cl-main 被它撑宽，工作区里每一张白卡跟着一起宽 —— 于是不是「页眉露出
        屏外」，是整页往右长出 283px，而 html/body 那句 overflow-x:clip 把它
        **裁掉**了：用户 chip、真实后端开关、Agent 入口在手机上根本点不到。
     ② **侧栏平铺成一堵墙**。十四项 + 报表树在 375 下五行、约 200px，每页开头
        先交出四分之一屏；分组标题被 display:none 掉，两层信息架构塌成一层。
     ③ **1024 下总览页也溢出**（body 1302 / 视口 1024）。这条与窄屏无关，是
        .grid2 用了 1fr 而不是 minmax(0,1fr)，十列宽表把栅格轨道顶开 ——
        顺手一起修了（见上文 .grid2 处的注释）。

   三条纪律在这一版里一个字没松：
   · **口径盒（.caliber）在任何宽度下都不折叠、不截断、不加 max-height**。
     窄屏最省事的做法就是把它收起来，而它恰好是这套系统里最不能收的一块 ——
     下面唯一为它写的规则是「允许标签换行」，让它在 375 上读得**更**全。
   · 色板一个 token 没动。这一整块只出现结构与间距，没有一处新颜色。
   · 桌面（≥861）没有任何一条规则落到它头上，除了 .grid2 那一处修的是溢出 bug。
   ══════════════════════════════════════════════════════════════ */

/* ── 页眉控件盒 ───────────────────────────────────────────────
   业务线 / 数据源 / 经典·Agent / 真假后端 四件全局状态收进一个盒子。
   桌面下它等价于原来那一串（同样的 gap、同样的顺序、同样被 .spacer 顶到右边），
   存在的意义在窄屏：整盒可以当一个整体挪到第二行。 */
.cl-tools{display:flex;align-items:center;gap:9px;flex:none;min-width:0}

/* ── 抽屉开关与遮罩（桌面下完全不存在） ─────────────────────── */
.navtog{display:none;flex:none;width:34px;height:34px;padding:0;margin-left:-6px;
        border:1px solid var(--line-2);border-radius:var(--r-xs);background:var(--panel);
        cursor:pointer;flex-direction:column;align-items:center;justify-content:center;gap:4px}
.navtog i{display:block;width:15px;height:1.5px;border-radius:1px;background:var(--ink2)}
.navtog:hover{border-color:var(--brand)}
.navtog:hover i{background:var(--brand)}
.cl-scrim{display:none}

/* ── 横滚提示（全宽度生效） ───────────────────────────────────
   .scrollx / .atend 由 classic.js markScrollables 量出来打（只量宽度、
   不改内容）。右缘一道 inset 渐隐：inset 阴影画在容器自己的边框盒上、
   不随内容滚，所以它是「右边还有列」而不是跟着表一起跑掉的一块灰。
   滚到头就撤掉 —— 一道永远亮着的提示等于没有提示。
   下缘留一点空给常驻滚动条（上一轮已把它从「自动隐藏」改成常驻）。 */
.tblwrap.scrollx{box-shadow:inset -18px 0 14px -14px rgba(28,38,90,.28)}
.tblwrap.scrollx.atend{box-shadow:none}

@media(max-width:860px){
  /* ── 侧栏：抽屉 ────────────────────────────────────────────
     取代原来的「横向平铺」。平铺的代价是每页头顶固定丢掉 ~200px、分组标题
     必须藏掉、报表树项数不定；抽屉的代价是多点一次。窄屏上这套系统的正事
     是读表，高度比一次点击值钱。
     宽度 264px / 上限 84vw：留出右侧那一条「点空白关掉」的可触区 ——
     一个铺满整屏的抽屉，人只能去找关闭按钮。 */
  .cl-side{position:fixed;top:0;left:0;bottom:0;z-index:60;width:264px;max-width:84vw;
           max-height:100vh;overflow-y:auto;overscroll-behavior:contain;
           border-right:1px solid var(--line-2);box-shadow:8px 0 32px rgba(28,38,90,.16);
           transform:translateX(-100%);transition:transform var(--dur-base) var(--ease);
           padding:16px 12px 20px}
  .cl.navopen .cl-side{transform:none}
  .cl-scrim{display:block;position:fixed;inset:0;z-index:55;background:rgba(20,26,46,.42);
            opacity:0;pointer-events:none;transition:opacity var(--dur-base) var(--ease)}
  .cl.navopen .cl-scrim{opacity:1;pointer-events:auto}
  .navtog{display:flex}
  /* 抽屉里的导航项按手指的尺寸给：40px 是触摸目标的下限，原来的 34px 在
     十四项紧挨着的列表里点错的概率不低。分组标题与报表树全部回来。 */
  .cl-item{padding:10px 10px;font-size:13px;min-height:40px}
  .cl-item.tr-i{padding-top:9px;padding-bottom:9px;min-height:38px}

  /* ── 页眉：折成两行 ────────────────────────────────────────
     第一行是「你在哪」（抽屉 · 面包屑 · 星标）加身份；第二行是「你按什么口径
     在看」那四件。order:1 + flex-basis:100% 把控件盒整块推到第二行，
     用户 chip 留在第一行右端 —— 身份是最不该被挪走的一样。 */
  .cl-head{height:auto;min-height:54px;flex-wrap:wrap;padding:8px 16px;row-gap:8px}
  /* 控件盒自己也允许换行。**不做横向滚动条** —— .tf-sums / .qseed 那种横滚
     用在「一排读数」上是对的（漏看一项只是少读一个数），这四件是当前口径
     本身：把「真实后端 / 假响应」滑到屏外，人就会对着一屏数字弄不清它是真是假。
     换来的代价是 375 下页眉高三行，认了。 */
  .cl-tools{order:1;flex-basis:100%;min-width:100%;flex-wrap:wrap;row-gap:8px}
  .cl-crumb{flex:1;min-width:0}
  .starbtn{min-width:34px;min-height:34px;display:inline-flex;align-items:center;justify-content:center}
}

@media(max-width:860px){
  /* ── 触摸目标 ──────────────────────────────────────────────
     鼠标能点中 26px 高的药丸，手指点不中。下面这些只加高度不改字号 ——
     缩字号是把省地方省到读者头上（与上一轮长表整改同一条）。 */
  .filters select,.filters .fl{padding-top:7px;padding-bottom:7px}
  .chip,.pager button,.vb-go,.vb-x,.vb-add{min-height:36px;display:inline-flex;
                                           align-items:center;justify-content:center}
  .vb-go{justify-content:flex-start}
  .mode-seg button,.sttab,.segbtn button,.unitseg button,.modetog,.buchip{min-height:32px}
  .mode-seg button,.sttab{padding-top:6px;padding-bottom:6px}
  /* 可排序表头是「点一下换个序」，也要够大 —— 但列宽金贵，只加高不加宽 */
  .tbl th{padding-bottom:12px}

  /* ── 口径盒：允许标签独占一行 ───────────────────────────────
     .caliber 原来是「标签 nowrap + 正文」的一行 flex，375 下正文被挤成
     一条 200px 的窄缝，一句话拆成六行。允许换行之后标签落一行、正文占满宽。
     **仍然没有 max-height、没有折叠、没有省略号** —— 这一块只准变得更好读，
     不准变少。 */
  .caliber{flex-wrap:wrap;gap:6px 12px;padding:11px 12px}
  .caliber>b{flex-basis:100%}

  /* KPI 卡：375 下两列。auto-fit 的 168px 下限在 343 的可用宽里正好差 5px
     掉回单列 —— 七张卡竖排要滚三屏，而这一排的用处恰恰是「一眼扫完」。 */
  .kgrid{grid-template-columns:repeat(auto-fit,minmax(146px,1fr));gap:10px}
  .ktile .v{font-size:19px}
  /* 页眉软卡：22px 的左右内边距在 343 宽里占掉 13%，收一档 */
  .cl-title{padding:15px 16px;gap:10px}
  .cl-title.hero .hero-lf{padding:16px 16px 18px}
  .cl-title.hero .hero-rt{padding:12px 12px 6px}
  .hero-big{font-size:52px}
  .hero-big small{font-size:18px}
  .panel{padding:16px 14px}
  .pagecard{padding:20px 18px;margin:24px auto}
  /* 上传拖拽区：手机上不存在「拖」这个动作，把它压矮，按钮才是主角 */
  .updrop{padding:18px 14px}
  .updrop .ic{font-size:22px}
  /* 长表底部合计栏在 ≤760 已经改成静态（见上文），这里只补触摸高度 */
  .tf-sums{gap:0 14px}
}

@media(max-width:860px){
  /* ── 首列吸附 ───────────────────────────────────────────────
     原来这里硬写着权限矩阵与三大报表两张表、且只在 ≤860 生效，理由是
     「吸附单元格必须自带不透明底，而行底色有八种状态，每加一张表就要把
     它那几种底色在首列上重述一遍」。那个结构问题已经解决（行底改挂在 tr
     上的 --rowbg），吸附规则也随之改成按实测判定、与断点无关 ——
     整段搬到文末「表格渲染层」，这里只留窄屏专有的那一条列宽下限。 */
  .tbl.mtx td:first-child{min-width:132px}
  /* 结构识别确认视图：左右两栏在 ≤1080 已塌成上下（见 .upgrid）。
     这里只把「原表」那块的高度收一档 —— 上下排之后 520px 的预览会把右边
     的逐列证据推到一屏之外。 */
  .pvwrap{max-height:340px}
  .cols{max-height:none}
}

/* 375 一档：可用宽只剩 343，把工作区左右内边距再收 4px 给表让位 */
@media(max-width:430px){
  .cl-body{padding:16px 12px 44px}
  .panel{padding:15px 12px}
  .cl-head{padding:8px 12px}
  .cl-title{padding:14px 14px}
}

/* 抽屉与遮罩的过场在减弱动效下自动没有（文件上方那条 * 全局 transition:none
   已经兜住）。这里只把「抽屉从屏外滑入」这件事本身说清楚：transform 变了
   照样生效，只是瞬间到位 —— 功能不依赖动画。 */
@media(prefers-reduced-motion:reduce){
  .cl-side,.cl-scrim{transition:none}
}

/* 断点比外壳那条（860）窄：640 以上这排药丸本来就排得下一行，提前竖起来
   只会在图表上方立一根没必要的栅栏。这里改的是「排不下时怎么断」。 */
@media(max-width:640px){
  /* ── 筛选药丸：窄屏下不许被折断 ────────────────────────────
     「标签 + 下拉」是靠负 margin 拼出来的一枚连续药丸，但它是**两个** flex 项：
     宽度一不够，flex 就在两者中间断行，屏幕上出现半枚「范围」和另起一行的
     半枚「全公司（法人口径）」—— 一枚药丸被劈成两个看不出关系的方块。
     改成两列栅格：标签恒在第一列、下拉恒在第二列，一对一行，药丸永不折断。
     列间距必须是 0，否则中间那道拼缝又被 gap 顶开。 */
  .filters{display:grid;grid-template-columns:max-content minmax(0,1fr);
           column-gap:0;row-gap:8px;align-items:stretch}
  .filters .fl{margin-right:0;display:flex;align-items:center}
  .filters select{width:100%}
  /* 元/万元这类分段按钮按自己的内容收宽：拉满第二列会在右边留出一段
     带边框的空槽，看着像少了一个按钮 */
  .filters .unitseg{justify-self:start}
  .fclear{grid-column:1/-1;justify-self:start;padding-left:0}
  /* 页眉软卡里的筛选区是 flex 项，竖起来之后按内容收宽只占右半边，左边空一大块。
     让它整行占满 —— 药丸拉长的是下拉那一列，读得到的取值反而更长。 */
  .cl-title>.filters{flex:1 1 100%}
}

/* 上一轮那两条权宜之计（.tbl.src/.sy-bat/.sy-src 的 min-width:840px 横滚、
   .npc-plot 的 min-width:560px 横滚）已经撤掉，换成本文件末尾「叙述表与图表
   窄屏」那一块的两个真解：表换形态、图抽标签。 */
@media(max-width:860px){
  /* 叙述型表的注记在窄屏不再限宽：340/360px 的 max-width 是给桌面多列并排
     定的，卡片形态下一行就是一整张卡，限宽只会让说明提前断行。 */
  .tbl.src .note,.tbl.sy-bat .note,.tbl.sy-src .note{max-width:none}
}

@media(max-width:640px){
  /* ── 一行三段的小标题在 325px 里会被挤成竖条 ────────────────
     「T+1 异常预警 · 说明 · 严重N 提醒N」是一条 baseline 对齐的 flex，
     宽度不够时 flex 先压缩第一项，于是标题本身被压成四个字一列的竖条。
     改成允许换行、标题与计数各自不缩：标题一行、说明一行、计数一行。 */
  .al-head{flex-wrap:wrap;row-gap:3px}
  .al-head>b,.al-head .al-count{flex:none}
  .al-head .hint{flex:1 1 100%}
  .al-count{margin-left:0}
  /* 结论句在窄屏收半档：16.5px 在 325 宽里一行只有 19 个字，
     断句太碎；15px 一行 21 个字，仍然是整页第二大的字。 */
  .al-say{font-size:15px}
  /* 同样被挤成竖条的几处一行三段 */
  .panel h3,.sys-hd,.recon,.sy-lead,.auditbar{flex-wrap:wrap}
  .cmt-hd,.rcard .hd,.mcard .hd,.pd-t{flex-wrap:wrap}
  .stbar{flex-wrap:wrap;row-gap:8px}
}

/* ══ 三因子下钻 ══════════════════════════════════════════════════
   这一块只有一个视觉任务：让「子项加起来等于上一层」一眼可验。
   所以版式的重心全押在**表尾三行**上 —— 本层合计 / 上一层 / 差额。
   三行必须与明细行分得开（否则「上一层」会被读成第六个大区），
   又必须彼此分得开（合计与上一层是同一组数的两个来源，差额是结论）。
   做法：明细行白底 → 合计行琥珀软底（与既有 rv-total 同一套语汇）→
   上一层灰底 → 差额行靛蓝细边，✓ 绿 ✗ 红，是全表唯一的判定色。

   「收入变动」那一列（rv-dcol）加一条左细线：它与三个因子不是同一类东西
   （它是行向恒等式的右端，不是第四个因子），不划一条线读者会顺手把四列
   一起横着加。理由与因子表里残差行不能长得像因子行完全一样。
   ══════════════════════════════════════════════════════════════ */
.rv-crumb{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-bottom:var(--sp-3)}
.rv-crumb .spacer{flex:1 1 auto}
.rv-crumb .fl{font-size:11.5px;color:var(--ink3)}
.rv-crumb select{padding:5px 9px;border:1px solid var(--line-2);border-radius:var(--r-xs);
                 background:#fff;color:var(--ink);font-size:12.5px}
.rv-crumb .rv-sep{color:var(--ink3);font-size:12px}
.rv-bc{border:1px solid var(--line-2);background:var(--panel);color:var(--ink2);
       border-radius:var(--r-xs);padding:4px 10px;font-size:12px;cursor:pointer}
.rv-bc:hover{border-color:var(--brand-border);color:var(--brand);background:var(--brand-soft)}
/* 当前层不是按钮：它是「你在这儿」，点它没有动作，做成按钮是骗点击 */
.rv-bc.cur{cursor:default;background:var(--brand-soft);border-color:var(--brand-border);
           color:var(--brand);font-weight:600}
.rv-bc.cur:hover{background:var(--brand-soft)}

/* 成员名上的「钻」：整行可点会与表格排序、文本选择打架，只让名字可点 */
.rv-go{border:0;background:none;padding:0;font:inherit;color:var(--brand);
       cursor:pointer;text-align:left;display:inline-flex;align-items:center;gap:5px}
.rv-go:hover{text-decoration:underline}
.rv-go-i{font-size:10px;font-weight:600;color:var(--brand);background:var(--brand-soft);
         border:1px solid var(--brand-border);border-radius:var(--r-pill);padding:0 5px;line-height:1.7}
.rv-drill-tbl tr.rv-merged td{background:var(--panel-2);color:var(--ink2)}

/* 「收入变动」列：与三个因子之间划一条线，它不是第四个因子 */
.rv-drill-tbl td.rv-dcol,.rv-drill-tbl th.rv-dcol{border-left:1px solid var(--line-2)}

/* 表尾三行 —— 这一块的立论点 */
.rv-drill-tbl tfoot tr.rv-total td{background:var(--warn-soft);font-weight:600}
.rv-drill-tbl tfoot tr.rv-total td:first-child{box-shadow:inset 3px 0 0 var(--warn)}
.rv-drill-tbl tfoot tr.rv-parent td{background:var(--panel-2);color:var(--ink2)}
.rv-drill-tbl tfoot tr.rv-parent td:first-child{box-shadow:inset 3px 0 0 var(--ink3)}
.rv-drill-tbl tfoot tr.rv-check td{background:var(--brand-soft);border-top:1px solid var(--brand-border)}
.rv-drill-tbl tfoot tr.rv-check td:first-child{box-shadow:inset 3px 0 0 var(--brand);font-weight:600}
.rv-ck{font-family:var(--mono);font-variant-numeric:tabular-nums}
.rv-ck.ok{color:var(--good)}
.rv-ck.bad{color:var(--bad);font-weight:600}

@media(max-width:900px){
  /* 六列在窄屏一定横滚（markScrollables 会挂提示）。这里只保证列不被压扁到
     数字换行 —— 金额换行之后等宽对齐就白做了。 */
  .rv-drill-tbl{min-width:720px}
}

/* ══ 叙述表与图表窄屏 ══════════════════════════════════════════
   上一轮窄屏整改留下的两条权宜之计，这一块把它们换成真解。

   ① **叙述型表在窄屏换形态，不是横滚。**
      账表和叙述表根本不是一回事：账表一格一个数，要对齐着扫，横滚只是
      「先读前几列」；叙述表一格是一整段话（表的用途说明、阻塞原因、口径
      注记、字段映射），横着排本来就别扭 —— 上一轮给它们钉 min-width:840px
      让它老实横滚，是在把「排不下」翻译成「请横着找」。
      现在四张叙述表（数据接入全景的源表清单与宽表列血缘、同步运行台的真实
      批次与上游表接入状态）在 ≤860 换成一行一张卡、字段名与值上下排。
      · 阈值取 860 不是另拍的：外壳在这一档已经判定「窄」（侧栏收成抽屉、
        页眉折两行），可用内容宽从此 ≤828，恒小于这几张表读得成句所需的 840 ——
        也就是说 860 以下表格形态**必然**失败，861 以上原样是表，桌面零改动。
      · 换形态用的是**同一份 DOM**（display 切换 + td[data-l] 出字段名），
        不另写一套卡片渲染函数。信息少一格是改渲染时就看得见的；两套渲染
        只要有人改了一处，另一处就会悄悄少一格，而且没人会发现。
      · 状态语义一条不丢：失败批次、未接入表、无来源列的整行标色改成整张卡
        标色，必需/可选徽章、SLA 徽章、未覆盖列的红 code 全部原样在卡里。
      · 真实批次表的两列可排序表头在卡片形态下会随 thead 一起消失，所以它的
        表头单独留成一排「排序」药丸 —— 换形态不该顺手把交互也换没了。

   ② **图表标签按可用宽度抽稀，不是横滚。**
      抽稀逻辑全部在 chart.js（按字宽估密度、瀑布段名错行、柱顶数值贪心去重、
      轴上告示折行不截断），这里只负责撤掉旧的 .npc-plot{min-width:560px} 与
      那圈横向滚动条，并且把读数卡放开 —— 抽掉的标签要靠它读回来，它自己
      再截断就等于真的把数弄丢了。

   色板一个 token 没动；口径盒（.caliber）本块一个字没碰，任何宽度下仍然
   完整展示。新增规则里没有任何 transition / animation，
   prefers-reduced-motion 分支因此无需增补（图层原有的两条仍在上文生效）。
   ══════════════════════════════════════════════════════════════ */

@media(max-width:860px){
  .tbl.narrc,.tbl.narrc>tbody{display:block;width:100%}
  .tbl.narrc>thead{display:none}

  /* 一行一张卡。卡内字段走 auto-fit 栅格而不是死板的单列：768 一档能排三列，
     375 自然掉回单列 —— 八个字段全部竖排会让一张卡高过一屏，读者滚完一张卡
     就忘了它是哪张表的。字段名恒在值的正上方，两者永不左右分家。 */
  .tbl.narrc>tbody>tr{display:grid;grid-template-columns:repeat(auto-fit,minmax(158px,1fr));
                      gap:0 14px;align-content:start;
                      border:1px solid var(--line);border-radius:var(--r-sm);
                      background:var(--panel);margin-bottom:10px;padding:12px 13px 3px}
  .tbl.narrc>tbody>tr:last-child{margin-bottom:0}
  .tbl.narrc>tbody>tr>td{display:block;min-width:0;padding:0 0 10px;border-bottom:0;
                         text-align:left;white-space:normal;vertical-align:top;
                         background:none;font-family:inherit;font-size:12.5px;line-height:1.7}
  .tbl.narrc>tbody>tr>td.mono,.tbl.narrc>tbody>tr>td.tnum{font-family:var(--mono);font-size:11.5px}
  /* 字段名：小、灰、加字距，压在值上面一行。字体栈在这里重写一遍是因为
     .mono / .tnum 那两格的 td 已经是等宽字体，::before 会继承过去 ——
     一排字段名里混两个等宽的「耗时 ms」，比多写一行样式难看得多。 */
  .tbl.narrc>tbody>tr>td[data-l]::before{content:attr(data-l);display:block;
      font:600 9.5px/1.5 -apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;
      letter-spacing:.08em;color:var(--ink3);margin-bottom:2px}
  /* 首格是卡的抬头（表名 / 列名 / 任务名）：它自己就是主语，不需要字段名，
     独占整行并压一道分隔线 —— 卡与卡之间靠这一行认边界。 */
  .tbl.narrc>tbody>tr>td.nc-hd{grid-column:1/-1;font-size:13.5px;
      padding-bottom:9px;margin-bottom:10px;border-bottom:1px solid var(--line)}
  .tbl.narrc>tbody>tr>td.nc-hd b{font-size:13.5px;font-weight:650}
  /* 整段话与整排字段映射独占一行：它们正是这几张表最该被读走的一格，
     挤进 158px 的栅格列里等于回到原来的问题。 */
  .tbl.narrc>tbody>tr>td.nc-full{grid-column:1/-1}
  .tbl.narrc .note{max-width:none;margin-top:3px}
  .tbl.narrc .sy-blk{max-width:none}

  /* 行状态 → 卡状态。td 背景一律撤空（否则一格一块底色，卡里出现横条），
     颜色改画在卡本身上；三条各自的选择器权重都压得过原来的行底色规则。 */
  .tbl.narrc>tbody>tr.fail,.tbl.narrc>tbody>tr.uncov{background:var(--deny-soft);border-color:var(--deny-line)}
  .tbl.narrc>tbody>tr.fail>td,.tbl.narrc>tbody>tr.uncov>td{background:none}
  /* 未接入不是故障：压灰而不标红，与上文运行台那条纪律一致 */
  .tbl.narrc>tbody>tr.off{background:var(--panel-2);border-color:var(--line-2)}
  .tbl.narrc>tbody>tr.off>td{background:none}

  /* 真实批次表：卡片形态下把可排序表头单独留成一排药丸 */
  .tbl.sy-bat.narrc>thead{display:block}
  .tbl.sy-bat.narrc>thead>tr{display:flex;flex-wrap:wrap;align-items:center;gap:7px;
                             padding:0 0 11px;font-size:11px;color:var(--ink3)}
  .tbl.sy-bat.narrc>thead>tr::before{content:'排序';letter-spacing:.08em}
  .tbl.sy-bat.narrc>thead>tr>th{display:none}
  .tbl.sy-bat.narrc>thead>tr>th.s{display:inline-flex;align-items:center;min-height:32px;
      padding:5px 12px;border:1px solid var(--line-2);border-radius:var(--r-pill);
      background:var(--panel);text-align:left}
}

@media(max-width:640px){
  /* 读数卡：图上抽掉的标签全靠它读回来，所以它自己不许再截断。
     桌面那条 62% + 单行 nowrap 是为了不压住正在读的柱；窄屏没有「旁边」
     可让，序列名改成允许折行，宁可卡高两行也不要一个带省略号的序列名 ——
     「不含税收入 · 上年同…」和「不含税收入 · 上年预算」是两个数。 */
  .npc-read{max-width:min(300px,88%)}
  .npc-read .rw{white-space:normal;line-height:1.6;align-items:baseline}
  .npc-read .rw .nm{overflow:visible;text-overflow:clip}
  .npc-read .rw i{position:relative;top:1px}
}

/* ══ 表格渲染层 ══════════════════════════════════════════════════
   三件互相纠缠的事，根在第一件。

   ① **行底色画在 td 上，没有一层可继承的行底。**
      后果不止是「首列吸附推广不了」。实测（1280 · 总部身份）发现它在当前
      版本上就已经出错：td 层的八种底色之间只靠选择器权重排先后，而那个
      权重是各人写各人那条时顺手排出来的，没有一处是想过的 ——
        .tbl tbody tr:nth-child(even) td      (0,2,3)  斑马
        .tbl tr.pv-total td                   (0,2,2)  合计
        .tbl.dense tbody tr:nth-child(even) td (0,3,3) 长表斑马
      于是「合计 / 未覆盖 / 叠图选中」凡是落在**偶数行**上，底色就被斑马纹
      盖掉；长表（.dense）更狠，连未接入灰行、报表合计行、收入榜单的分段带
      一并盖住。一个状态色看不看得见由行号的奇偶决定，这不是取舍是 bug。
      顺带被盖掉的还有 hover：偶数行根本不响应，明细透视里可点的小计行
      有一半点上去没有反馈。

      所以底色改成挂在 tr 上的一个自定义属性 --rowbg：一行一个值、一条规则
      一个赢家，先后由这一块从上往下的顺序说了算 —— 看得见，也改得动。
      顺序：默认 → 斑马 → hover → 状态底 → 状态自己的 hover 变体。
      「状态底压过 hover」是照着原来「合计行 hover 不变色」定的：账表上
      「这一行是合计」比「鼠标现在在这儿」重要。

   ② **通用占比格是一根固定 62px 的条。** 取舍与总览那三张表一模一样
      （写在「总览版位」块里）。弹性条要有地方可弹，所以把 .mix 的列几何
      抽成 .tbl.tight，由渲染出口按「这张表里有没有占比格」自动打 ——
      收入分析与费用与预算两页因此跟着受益，两个页面函数一个字没改。

   ③ **横滚时吸附列右边露出上一列的尾巴**（「…2 亿」看着像「2 亿」）。
      判断与做法写在下面 scroll-snap 那一段，那一段也说清了它解决到哪儿、
      哪一档解决不了。
   ══════════════════════════════════════════════════════════════ */

/* ── 一层可继承的行底 ─────────────────────────────────────────
   --rowbg 挂在 tr 上，td 恒透明。td 那句 !important 是这条约束的执行机制，
   不是图省事：谁再往 td 上画一行的底色，颜色**不会生效**，而不是悄悄让
   吸附列和本行变成两个颜色 —— 前者一眼看见，后者要横滚到某一行才发现。
   下一步自然就是回到这里加一行 --rowbg。
   单元格级底色（权限矩阵那种「这一格对你不可见」）是格子的属性、不是行的
   属性，单列在最后，是这条规矩唯一的例外。 */
.tbl{--zebra:#f8f9fe}
.tbl.dense{--zebra:#f8f9fd}        /* 行距一紧串行风险回来，斑马纹补一点（见「质感整改」②） */

.tbl tbody tr{--rowbg:var(--panel)}
.tbl tbody tr:nth-child(even){--rowbg:var(--zebra)}
/* hover 压过斑马。原来压不过（斑马 0,2,3 > hover 0,2,2），偶数行整行没有
   悬停反馈 —— 一张表一半的行「点得动但看不出点得动」。 */
.tbl tbody tr:hover{--rowbg:#e7ebfd}
.tbl tbody tr.pv-click:hover{--rowbg:var(--brand-soft)}
/* 状态底压过 hover：合计行 / 分节行 / 未接入行 hover 时不变色，照旧 */
.tbl tbody tr.pv-total{--rowbg:var(--panel-2)}
.tbl tbody tr.uncov{--rowbg:var(--deny-soft)}
.tbl tbody tr.cmp-on{--rowbg:var(--brand-soft)}
.tbl.mtx tbody tr.me{--rowbg:var(--brand-soft)}
.tbl.sy-bat tbody tr.fail{--rowbg:var(--deny-soft)}
.tbl.sy-src tbody tr.off{--rowbg:var(--panel-2)}
.tbl.sttbl tbody tr.stsec{--rowbg:var(--panel)}
.tbl.sttbl tbody tr.stln.b{--rowbg:var(--panel-2)}
/* lv0 写在 b 之后：一行同时是 lv0 和 b 时按 lv0 走（原来也是这个结果，
   靠的是另一条 nth-child 规则的权重，换到这里就成了一句能读的先后） */
.tbl.sttbl tbody tr.stln.lv0{--rowbg:var(--panel)}
.tbl.rv-tbl tbody tr.rv-resid,.tbl.rv-tbl tbody tr.rv-others{--rowbg:var(--panel-2)}
.tbl.rv-tbl tbody tr.rv-total{--rowbg:var(--warn-soft)}
.tbl.rv-tbl tbody tr.rv-band{--rowbg:var(--bg-2)}
.tbl.pvtbl tbody tr.hdr{--rowbg:var(--brand-soft)}
.tbl.pvtbl tbody tr.tot{--rowbg:var(--warn-soft)}
/* 状态自己的 hover 变体：只有叠图选中行有，原样保留 */
.tbl tbody tr.cmp-on:hover{--rowbg:#e7ebfd}

.tbl tbody tr{background:var(--rowbg)}
.tbl tbody td{background-color:transparent!important}
/* 例外：格子级底色。「不可见」这一格是格的属性不是行的属性 */
.tbl.mtx tbody td.n{background-color:var(--panel-2)!important}
.tbl.mtx tbody tr.me td.n{background-color:#d9e0fb!important}

/* ── 通用列几何 .tbl.tight ────────────────────────────────────
   原来只有总览三张表在用（写作 .tbl.mix）。两条内容：
   ① 表的外沿贴齐面板内容边（首列去左内边距、末列去右内边距）——
      表比标题多缩进 12px 是一道谁都没打算要的错位，顺手省 24px；
   ② 占比那一列 width:100%，把这一行剩下的宽度全部领走，其余各列因此停在
      自己的内容宽度上：面板从 450px 拉到 850px，多出来的 400px 全进条长。
   列序号由渲染出口量出来标 .flexcol，不再写死「末列」：费用结构表的占比在
   第三列，拆解表在第四列（带叠图开关时第五列）。 */
.tbl.tight th,.tbl.tight td{padding-left:9px;padding-right:9px}
.tbl.tight th:first-child,.tbl.tight td:first-child{padding-left:0}
.tbl.tight th:last-child,.tbl.tight td:last-child{padding-right:0}
.tbl.tight th.flexcol{width:100%}

/* ── 首列吸附：判定跟着 markScrollables 走 ────────────────────
   条件是量出来的，不是断点：**真的滚得动**、并且**首列窄到还留得下正文**
   的账表才钉（见 classic.js stickyCols）。1280 上滚得动的表和 375 上滚得动
   的表，读者的困境是同一个 —— 离开行名，右边那片数字就没有主语了。
   .stick2 是给拆解表的：它第一列是 44px 的叠图开关、行名在第二列，只钉
   第一列等于钉了一列圆点。第二列钉在哪由 --stick-x（量出来的第一列宽）给。
   只钉表头**第一行**：权限矩阵的「角色」是 rowspan=2，第二行的第一个 th
   已经是「华东大区」了，一起钉住的话横滚时大区列名会压在角色列上。 */
.tbl.stick1>tbody>tr>td:first-child,
.tbl.stick1>thead>tr:first-child>th:first-child,
.tbl.stick2>tbody>tr>td:nth-child(-n+2),
.tbl.stick2>thead>tr:first-child>th:nth-child(-n+2){position:sticky;z-index:1}
.tbl.stick1>tbody>tr>td:first-child,.tbl.stick1>thead>tr:first-child>th:first-child,
.tbl.stick2>tbody>tr>td:first-child,.tbl.stick2>thead>tr:first-child>th:first-child{left:0}
.tbl.stick2>tbody>tr>td:nth-child(2),
.tbl.stick2>thead>tr:first-child>th:nth-child(2){left:var(--stick-x,44px)}
/* 吸附格自带不透明底 —— 这正是上面那一层存在的理由：一句 var(--rowbg)，
   八种行状态自动跟着走，不必再一张表一张表地把底色重述一遍。 */
.tbl.stick1>tbody>tr>td:first-child,
.tbl.stick2>tbody>tr>td:nth-child(-n+2){background-color:var(--rowbg)!important}
.tbl.stick1>thead>tr:first-child>th:first-child,
.tbl.stick2>thead>tr:first-child>th:nth-child(-n+2){background-color:var(--panel)}

/* 吸附列右缘的界线。用 ::after 而不是 box-shadow：合计行、残差行、分段带的
   首格已经拿 inset box-shadow 画着左侧那道竖条，往同一个属性上叠就把人家
   顶掉了 —— 而那道竖条是「这不是一行数据」的唯一标记。 */
.tbl.stick1>tbody>tr>td:first-child::after,
.tbl.stick1>thead>tr:first-child>th:first-child::after,
.tbl.stick2>tbody>tr>td:nth-child(2)::after,
.tbl.stick2>thead>tr:first-child>th:nth-child(2)::after{
  content:'';position:absolute;top:0;bottom:0;right:0;width:1px;
  background:var(--line);pointer-events:none}
/* 整行一格的分节带 / 分段带（colspan）不画这道线：那一格跨满整行，
   线会落在表的最右边，成了一道没有含义的竖杠。 */
.tbl.stick1>tbody>tr>td[colspan]:first-child::after{display:none}
/* 滚起来之后再加一层很浅的投影：它不是装饰，是把滑到吸附列底下那一格的
   左缘吃掉一点 —— 见下面 ③。停在原点时撤掉，一道永远亮着的提示等于没提示
   （与 .scrollx / .atend 同一条）。 */
.tblwrap.scrolled .tbl.stick1>tbody>tr>td:first-child::after,
.tblwrap.scrolled .tbl.stick1>thead>tr:first-child>th:first-child::after,
.tblwrap.scrolled .tbl.stick2>tbody>tr>td:nth-child(2)::after,
.tblwrap.scrolled .tbl.stick2>thead>tr:first-child>th:nth-child(2)::after{
  box-shadow:5px 0 7px -2px rgba(28,38,90,.26)}

/* ── ③ 吸附列右边露出的那截尾巴 ───────────────────────────────
   病象：横滚到中途，吸附列右缘紧挨着的是上一列被切掉左半的数字，
   「14.32 亿元」剩下「2 亿元」—— 而它右对齐、等宽、看着完好，读者没有
   任何线索知道自己读的是半个数。这一条比「看不见右边还有列」严重：
   前者少读一个数，后者读到一个**错的**数。

   审计说「靠 CSS 只能加一道边界线标住」。加了，但一道线只说明「界在这儿」，
   说明不了「界那边那个数是残的」—— 读者仍然会把它当成一个完整的数。
   所以这一轮做两件事，一软一硬：

   · 软的：滚起来时吸附列右缘投一道浅影（上一段）。影子压在残缺数字的
     **左缘**上，一个左边糊掉的数字不再像一个完整的数字。它在任何滚动
     位置都成立，包括手指还按在屏幕上的时候。
   · 硬的：列级 scroll-snap。**吸附对象只挂在表头那一行的 th 上**，不是
     每一格 —— 挂每一格的话，分节带 / 分段带那种 colspan 跨满整行的格子会
     造出一个和整张表一样宽的吸附区，吸附点就散了。
     scroll-padding-left 由 JS 按吸附列的实测宽度给：这样一列停下来时，
     它的左缘正好贴在吸附列右缘上，界的那一边永远是一整列。

   做不到的那一档，说清楚：
   · 手指/滚轮**正在滚**的过程中照样看得见半列 —— scroll-snap 管的是
     停在哪儿，不管路上。这一档只有那道浅影兜着。
   · 某一列本身比「可视宽 − 吸附列宽」还宽时（数据接入全景在 375 上就是
     这样），把它整列摆进来做不到，这时不打 snapx：与其吸附到一个仍然
     露半列的位置，不如老实横滚。判定在 classic.js stickyCols 里量。
   · 减弱动效下整个关掉：snap 会在手指离开后自己挪一段视口，那正是
     prefers-reduced-motion 要避免的那种「页面自己动」。那一档退回浅影。 */
.tblwrap.snapx{scroll-snap-type:x mandatory;scroll-padding-left:var(--stick-w,0px)}
/* 挂**最后一行**表头，不是第一行：权限矩阵的表头是两层（「组织范围（行级）」
   底下才是各个大区），第一行那几格是 colspan 的组标题 —— 按组标题吸附，
   停下来时正好把「华中大区」切成「中大区」，比不吸附还糟。
   单层表头的表两者是同一行，行为不变。 */
.tblwrap.snapx>.tbl>thead>tr:last-child>th{scroll-snap-align:start}
@media(prefers-reduced-motion:reduce){
  .tblwrap.snapx{scroll-snap-type:none}
}

/* ══ 首列对齐 ═══════════════════════════════════════════════════
   账表的行首与面板标题对齐，表贴齐面板内容边。

   在这之前只有带占比条的表（.tbl.tight）是这样的 —— 它当初把首列内边距
   归零，是为了让弹性条有地方可弹，对齐只是顺带的结果。于是同一页上出现
   两种行首：费用与预算页的占比表在 0，旁边的逐月明细表在 12px。差 12px
   不足以让人说出哪里不对，但足以让整页看起来没有一根共同的竖线 —— 这正是
   「幻灯片感」最后的来源之一：每块自己排自己的。

   两类表**不参与**，都不是懒得改：

   ① 首列左缘被当作状态通道的表（.rv-tbl / .pvtbl 家族）。合计、残差、
      涨跌各有一条 box-shadow inset 色条画在首列格子里（inset 阴影画在背景
      之上、文字之下）；首列内边距归零，文字左缘正好落在格子左缘，3px 色条
      整条被压在字底下 —— 实测过，不是推测。那 12px 不是内边距，是给色条留
      的位置，所以直接排除在下面的 :not() 列表里，而不是另写一条覆盖 ——
      覆盖要跟 :not() 拼特异度（:not 里的类名是计数的），赢了也难读。

   排除列表写在 :not(:where(...)) 里而不是 :not(a):not(b):not(c)：后者每个
   类名都计一次特异度，四个排除项就把这条基础规则堆到 (0,6,3)，反过来把
   三大报表的层级缩进（.sttbl .stln.lv2>td:first-child，(0,4,1)）压掉，
   二级行会跟一级行齐平。:where() 的参数不计特异度，这条规则因此停在
   (0,2,3) —— 刚好压过 .tbl td 的默认内边距，又让所有按行类定制缩进的
   规则照常生效。
   ② 叙述型表（.narrc）。它们的列几何来自窄屏卡片化那一轮（.tblwrap 自带
      内边距 + 卡片形态的行内边距），与账表不是一套东西，硬拉齐会把卡片
      形态下的留白一起弄坏。 */
.tbl:not(:where(.tight,.narrc,.rv-tbl,.pvtbl))>thead>tr>th:first-child,
.tbl:not(:where(.tight,.narrc,.rv-tbl,.pvtbl))>tbody>tr>td:first-child,
.tbl:not(:where(.tight,.narrc,.rv-tbl,.pvtbl))>tfoot>tr>td:first-child{padding-left:0}
.tbl:not(:where(.tight,.narrc,.rv-tbl,.pvtbl))>thead>tr>th:last-child,
.tbl:not(:where(.tight,.narrc,.rv-tbl,.pvtbl))>tbody>tr>td:last-child,
.tbl:not(:where(.tight,.narrc,.rv-tbl,.pvtbl))>tfoot>tr>td:last-child{padding-right:0}

/* ══════════════════════════════════════════════════════════════
   数据集成三页：字段映射 / 主数据对照 / 数据质量
   ─────────────────────────────────────────────────────────────
   这三页的共同点是「结论必须比数字显眼」。它们不出业务数值，出的是
   对账结论、落桶承诺、校验实测值 —— 所以配色规则和账表页反过来用：
   账表页里红绿只表示涨跌、绝不做状态底色；这三页里没有涨跌，红绿黄
   全部还给状态本身（通过 / 未通过 / 只报数）。两套规则不会打架，
   因为它们从不出现在同一页上。
   ══════════════════════════════════════════════════════════════ */

/* 指路条：一句话 + 两个去处。它不是面板，只是一块软底提示，
   所以不给标题下划线，也不给 h3 的下边距。 */
.panel.xref{padding:13px 17px;background:var(--brand-soft);border-color:var(--brand-border)}
.panel.xref h3{border-bottom:0;padding-bottom:0}
.panel.xref .acts{display:flex;gap:8px;flex-wrap:wrap;margin-top:11px}

/* 只读药丸：取值域、指标名这类「一串短标签」的统一形制。
   不可点，所以不给 hover 与指针 —— 长得像按钮但点不动是最恼人的一种界面。 */
.chips{display:flex;gap:6px;flex-wrap:wrap;margin-top:2px}
.chip-ro{display:inline-flex;align-items:baseline;gap:5px;font-size:11.5px;padding:2px 9px;
         border-radius:var(--r-pill);background:var(--bg-2);color:var(--ink);border:1px solid var(--line-2)}
.chip-ro code{font-family:var(--mono);font-size:10px;color:var(--ink3)}
.chip-ro.more{background:transparent;border-style:dashed;color:var(--ink3)}

/* 缺口清单：缺列会让哪些指标算不出。整块走拒答色 ——
   它是这一页唯一一处「坏消息」，弱化它等于把这一页最有用的东西藏起来。 */
.panel.risk{background:var(--deny-soft);border-color:var(--deny-line)}
.panel.risk h3{border-bottom-color:var(--deny-line)}
.panel.risk .chip-ro{background:var(--panel);border-color:var(--deny-line);color:var(--bad)}

/* ── 字段映射 ─────────────────────────────────────────────── */
.fmtbl{border-top:1px solid var(--line)}
.fmtbl:first-child{border-top:0}
.fm-hd{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;padding:10px 14px 2px}
.fm-hd b{font-size:12.5px;font-weight:650}
.fm-hd code{font-family:var(--mono);font-size:11px;color:var(--ink3)}
.fm-hd .meta{font-size:11px;color:var(--ink3);margin-left:auto}
.tbl.fm td{white-space:normal;vertical-align:top;font-size:12.5px}
/* 上游字段名走等宽：它是要被人拿去和 SAP 数据字典逐字符比对的，
   比例字体下 VBRK-VBELN 和 VBRK-VBELM 长得一样。 */
.tbl.fm td.up,.tbl.lin td.up{font-family:var(--mono);font-size:11.5px;line-height:1.75}
.tbl.fm td.up em,.tbl.lin td.up em{display:block;font-style:normal;font-family:inherit;
                                   font-size:10.5px;color:var(--ink3);margin-top:2px}
/* 落点徽章。unknown 是唯一一个红的 —— 其余四种都是正常落点，
   给它们上色只会稀释掉那一个真正要被看见的。 */
.sink{font-size:10px;padding:1px 8px;border-radius:var(--r-pill);font-weight:600;white-space:nowrap;
      background:var(--bg-2);color:var(--ink2);border:1px solid var(--line-2)}
.sink.wide{background:var(--brand-soft);color:var(--brand);border-color:var(--brand-border)}
.sink.doc{background:var(--good-soft);color:var(--good);border-color:var(--good-line)}
.sink.gl{background:#efeafc;color:#5b49b8;border-color:#d5cbf3}
.sink.unknown{background:var(--deny-soft);color:var(--bad);border-color:var(--deny-line)}

/* ── 主数据对照 ───────────────────────────────────────────── */
.cmcards{display:grid;grid-template-columns:repeat(auto-fill,minmax(400px,1fr));gap:14px}
.cmcard{background:var(--panel-bg);box-shadow:var(--shadow-sm);border:1px solid var(--line);
        border-radius:var(--r-md);padding:16px 18px 13px}
.cmcard.broken{border-color:var(--deny-line);background:var(--deny-soft)}
.cmcard .hd{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding-bottom:11px;
            border-bottom:1px solid var(--line);margin-bottom:11px}
.cmcard .hd b{font-size:13.5px;font-weight:650;flex:1}
/* 每一行是「标签 → 内容」两栏。标签固定宽度让四张卡的行首对齐 ——
   卡片并排时，行首不齐会让人以为它们讲的不是同一组事。 */
.cm-row{display:flex;gap:12px;font-size:12px;line-height:1.8;padding:5px 0}
.cm-row>span{flex:none;width:104px;color:var(--ink3);font-size:11px;padding-top:1px}
.cm-row>div{flex:1;min-width:0;color:var(--ink)}
.cm-row code{font-family:var(--mono);font-size:11.5px;background:var(--brand-soft);color:var(--brand);
             padding:1px 6px;border-radius:3px}
.cm-row em{display:block;font-style:normal;font-size:10.5px;color:var(--ink3);margin-top:3px;line-height:1.7}
.cm-row.why>div{color:var(--ink2)}
/* 落桶策略是这张卡上唯一一条**承诺**（其余是描述），给它一道左边框和
   软底把它从描述里拎出来。 */
.cm-row.fall{margin-top:6px;padding:9px 11px;background:var(--warn-soft);border-radius:var(--r-xs);
             border-left:3px solid var(--warn)}
.cm-row.fall>span{color:#6b4a13}
.cm-row.fall>div{color:#6b4a13}
.cmcard .cm-foot{font-size:10.5px;color:var(--ink3);margin-top:11px;padding-top:9px;border-top:1px solid var(--line)}
.cmcard .bad{color:var(--bad);font-weight:600}

/* ── 数据质量 ─────────────────────────────────────────────── */
.qrules{display:flex;flex-direction:column;gap:10px}
.qrule{border:1px solid var(--line);border-left:3px solid var(--line-2);border-radius:var(--r-sm);
       padding:12px 15px;background:var(--panel)}
.qrule.ok{border-left-color:var(--good)}
.qrule.bad{border-left-color:var(--bad);background:var(--deny-soft);border-color:var(--deny-line)}
/* 实测项与跳过项都不是「成绩」，所以都不给绿也不给红。
   实测走靛蓝（有结果、只是不判成败），跳过走灰（压根没跑）。
   这两档在视觉上必须和通过项区分得开 —— 混进绿色里就是把跳过算作通过。 */
.qrule.msr{border-left-color:var(--brand);background:var(--brand-soft);border-color:var(--brand-border)}
.qrule.skip{border-left-color:var(--ink3);background:var(--panel-2)}
.q-hd{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin-bottom:8px}
.q-hd b{font-size:13px;font-weight:650}
.q-hd .spacer{flex:1}
.q-st{font-size:10px;font-weight:700;padding:2px 9px;border-radius:var(--r-pill);letter-spacing:.04em;flex:none}
.qrule.ok .q-st{background:var(--good-soft);color:var(--good);border:1px solid var(--good-line)}
.qrule.bad .q-st{background:var(--panel);color:var(--bad);border:1px solid var(--deny-line)}
.qrule.msr .q-st{background:var(--panel);color:var(--brand);border:1px solid var(--brand-border)}
.qrule.skip .q-st{background:var(--bg-2);color:var(--ink2);border:1px solid var(--line-2)}
.q-sev{font-size:10px;padding:1px 8px;border-radius:var(--r-pill);background:var(--bg-2);color:var(--ink2);flex:none}
.q-sev.block{background:var(--deny-soft);color:var(--bad);border:1px solid var(--deny-line)}
.q-sev.warn{background:var(--warn-soft);color:var(--warn);border:1px solid var(--warn-line)}
.q-act{font-size:11.5px;color:var(--ink2);white-space:nowrap}
.q-act b{font-size:14px;font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums}
.q-rule{font-size:12px;color:var(--ink);line-height:1.8;font-family:var(--mono);
        background:var(--panel-2);padding:7px 11px;border-radius:var(--r-xs);border:1px solid var(--line)}
.qrule.bad .q-rule,.qrule.msr .q-rule{background:var(--panel)}
.q-why{font-size:11.5px;color:var(--ink2);line-height:1.8;margin-top:8px}
.q-note{font-size:11px;color:var(--ink3);line-height:1.75;margin-top:5px}
.q-fail{font-size:11px;color:var(--ink2);line-height:1.75;margin-top:8px;padding-left:10px;
        border-left:2px solid var(--line-2)}
.q-fail>span{color:var(--ink3);margin-right:7px}
.q-sql{margin-top:9px}
.q-sql summary{font-size:11px;color:var(--ink3);cursor:pointer;list-style:none}
.q-sql summary::-webkit-details-marker{display:none}
.q-sql summary::before{content:'▸ ';color:var(--ink3)}
.q-sql[open] summary::before{content:'▾ '}
.q-sql pre{margin:7px 0 0;font-family:var(--mono);font-size:11px;line-height:1.75;color:var(--ink2);
           background:var(--panel-2);border:1px solid var(--line);border-radius:var(--r-xs);
           padding:10px 12px;overflow-x:auto;white-space:pre-wrap;word-break:break-word}

/* 窄屏：对照卡的标签栏折到内容上面，两栏变一栏 —— 104px 的标签栏在
   375 的框里会把内容挤成一列单字。 */
@media (max-width:640px){
  .cmcards{grid-template-columns:1fr}
  .cm-row{flex-direction:column;gap:3px}
  .cm-row>span{width:auto}
  .q-hd .q-act{width:100%;text-align:left}
}

/* ══════════════════════════════════════════════════════════════
   月度部门经营分析 + 预算管理（dept.js）

   这一组页面的版式判断只有一条：**它不是看板，是一份月结工作台**。
   所以没有一块 66px 的大数字，没有并排的同构磁贴 —— 屏幕上占地方最多的
   三样东西依次是：谁还没交（名单）、这个月的数（表）、人写的判断（正文）。
   ══════════════════════════════════════════════════════════════ */

/* 页头：左边是这一页在回答什么，右边是期间与下发。
   期间选择器与下发按钮退到右上角一条工具栏 —— 它们是工具，不是内容。 */
.dp-head{ display:flex; align-items:flex-start; gap:var(--sp-5); flex-wrap:wrap; }
.dp-head .dp-hl{ flex:1 1 320px; min-width:0; }
.dp-head .dp-hl p{ margin:var(--sp-2) 0 0; color:var(--dk-ink2); font-size:13px; line-height:1.7; max-width:72ch; }
.dp-head .dp-hr{ display:flex; align-items:center; gap:var(--sp-2); flex-wrap:wrap; }
.dp-head .fl{ font-size:12px; color:var(--dk-ink3); }

/* tab 条。状态点在切之前就看得见 —— 「还差谁」是这一页最该被一眼看到的事。
   横向可滚：十一个 tab 在窄屏上必然放不下，能选的只有折行 / 藏 / 横滚，
   藏是不许的（藏掉的那个恰恰可能是没交的那个）。 */
.dp-tabs{
  display:flex; gap:var(--sp-1); overflow-x:auto; padding:var(--sp-1) 0 var(--sp-3);
  border-bottom:1px solid var(--line-2); margin-bottom:var(--sp-4); scrollbar-width:thin;
}
.dp-tab{
  flex:0 0 auto; display:flex; flex-direction:column; align-items:flex-start; gap:2px;
  padding:var(--sp-2) var(--sp-3); border:1px solid transparent; border-radius:var(--r-xs);
  background:transparent; cursor:pointer; text-align:left; position:relative;
  font:inherit; color:var(--ink2); transition:background var(--dur-fast) var(--ease);
}
.dp-tab:hover{ background:var(--panel-2); }
.dp-tab.on{ background:var(--panel); border-color:var(--line-2); box-shadow:var(--shadow-sm); color:var(--ink); }
.dp-tab.on::after{
  content:''; position:absolute; left:var(--sp-3); right:var(--sp-3); bottom:-1px;
  height:2px; background:var(--brand); border-radius:2px;
}
.dp-tab .tx{ font-size:13px; font-weight:600; white-space:nowrap; }
.dp-tab .st{ font-size:11px; color:var(--ink3); white-space:nowrap; }
.dp-tab .dot{ position:absolute; top:8px; right:8px; width:6px; height:6px; border-radius:50%; }
.dot.todo{ background:var(--ink3); }
.dot.wait{ background:var(--warn); }
.dot.sent{ background:var(--brand); }
.dot.back{ background:var(--bad); }
.dot.done{ background:var(--good); }

.dp-back{ margin-top:var(--sp-4); }

/* 状态芯片（表格里与状态条上共用一套语汇） */
.dp-chip{
  display:inline-block; padding:2px 8px; border-radius:var(--r-pill);
  font-size:11px; font-weight:600; white-space:nowrap;
}
.dp-chip.todo{ background:var(--bg-2); color:var(--ink2); }
.dp-chip.wait{ background:var(--warn-soft); color:var(--warn); }
.dp-chip.sent{ background:var(--brand-soft); color:var(--brand); }
.dp-chip.back{ background:var(--deny-soft); color:var(--bad); }
.dp-chip.done{ background:var(--good-soft); color:var(--good); }
.dp-sec-n{ margin-left:6px; font-size:11px; color:var(--ink3); font-variant-numeric:tabular-nums; }
.dp-sec-n.gap{ color:var(--warn); font-weight:600; }

/* 对平检查条。通过时它是一行安静的说明，不通过时它必须比页面上任何数字都显眼 ——
   有笔费用没人认领的时候，先别看数。 */
.dp-recon{
  display:flex; gap:var(--sp-3); align-items:baseline; flex-wrap:wrap;
  padding:var(--sp-2) var(--sp-4); border-radius:var(--r-xs); margin-bottom:var(--sp-4); font-size:12px;
}
.dp-recon.ok{ background:var(--good-soft); color:var(--good); border:1px solid var(--good-line); }
.dp-recon.bad{ background:var(--deny-soft); color:var(--bad); border:1px solid var(--deny-line); font-size:13px; }
.dp-recon span{ color:var(--ink2); }
.dp-recon.bad span{ color:var(--bad); }

/* 进度：一排名单，不是一个分数。分数不能拿去催人。 */
.dp-prog-g{ display:grid; grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); gap:var(--sp-3); }
.dp-prog-g .pg{
  padding:var(--sp-3); border-radius:var(--r-xs); background:var(--panel-2);
  border-left:3px solid var(--ink3);
}
.dp-prog-g .pg.wait{ border-left-color:var(--warn); }
.dp-prog-g .pg.sent{ border-left-color:var(--brand); }
.dp-prog-g .pg.back{ border-left-color:var(--bad); }
.dp-prog-g .pg.done{ border-left-color:var(--good); }
.dp-prog-g .pg b{ font-size:12px; color:var(--ink2); }
.dp-prog-g .pg .n{ float:right; font-size:15px; font-weight:700; }
.dp-prog-g .pg p{ margin:var(--sp-2) 0 0; font-size:12px; line-height:1.65; color:var(--ink); }

/* 流转状态条 */
.dp-flow{
  display:grid; grid-template-columns:1fr auto; gap:var(--sp-2) var(--sp-4);
  padding:var(--sp-3) var(--sp-4); border-radius:var(--r-sm); margin-bottom:var(--sp-4);
  background:var(--panel); border:1px solid var(--line-2); border-left:4px solid var(--ink3);
}
.dp-flow.wait{ border-left-color:var(--warn); }
.dp-flow.sent{ border-left-color:var(--brand); }
.dp-flow.back{ border-left-color:var(--bad); }
.dp-flow.done{ border-left-color:var(--good); }
.dp-flow .ft b{ font-size:14px; }
.dp-flow .ft span{ margin-left:var(--sp-2); font-size:12px; color:var(--ink2); }
.dp-flow .fm{ grid-column:1; font-size:12px; color:var(--ink3); }
.dp-flow .fm .cm{ display:block; margin-top:4px; color:var(--bad); }
.dp-flow .fa{ grid-row:1/3; grid-column:2; display:flex; gap:var(--sp-2); align-items:center; flex-wrap:wrap; }

/* 关注项：现象，不是结论 —— 所以阈值原样印出来 */
.dp-flags{
  padding:var(--sp-3) var(--sp-4); border-radius:var(--r-xs); margin-bottom:var(--sp-4);
  background:var(--warn-soft); border:1px solid var(--warn-line); font-size:13px;
}
.dp-flags.none{ background:var(--panel-2); border-color:var(--line-2); color:var(--ink2); font-size:12px; }
.dp-flags b{ color:var(--warn); }
.dp-flags ul{ margin:var(--sp-2) 0 0; padding-left:1.2em; }
.dp-flags li{ margin:2px 0; }
.dp-flags p{ margin:var(--sp-2) 0 0; font-size:11.5px; }

.dp-kpis{ margin-bottom:var(--sp-4); }

/* 驱动指标。合成占位那几张带琥珀左边 —— 一个部门经营分析里最危险的东西
   不是算错的数，是看起来像业务真值的假数。 */
.dp-drv{ display:grid; grid-template-columns:repeat(auto-fit,minmax(215px,1fr)); gap:var(--sp-3); }
.dp-drv .drv{
  padding:var(--sp-3); border-radius:var(--r-xs); background:var(--panel-2);
  border:1px solid var(--line); border-left:3px solid var(--brand);
}
.dp-drv .drv.synth{ border-left-color:var(--warn); background:var(--warn-soft); }
.dp-drv .lb{ font-size:12px; color:var(--ink2); display:flex; justify-content:space-between; gap:var(--sp-2); }
.dp-drv .lb .src{ font-size:10.5px; color:var(--ink3); white-space:nowrap; }
.dp-drv .drv.synth .lb .src{ color:var(--warn); font-weight:600; }
.dp-drv .vd{ margin:var(--sp-1) 0; font-size:19px; }
.dp-drv .cf{ font-size:11.5px; color:var(--ink2); }
.dp-drv .fm{ margin-top:var(--sp-2); font-size:10.5px; line-height:1.55; color:var(--ink3); }

/* 「还原口径」「种子预算」这类标记：它们不是装饰，是一句必须跟着数字走的话 */
.seedmark{
  display:inline-block; margin-left:5px; padding:1px 5px; border-radius:var(--r-xs);
  background:var(--warn-soft); color:var(--warn); font-size:10px; font-weight:700;
  border:1px solid var(--warn-line);
}
.tbl td.bs, .tbl .bs{ font-size:11.5px; color:var(--ink3); line-height:1.55; }
.tbl .tnum.bad, .bgtbl .bad{ color:var(--bad); }

/* 复盘提醒：闭环的另一半 */
.dp-due{
  padding:var(--sp-3) var(--sp-4); border-radius:var(--r-xs); margin-bottom:var(--sp-4);
  background:var(--brand-soft); border:1px solid var(--brand-border); font-size:13px;
}
.dp-due ul{ margin:var(--sp-2) 0 0; padding-left:1.2em; }
.dp-due p{ margin:var(--sp-2) 0 0; font-size:11.5px; }

/* 章节：一份文档的节，不是五张同构卡。空位是内容，不是完成度上少的一格。 */
.dp-secs .dp-sec{ padding:var(--sp-5) 0; border-top:1px solid var(--line); }
.dp-secs .dp-sec:first-of-type{ border-top:0; padding-top:var(--sp-3); }
.dp-sec h4{ margin:0 0 var(--sp-1); font-size:15px; display:flex; align-items:baseline; gap:var(--sp-2); }
.dp-sec h4 .no{
  display:inline-flex; align-items:center; justify-content:center; min-width:22px; height:22px;
  border-radius:var(--r-xs); background:var(--brand-soft); color:var(--brand); font-size:12px;
}
.dp-sec h4 .st{ margin-left:auto; font-size:11px; font-weight:500; }
.dp-sec h4 .st.done{ color:var(--good); }
.dp-sec h4 .st.gap{ color:var(--warn); }
.dp-sec .focus{ margin:0 0 var(--sp-3); font-size:12px; color:var(--ink3); }
.dp-sec .body p{ margin:0 0 var(--sp-2); font-size:13.5px; line-height:1.85; }
.dp-sec .pact{
  margin-top:var(--sp-2); padding:var(--sp-2) var(--sp-3); border-left:2px solid var(--ink);
  background:var(--panel-2); font-size:12.5px; border-radius:0 var(--r-xs) var(--r-xs) 0;
}
.dp-sec .pact.none{ border-left-color:var(--line-2); color:var(--ink3); }
.dp-sec .pact em{ font-style:normal; font-weight:600; }
.dp-sec .by{ margin:var(--sp-2) 0 0; font-size:11.5px; color:var(--ink3); text-align:right; }
.dp-sec .by .draft{ color:var(--warn); }
.dp-sec .gapbox{
  padding:var(--sp-4); border:1px dashed var(--warn-line); border-radius:var(--r-xs);
  background:var(--warn-soft);
}
.dp-sec .gapbox b{ color:var(--warn); font-size:13px; }
.dp-sec .gapbox p{ margin:var(--sp-2) 0 var(--sp-3); font-size:12.5px; line-height:1.7; color:var(--ink2); }
.dp-in{
  width:100%; padding:var(--sp-3); border:1px solid var(--line-2); border-radius:var(--r-xs);
  font:13.5px/1.8 inherit; resize:vertical; background:var(--panel); color:var(--ink);
}
.dp-in:focus{ outline:2px solid var(--brand-border); outline-offset:1px; }
.dp-loop{ display:flex; gap:var(--sp-3); flex-wrap:wrap; margin:var(--sp-2) 0; }
.dp-loop label{ display:flex; align-items:center; gap:6px; font-size:12px; color:var(--ink2); flex:1 1 220px; }
.dp-loop input{
  flex:1; min-width:0; padding:6px 8px; border:1px solid var(--line-2);
  border-radius:var(--r-xs); font:12.5px inherit; background:var(--panel); color:var(--ink);
}
/* 初稿说明：它必须比初稿正文更醒目一点 —— 一段编得像模像样、但归因是猜的
   经营分析，比一段空白危险得多。 */
.dp-draft{
  padding:var(--sp-3) var(--sp-4); margin-bottom:var(--sp-2); border-radius:var(--r-xs);
  background:var(--warn-soft); border:1px solid var(--warn-line); font-size:12px; line-height:1.7;
}
.dp-draft b{ color:var(--warn); }
.dp-draft p{ margin:var(--sp-1) 0 0; color:var(--ink2); }
.dp-draft .gaps{ color:var(--warn); font-weight:600; }

/* 展开线说明：一条线管五节，它必须印在这五节的上面，不能只藏在 title 里 */
.dp-focusbar{
  display:flex; gap:var(--sp-3); align-items:baseline; flex-wrap:wrap;
  padding:var(--sp-2) var(--sp-3); margin-bottom:var(--sp-2);
  border-radius:var(--r-xs); background:var(--panel-2); border:1px solid var(--line);
  font-size:12px; line-height:1.7;
}
.dp-focusbar b{ white-space:nowrap; }
.dp-focusbar span{ flex:1 1 320px; min-width:0; color:var(--ink2); }

/* 差异徽标：这一节盯的差异 + 它现在是多少。三档三个颜色 ——
   重点是要办的事（醒目），小差异是背景（安静），算不出是个问题（点出来）。 */
.vchip{
  display:inline-flex; align-items:baseline; gap:5px; padding:1px 8px;
  border-radius:999px; font-size:11.5px; font-weight:500; white-space:nowrap;
  border:1px solid transparent;
}
.vchip.key{ background:var(--warn-soft); border-color:var(--warn-line); color:var(--warn); }
.vchip.minor{ background:var(--panel-2); border-color:var(--line-2); color:var(--ink3); }
.vchip.unk{ background:var(--panel-2); border-color:var(--line-2); color:var(--ink3); }
.vchip .wy{ color:var(--ink3); font-weight:400; }
.dp-fold{
  margin-left:var(--sp-2); padding:1px 8px; border:1px solid var(--line-2);
  border-radius:999px; background:var(--panel); color:var(--ink2);
  font:11.5px inherit; cursor:pointer;
}
.dp-fold:hover{ border-color:var(--brand-border); color:var(--brand); }
/* 折叠态：**不是隐藏**。差异、状态、这一节要回答什么都还在，
   收起来的只有正文与编辑框。 */
.dp-secs .dp-sec.fold{ padding:var(--sp-3) 0; }
.dp-sec.fold .focus{ display:none; }
.dp-sec .foldnote{ margin:2px 0 0 30px; font-size:11.5px; color:var(--ink3); line-height:1.7; }

/* 下钻卡片：差异是从哪一格来的。里面一个数都不是这里算的。 */
.dp-drill{
  margin:0 0 var(--sp-3); padding:var(--sp-3) var(--sp-4);
  border:1px solid var(--brand-border); border-radius:var(--r-xs);
  background:var(--brand-soft); font-size:12.5px;
}
.dp-drill .dh{ display:flex; gap:var(--sp-2); align-items:baseline; flex-wrap:wrap; }
.dp-drill .dh b{ font-size:13px; }
.dp-drill .dh .hint{ flex:1 1 240px; min-width:0; font-size:11.5px; color:var(--ink3); }
.dp-drill .dlayer{ margin-top:var(--sp-3); }
.dp-drill h5{ margin:0 0 var(--sp-2); font-size:12.5px; font-weight:600; }
.dp-drill .tblwrap{ background:var(--panel); border-radius:var(--r-xs); }
.dp-drill .dim, .dp-drill .gaps{ margin:var(--sp-1) 0 0; font-size:11.5px; line-height:1.7; }
.dp-drill .gaps{ color:var(--warn); font-weight:600; }
.dp-drill .dbody{ margin-top:var(--sp-3); }
.dp-drill .dbody pre{
  margin:var(--sp-1) 0 var(--sp-2); padding:var(--sp-3); white-space:pre-wrap;
  background:var(--panel); border:1px solid var(--line); border-radius:var(--r-xs);
  font:12.5px/1.85 inherit; color:var(--ink);
}
/* 行标记：超支 / 节约 / 合计 / 占位 —— 与页面其余各表同一套语义色 */
.dp-drill .dl-over td{ color:var(--bad); }
.dp-drill .dl-under td{ color:var(--good); }
.dp-drill .dl-total td{ font-weight:600; border-top:1px solid var(--line-2); }
.dp-drill .dl-synth td:first-child{ color:var(--warn); }
.dp-drill .dl-key td:first-child{ font-weight:600; }

/* 报告出口 */
.dp-report{
  display:flex; gap:var(--sp-4); align-items:center; justify-content:space-between;
  flex-wrap:wrap; padding:var(--sp-4); margin:var(--sp-4) 0;
  border-radius:var(--r-sm); background:var(--panel); border:1px solid var(--line-2);
  box-shadow:var(--shadow-sm);
}
.dp-report .rl{ flex:1 1 340px; min-width:0; }
.dp-report .rl b{ font-size:14px; }
.dp-report .rl p{ margin:var(--sp-1) 0 0; font-size:12.5px; line-height:1.7; color:var(--ink2); }
.dp-report .ra{ display:flex; gap:var(--sp-2); flex-wrap:wrap; }

/* 预算编制表：12 列 + 科目列，必然要横滚 */
.bg-pick{ display:flex; align-items:center; gap:var(--sp-2); flex-wrap:wrap; margin-bottom:var(--sp-3); }
.bg-pick select{ max-width:230px; }
.bgtbl td:first-child{ min-width:160px; }
.bgtbl .bgcell{
  width:76px; padding:4px 6px; text-align:right; border:1px solid var(--line-2);
  border-radius:var(--r-xs); font:12.5px var(--mono); background:var(--panel); color:var(--ink);
}
.bgtbl .bgcell:focus{ outline:2px solid var(--brand-border); outline-offset:1px; }

@media (max-width:860px){
  .dp-flow{ grid-template-columns:1fr; }
  .dp-flow .fa{ grid-row:auto; grid-column:1; }
}
/* KPI 卡上的对比数：整块不换行，行内自己折 —— 「同比 +3.41%」被折成
   「同」「比 +3.41%」两行，是窄卡片上最难看也最常见的一种碎裂。 */
.kpi .d{ display:flex; flex-wrap:wrap; gap:2px 10px; }
.kpi .d .cp{ white-space:nowrap; }
.dp-kpis .kpi .v{ font-size:17px; }
.dp-kpis .kpi .v b.tnum{ font-weight:600; }
/* 面板标题右侧的动作位。h3 是一行「这块是什么 + 一句口径」，动作贴右端 ——
   摆在面板下方会离它所属的那张表太远，摆在页头又会和期间选择器混成一排。 */
.panel h3 .h3act{ margin-left:auto; display:flex; gap:var(--sp-2); }
/* 合计行与「当前生效版本」那一行。
   注意别借用 .gt —— 它在这套 CSS 里是引导提示卡（display:flex），
   挂到 <tr> 上会让整行塌成一个 flex 容器，列宽全乱。 */
.tbl tr.dp-total td{ font-weight:700; background:var(--panel-2); border-top:1px solid var(--ink); }
.tbl tr.dp-live td{ background:var(--good-soft); }
.tbl tr.dp-live td:first-child{ box-shadow:inset 3px 0 0 var(--good); }
/* 版本表的「说明」列：种子版本那段声明很长，不限宽会把前面几列挤扁 */
.tbl td.bs{ max-width:260px; }

/* ══════════════════════════════════════════════════════════════
   会计期间选择器 / 选项选择器（pick.js）

   为什么值得为它单开一块：原来这里是一个裸 <select>，19 个 YYYY-MM 铺成
   一条长条 —— 年这一层信息被压掉了，而财务找期间是先想年、再想月。
   十二宫格把它还回来，代价是一块自绘弹层要自己负责焦点、定位与减弱动效。

   配色一个新变量都没引：触发器沿用 .filters select 那一档（浅底 + 靛蓝描边），
   选中格是 --brand 实色，「最新已结账」那一格只加一圈环。红绿在这套系统里
   只表示涨跌，所以选择器上一点红绿都没有。
   ══════════════════════════════════════════════════════════════ */
.npk{ display:inline-flex; align-items:stretch; vertical-align:middle; }
.npk-btn{
  display:inline-flex; align-items:baseline; gap:7px; font:inherit; font-size:12.5px;
  padding:5px 10px; border:1px solid var(--brand-border); background:var(--panel);
  color:var(--ink); border-radius:var(--r-xs); cursor:pointer;
  transition:border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.npk-btn:hover{ border-color:var(--brand); background:var(--brand-soft); }
.npk-btn[aria-expanded="true"]{ border-color:var(--brand); background:var(--brand-soft); }
.npk-btn .npk-v{ font-weight:650; }
.npk-btn .npk-v.mono{ font-family:var(--mono); font-variant-numeric:tabular-nums; }
.npk-btn .npk-n{ font-size:11px; color:var(--ink3); }
.npk-btn .npk-c{
  align-self:center; width:0; height:0; margin-left:1px;
  border:4px solid transparent; border-top-color:var(--ink3); transform:translateY(2px);
}
.npk-btn[aria-expanded="true"] .npk-c{ border-top-color:var(--brand); }
/* 步进键：这一页最频繁的动作是「往前翻一个月」，它该是一次点击。
   与触发器拼成一枚控件（负 margin 抵掉圆角接缝），不是三个散按钮。 */
.npk-step .npk-arw{
  font:inherit; font-size:14px; line-height:1; width:26px; cursor:pointer; color:var(--ink2);
  border:1px solid var(--brand-border); background:var(--panel); padding:0;
}
.npk-step .npk-arw:first-child{ border-radius:var(--r-xs) 0 0 var(--r-xs); border-right:0; }
.npk-step .npk-arw:last-child{ border-radius:0 var(--r-xs) var(--r-xs) 0; border-left:0; }
.npk-step .npk-btn{ border-radius:0; }
.npk-step .npk-arw:hover:not(:disabled){ background:var(--brand-soft); color:var(--brand); border-color:var(--brand); }
.npk-step .npk-arw:disabled{ color:var(--line-2); cursor:default; }

.npk-pop{
  position:fixed; z-index:9000; min-width:246px; max-width:min(92vw,340px);
  background:var(--panel); border:1px solid var(--line-2); border-radius:var(--r-sm);
  box-shadow:var(--shadow-md); padding:var(--sp-3);
  opacity:0; transform:translateY(-4px); transition:opacity 120ms var(--ease), transform 120ms var(--ease);
}
.npk-pop.on{ opacity:1; transform:none; }
.npk-hd{ display:flex; align-items:center; justify-content:space-between; margin-bottom:var(--sp-2); }
.npk-hd.one{ justify-content:flex-start; }
.npk-hd b{ font-size:12.5px; font-weight:650; }
.npk-yr{
  font:inherit; font-size:14px; line-height:1; width:24px; height:24px; cursor:pointer;
  border:1px solid var(--line-2); background:var(--panel); border-radius:var(--r-xs); color:var(--ink2);
}
.npk-yr:hover:not(:disabled){ border-color:var(--brand); color:var(--brand); background:var(--brand-soft); }
.npk-yr:disabled{ color:var(--line-2); border-color:var(--line); cursor:default; }
.npk-grid{ display:grid; grid-template-columns:repeat(4,1fr); gap:var(--sp-1); }
.npk-cell{
  font:inherit; font-size:12.5px; padding:7px 0; cursor:pointer; text-align:center;
  border:1px solid transparent; border-radius:var(--r-xs); background:var(--panel-2); color:var(--ink);
  font-variant-numeric:tabular-nums;
}
.npk-cell:hover:not(:disabled){ background:var(--brand-soft); color:var(--brand); }
/* 不在已结账期间轴上的月：**留在格子里但不可点**，不隐藏 ——
   「9 月怎么没了」比「9 月是灰的」更让人停手。理由挂在 title 上。 */
.npk-cell:disabled{ background:transparent; color:var(--ink3); opacity:.42; cursor:default;
                    text-decoration:line-through; text-decoration-thickness:1px; }
.npk-cell.last:not(.on){ box-shadow:inset 0 0 0 1px var(--brand-border); }
.npk-cell.on{ background:var(--brand); color:#fff; font-weight:650; }
.npk-ft{ display:flex; flex-wrap:wrap; gap:var(--sp-1); margin-top:var(--sp-3);
         padding-top:var(--sp-3); border-top:1px solid var(--line); }
.npk-q{
  font:inherit; font-size:11.5px; display:inline-flex; align-items:baseline; gap:5px;
  padding:4px 9px; cursor:pointer; color:var(--ink2);
  border:1px solid var(--line-2); border-radius:var(--r-pill); background:var(--panel);
}
.npk-q em{ font-style:normal; font-size:11px; color:var(--ink3); }
.npk-q:hover{ border-color:var(--brand); color:var(--brand); background:var(--brand-soft); }
.npk-q:hover em{ color:var(--brand); }
.npk-hint{ margin:var(--sp-2) 0 0; font-size:11px; line-height:1.7; color:var(--ink3); }

.npk-list{ display:flex; flex-direction:column; gap:1px; max-height:52vh; overflow-y:auto; }
.npk-row{
  font:inherit; font-size:12.5px; display:grid; grid-template-columns:16px 1fr auto;
  align-items:baseline; gap:8px; text-align:left; padding:7px 8px; cursor:pointer;
  border:0; border-radius:var(--r-xs); background:transparent; color:var(--ink); width:100%;
}
.npk-row:hover:not(:disabled){ background:var(--brand-soft); }
.npk-row.on{ background:var(--brand-soft); color:var(--brand); font-weight:600; }
.npk-row .tk{ color:var(--brand); font-size:11px; }
.npk-row .nt{ font-size:11px; color:var(--ink3); }
.npk-row:disabled{ color:var(--ink3); cursor:default; opacity:.6; }
@media (prefers-reduced-motion:reduce){
  .npk-pop{ transition:none; opacity:1; transform:none; }
}

/* ══════════════════════════════════════════════════════════════
   部门经营分析：图、内嵌条、涨跌图例（dept.js 新增部分）

   这一页原来一张图都没有。加图不是为了好看 —— 是因为「毛利率 −1.47pt
   该不该写进风险」这个判断，单期的一屏数回答不了：它取决于这是从平线上
   掉下来的一次，还是已经连掉四个月。图把那个判断变得做得出来。

   版位纪律：**图长在它解释的那张表上面，不另开一个「图表区」**。
   图表区是仪表盘的做法，这一页不是仪表盘，是一份边看边写的材料 ——
   把图和它的表拆到两处，人就得来回滚。
   ══════════════════════════════════════════════════════════════ */
.dp-figs{ display:grid; grid-template-columns:repeat(auto-fit,minmax(330px,1fr));
          gap:var(--sp-4); margin-bottom:var(--sp-4); }
.dp-figs:empty{ display:none; margin:0; }
.dp-fig{ min-width:0; border:1px solid var(--line); border-radius:var(--r-sm);
         background:var(--panel-2); padding:var(--sp-3) var(--sp-3) var(--sp-2); }
.dp-fig .fg-t{ display:flex; flex-wrap:wrap; align-items:baseline; gap:var(--sp-2);
               margin-bottom:var(--sp-2); }
.dp-fig .fg-t b{ font-size:12.5px; font-weight:650; color:var(--ink); }
.dp-fig .fg-t span{ font-size:11px; color:var(--ink3); line-height:1.6; }
.dp-fig .npc{ margin:0; }

/* 涨跌图例。整页只印一次；两枚色样自己就是那两个类的样本，
   不再另画一个色块 —— 图例最该长得像它解释的那个东西。 */
.dp-polar{
  display:flex; flex-wrap:wrap; align-items:baseline; gap:6px 14px;
  margin:0 0 var(--sp-4); padding:9px 14px; font-size:11.5px; line-height:1.75;
  background:var(--panel); border:1px solid var(--line); border-radius:var(--r-sm);
  color:var(--ink2);
}
.dp-polar b{ font-size:12px; color:var(--ink); font-weight:650; }
.dp-polar .up,.dp-polar .down{ font-weight:600; white-space:nowrap; }
.dp-polar .up::before{ content:'▲ '; }
.dp-polar .down::before{ content:'▼ '; }
.dp-polar em{ flex:1 1 320px; min-width:0; font-style:normal; color:var(--ink3); font-size:11px; }

/* 带色的差异数。色之外永远还有 + / − 符号（signed 恒出）——
   黑白打印、色觉障碍、强制配色下这一屏的信息量不减。
   下划虚线是「这里有话可问」的提示：悬停给出判断口径。 */
.dlt{ font-weight:650; }
.dlt.up{ color:var(--good); }
.dlt.down{ color:var(--bad); }
.dlt.flat{ color:var(--ink3); }
.dlt[title]{ text-decoration:underline dotted rgba(139,147,173,.5); text-underline-offset:3px; }

/* 表格内嵌条。给两三行的表配饼图是浪费一整块版面；条长在它解释的那一行上，
   而且长度不依赖颜色 —— 经营分析材料十有八九是黑白打出来上会的。 */
.dp-bar{ display:flex; align-items:center; gap:7px; justify-content:flex-end; }
.dp-bar i{ flex:1 1 auto; min-width:24px; max-width:78px; height:6px; border-radius:3px;
           background:var(--bg-2); overflow:hidden; }
.dp-bar i b{ display:block; height:100%; border-radius:3px; background:var(--pg-ultra); }
.dp-bar em{ font-style:normal; font-size:11.5px; color:var(--ink2); min-width:40px; text-align:right; }

/* 执行率量表：刻线就是预算 100%，超出的一段染红。
   0–150% 映射满宽，>150% 顶格并把真值挂在 title 上 —— 一根撑出格子的条
   会把「超了一点」和「超了三倍」画成同一个样子。 */
.dp-rt{ display:inline-flex; flex-direction:column; align-items:flex-end; gap:3px; }
.dp-gauge{ display:block; width:76px; }
.dp-gauge i{ display:block; position:relative; height:5px; border-radius:3px;
             background:var(--bg-2); overflow:hidden; }
.dp-gauge i::after{ content:''; position:absolute; left:66.6%; top:-2px; bottom:-2px;
                    width:1px; background:var(--ink3); }
.dp-gauge i b{ display:block; height:100%; border-radius:3px; background:var(--pg-ultra); }
.dp-gauge.over i b{ background:var(--bad); }

/* 来源卡的口径段与构成表：与经典模式下钻抽屉共用 .drill-* 那套，
   这里只补它没有的那一条（口径正文块）。 */
.drill-cal{ margin:0; font-size:12.5px; line-height:1.85; color:var(--ink);
            background:var(--panel-2); border:1px solid var(--line);
            border-left:3px solid var(--brand); border-radius:var(--r-xs); padding:10px 13px; }
.drill-lin .ln-r{ display:block; font-size:10.5px; color:var(--ink3); margin:2px 0 4px; }
/* 可穿透的数字：与既有 .numlink 同一套，只是来源卡档用点线而不是实线 —— 
   实线下划留给「能穿到单据」的那一档，两档的深度不一样，提示也不该一样。 */
.numlink.sc{ text-decoration:underline dotted; text-underline-offset:3px; }

@media (max-width:640px){
  .dp-figs{ grid-template-columns:1fr; }
  .dp-bar i{ max-width:56px; }
  .dp-gauge{ width:60px; }
}

/* 数字本身就是穿透口时，按钮只借它的「可点」，不借它的字号。
   button.numlink 上那条 font-size:12px 是给表格里的行内链接定的，在那儿
   是对的；但同一条落到 KPI 卡的主数字上，就把这张卡的主角从 17px 缩成了
   一个链接的大小 —— 一屏六张卡同时降级，页面的层级就塌了一层。
   表格里也改成 inherit：同一列里「能穿透的格」和「不能穿透的格」差
   0.5px 字号，看起来像两种数。 */
.dp-kpis .kpi .v button.numlink,
.dp-drv .vd button.numlink,
.tbl button.numlink{ font-size:inherit; }

/* ══════════════════════════════════════════════════════════════
   部门经营分析 · 模块版式（dept.js 的 modules / varTable / mod-ai）

   这一页的单位是**模块**：一节 = 差异表 + 可开关的图 + 紧跟其后的 AI 分析。
   旧版把数摆在上半页、把五节正文堆在页尾，写「收入分析」那一节的人要在
   第 2 屏的表和第 7 屏的输入框之间来回跳 —— 而他要写的判断恰恰来自那张表。
   写材料的人是一段数一段话往下推的，版式得跟上这个动作。
   ══════════════════════════════════════════════════════════════ */
.mods{ display:flex; flex-direction:column; gap:var(--sp-4); }
.mod{
  background:var(--panel); border:1px solid var(--line); border-radius:var(--r-md);
  box-shadow:var(--shadow-sm); padding:var(--sp-5) var(--sp-5) var(--sp-4);
}
.mod.fold{ padding-bottom:var(--sp-4); background:var(--panel-2); box-shadow:none; }
.mod.gap{ border-left:3px solid var(--warn); }
.mod-h{ display:flex; align-items:center; gap:var(--sp-2); flex-wrap:wrap; }
.mod-h .no{
  width:22px; height:22px; flex:none; border-radius:50%; background:var(--brand-soft);
  color:var(--brand); font-size:12px; font-weight:700; display:grid; place-items:center;
}
.mod-h b{ font-size:15px; font-weight:700; letter-spacing:-.01em; }
.mod-h .st{ font-size:11px; padding:2px 8px; border-radius:var(--r-pill); }
.mod-h .st.done{ background:var(--good-soft); color:var(--good); }
.mod-h .st.gap{ background:var(--warn-soft); color:var(--warn); }
.mod-fig,.dp-fold{
  margin-left:auto; font:inherit; font-size:11.5px; padding:3px 10px; cursor:pointer;
  border:1px solid var(--line-2); border-radius:var(--r-pill);
  background:var(--panel); color:var(--ink2);
}
.mod-fig+.dp-fold{ margin-left:0; }
.mod-fig:hover,.dp-fold:hover{ border-color:var(--brand); color:var(--brand); }
.mod-fig.on{ background:var(--brand-soft); border-color:var(--brand-border); color:var(--brand); }
.mod .focus{ margin:var(--sp-2) 0 var(--sp-4); font-size:12px; color:var(--ink3); }
.mod .foldnote{ margin:var(--sp-2) 0 0; font-size:12px; color:var(--ink3); }
.mod .nodata{
  margin:0; font-size:12.5px; line-height:1.8; color:var(--ink2);
  background:var(--panel-2); border:1px dashed var(--line-2); border-radius:var(--r-sm);
  padding:12px 15px;
}
.modt{
  margin:var(--sp-5) 0 var(--sp-2); font-size:12.5px; font-weight:650; color:var(--ink);
  display:flex; align-items:baseline; gap:var(--sp-2); flex-wrap:wrap;
}
.modt span{ font-size:11px; font-weight:400; color:var(--ink3); }

/* ── 差异表 ────────────────────────────────────────────────────
   经营差异分析的骨架。三组基准并排，红绿**只落在差异列上** ——
   实际值本身没有好坏，「5.24 亿」是红是绿取决于跟谁比。 */
.vtbl th.sub{ font-size:10.5px; font-weight:500; color:var(--ink3); padding-top:2px; }
.vtbl thead tr:first-child th[colspan]{
  text-align:center; border-bottom:1px solid var(--line);
  box-shadow:inset 1px 0 0 var(--line);
}
.vtbl td.base{ color:var(--ink3); }
.vtbl td.act{ font-weight:650; }
.vtbl .dpct{ display:block; font-size:10.5px; color:var(--ink3); font-variant-numeric:tabular-nums; }
.vtbl tr.vopen>td{ background:var(--brand-soft); }
/* 可就地展开的数字。点线下划 = 「这个数能拆开」，与穿到单据那一档
   （实线下划）区分：两档深度不同，提示也不该一样。 */
button.cellx{
  font:inherit; font-family:var(--mono); font-variant-numeric:tabular-nums;
  background:none; border:0; padding:0; cursor:pointer; color:var(--ink);
  text-decoration:underline dotted var(--brand-border); text-underline-offset:3px;
}
button.cellx:hover{ color:var(--brand); text-decoration-color:var(--brand); }
button.cellx.on{ color:var(--brand); font-weight:700; }
button.cellx::after{ content:' ⌄'; font-size:9px; color:var(--ink3); }
button.cellx.on::after{ content:' ⌃'; color:var(--brand); }
.vtbl tr.vdrill>td{ background:var(--panel-2); padding:0; }
.vd-h{
  display:flex; align-items:center; gap:var(--sp-3); flex-wrap:wrap;
  padding:10px 14px 8px; border-bottom:1px solid var(--line);
}
.vd-h b{ font-size:12px; }
.vd-h .lnk{ margin-left:auto; }
.vd-h .seg{ display:inline-flex; border:1px solid var(--line-2); border-radius:var(--r-pill); overflow:hidden; }
.vd-h .seg button{
  font:inherit; font-size:11px; padding:3px 11px; border:0; cursor:pointer;
  background:var(--panel); color:var(--ink2);
}
.vd-h .seg button.on{ background:var(--brand); color:#fff; font-weight:600; }
.vd-load{ padding:14px; font-size:12px; color:var(--ink3); }
.vtbl tr.vdrill .tblwrap{ padding:0 14px; }
.vtbl tr.vdrill .dim{ padding:0 14px 12px; margin:6px 0 0; }
.vd-t{ font-size:12px; }
.vtip{ margin:var(--sp-2) 0 0; font-size:11px; line-height:1.75; color:var(--ink3); }
.synthrow td{ background:var(--warn-soft); }

/* ── 每个模块自己的 AI 分析块 ──────────────────────────────────
   形态取自 GEO-fresh 智能报表：AI 块贴在它所解释的那段数据正下方，
   不是全页尾巴上的一个大区。左侧那道品牌色实边就是「这段是判断，
   不是数」的视觉分界 —— 材料上这两类东西的责任人是不同的。 */
.mod-ai{
  margin-top:var(--sp-5); border:1px solid var(--brand-border); border-left:3px solid var(--brand);
  border-radius:var(--r-sm); padding:13px 16px;
  background:linear-gradient(180deg,var(--brand-soft),var(--panel) 70%);
}
.mod-ai.blank{ border-color:var(--line-2); border-left-color:var(--warn); background:var(--panel-2); }
.mod-ai .ai-h{
  display:flex; align-items:baseline; gap:var(--sp-2); flex-wrap:wrap;
  font-size:10.5px; font-weight:800; letter-spacing:.06em; color:var(--brand); margin-bottom:9px;
}
.mod-ai .ai-h::before{ content:'✦ '; }
.mod-ai.blank .ai-h{ color:var(--warn); }
.mod-ai .ai-x{ font-size:10.5px; font-weight:400; letter-spacing:0; color:var(--ink3); }
.mod-ai .body{ font-size:13px; line-height:1.85; color:var(--ink); }
.mod-ai .body p{ margin:0 0 var(--sp-2); }
.mod-ai .blankline{ margin:0; font-size:12.5px; line-height:1.8; color:var(--ink2); }
.mod-ai .by{ margin:var(--sp-2) 0 0; font-size:11px; color:var(--ink3); }
.mod-ai .by .draft{ color:var(--warn); }
.mod-ai .acts{ margin-top:var(--sp-3); display:flex; gap:var(--sp-2); align-items:center; flex-wrap:wrap; }
.chip.ai{ background:var(--brand-soft); color:var(--brand); border-color:var(--brand-border); }
.chip.ai:hover{ background:var(--brand); color:#fff; }
.mod-ai .dp-in{ width:100%; }

/* ── 差异导航条：先看哪一节 ─────────────────────────────────── */
.focusbar{
  margin-bottom:var(--sp-4); padding:12px 16px; background:var(--panel);
  border:1px solid var(--line); border-radius:var(--r-sm);
}
.focusbar>b{ font-size:12.5px; }
.focusbar .fx{ font-size:11px; color:var(--ink3); margin-left:var(--sp-2); }
.focusbar .fl{ display:flex; flex-wrap:wrap; gap:var(--sp-2); margin-top:var(--sp-2); }
.focusbar .dim{ margin:var(--sp-2) 0 0; font-size:11px; line-height:1.7; }
.fchip{
  font:inherit; font-size:12px; display:inline-flex; align-items:baseline; gap:7px;
  padding:5px 12px; cursor:pointer; border:1px solid var(--line-2);
  border-radius:var(--r-pill); background:var(--panel); color:var(--ink);
}
.fchip:hover{ border-color:var(--brand); background:var(--brand-soft); }
.fchip.key{ border-color:var(--warn-line); background:var(--warn-soft); font-weight:600; }
.fchip em{ font-style:normal; font-size:11px; color:var(--ink3); font-variant-numeric:tabular-nums; }

@media (max-width:860px){
  .mod{ padding:var(--sp-4) var(--sp-3); }
  .mod-fig,.dp-fold{ margin-left:0; }
}
/* 拆开看的表尾那一排「穿到单据」入口：这一层给构成，再深一档才是明细与
   单据，两档的入口摆在一起、但视觉分量不同 —— 构成是表，深钻是链接。 */
.vd-deep{ display:flex; flex-wrap:wrap; gap:6px 12px; padding:0 14px 12px; margin:6px 0 0; }
.vd-deep .numlink{ font-size:11.5px; font-family:inherit; }
