  /* ===== 管理大屏（Management Big Screen） =====
     从 css/views.css 拆出来的独立文件——views.css 本轮涨到 371 行，超过
     CLAUDE.md 0.4 定的 300 行文件硬指标，按职责切开：大屏专属的 .bs-* 规则
     （KPI 卡组/店铺进度卡/运营对比/动态时间线/模块热力矩阵）整块搬到这里，
     views.css 只保留每日记录/运营填报/设置页/清单管理。纯物理搬家，选择器与
     声明逐字未变，不是重新设计。
     加载顺序：必须排在 base.css/components.css/views.css 之后、mobile.css 之前
     ——mobile.css 里 .bs-banner/.bs-section-title/.bs-op-stats-row/
     .bs-store-card-stats 等规则要靠层叠顺序覆盖这里的同名选择器（见
     css/mobile.css 文件头注释），这里排在它后面就会被静默吃掉，覆盖不生效。
     见 public/index.html 与 public/admin.html 的 <link> 顺序。 */
  .bs-banner { display:flex; align-items:center; gap:16px; padding:16px 24px; background:var(--brand); border-radius:var(--radius); margin-bottom:16px; color:#fff; }
  .bs-banner-logo { width:44px; height:44px; border-radius:var(--radius-sm); background:rgba(255,255,255,0.2); display:flex; align-items:center; justify-content:center; font-size:22px; flex-shrink:0; }
  .bs-banner-title { font-size:22px; font-weight:800; letter-spacing:1px; }
  .bs-banner-sub { font-size:12px; opacity:0.85; margin-top:2px; }
  .bs-banner-date { margin-left:auto; font-size:13px; opacity:0.9; text-align:right; }
  .bs-kpi-row { display:grid; grid-template-columns:repeat(auto-fit, minmax(170px, 1fr)); gap:12px; margin-bottom:16px; }
  /* 11 张卡的底色渐变/图标底色/数字色收敛成四个变量：--c 主色、--bg1/--bg2 渐变
     两端、--bd 边框。公共规则只写一次，每张卡只声明四个变量——颜色值逐字未变，
     纯粹是规则收敛，不是重新配色。k1/k2 的图标底色与卡片渐变起点本来就不同
     （二者是两个独立设计出的颜色，不是同一个值的重复），不能强行并进 --bg1，
     单独覆盖；k11 非 warn 状态同理，图标色(--text-subtle)与数字色(--text)不同，
     单独覆盖图标色。 */
  /* 1c（2026-09-14）：用户要求两行 KPI 卡「整体高度增大一些」——只加高度：
     min-height 104→140、上下 padding 18→26、数字 28→34、标签 12→13。左右 padding
     与图标尺寸刻意不动：第二行 7 列每张卡只有约 189px 宽，横向再挤会让标签断行。
     tests/responsive.js 的 DESKTOP_BASELINE_1440.kpiCard1 已同步重测。 */
  .bs-kpi-card { min-height:140px; border-radius:var(--radius); padding:26px 16px; position:relative; overflow:hidden; display:flex; align-items:center; gap:14px; transition:all 0.3s; background:linear-gradient(135deg,var(--bg1),var(--bg2)); border:1px solid var(--bd); box-shadow:var(--shadow-card); }
  .bs-kpi-card:hover { transform:translateY(-3px); box-shadow:0 8px 24px rgba(0,0,0,0.1); }
  .bs-kpi-card .kpi-icon { width:48px; height:48px; border-radius:var(--radius-sm); display:flex; align-items:center; justify-content:center; font-size:24px; flex-shrink:0; background:var(--bg1); color:var(--c); }
  .bs-kpi-card .kpi-body { flex:1; min-width:0; }
  .bs-kpi-card .kpi-head { display:flex; align-items:baseline; gap:7px; flex-wrap:wrap; }
  .bs-kpi-card .kpi-num { font-size:34px; font-weight:800; line-height:1.1; font-variant-numeric:tabular-nums; color:var(--c); }
  .bs-kpi-card .kpi-lbl { font-size:13px; color:var(--text-muted); margin-top:2px; }
  /* min-height 固定按两行留白：row1(4 列/339px 宽) 与 row2(7 列/~189px 宽) 是两个
     独立的 grid 容器，行高各自独立结算——row2 更窄，好几张卡的 sub 文案在窄列下
     会换成两行，若不统一预留，两个 grid 各自结算出的自然高度就会对不上（11 张
     卡"全部等高"的验收硬指标）。按两行的实际高度(30px = 15px×2)统一预留，无论
     这张卡的文案是否真的换行，都占同样的位。 */
  .bs-kpi-card .kpi-sub { font-size:10px; color:var(--text-subtle); margin-top:2px; min-height:30px; }
  .bs-kpi-card .kpi-chip { font-size:10.5px; font-weight:600; padding:1px 7px; border-radius:var(--radius-sm); background:#fff1f0; color:var(--bad); }
  .bs-kpi-card .kpi-bar { display:flex; height:4px; border-radius:2px; margin-top:8px; gap:2px; background:rgba(0,0,0,.05); }
  .bs-kpi-card .kpi-bar i { height:100%; border-radius:2px; background:var(--c); }
  .bs-kpi-card .kpi-bar i.seg-expired { background:var(--bad); opacity:.55; }
  .bs-kpi-card.k1 { --c:var(--brand); --bg1:var(--brand-bg); --bg2:var(--brand-bg); --bd:var(--brand-bd); }
  .bs-kpi-card.k1 .kpi-icon { background:var(--brand-bg); }
  .bs-kpi-card.k2 { --c:var(--ok); --bg1:#f6ffed; --bg2:#fcfffa; --bd:#b7eb8f; }
  .bs-kpi-card.k2 .kpi-icon { background:#f0fff0; }
  .bs-kpi-card.k3 { --c:#fa8c16; --bg1:#fff7e6; --bg2:#fffbf0; --bd:#ffd591; }
  .bs-kpi-card.k4 { --c:var(--brand); --bg1:#e6f7ff; --bg2:#f0f9ff; --bd:#91d5ff; }
  .bs-kpi-card.k5 { --c:var(--week); --bg1:#f9f0ff; --bg2:#fcf6ff; --bd:#d3adf7; }
  .bs-kpi-card.k6 { --c:var(--bad); --bg1:#fff1f0; --bg2:#fff5f5; --bd:#ffa39e; }
  .bs-kpi-card.k7 { --c:#13c2c2; --bg1:#e6fffb; --bg2:#f0fffc; --bd:#87e8de; }
  .bs-kpi-card.k8 { --c:#d4b106; --bg1:#fffbe6; --bg2:#fffef5; --bd:#ffe58f; }
  .bs-kpi-card.k9 { --c:#eb2f96; --bg1:#fff0f6; --bg2:#fff5f9; --bd:#ffadd2; }
  /* k10 新品 SOP：复用 components.css .tf-once 已在用的 --once 一档，不新造颜色——
     k1-k9 已占满其余分类色，且品牌换蓝后原来的靛蓝色值与 --brand 太接近，一并
     挪到中性 --once（见 CLAUDE.md 工程约定） */
  .bs-kpi-card.k10 { --c:var(--once); --bg1:var(--once-bg); --bg2:var(--once-bg); --bd:var(--border); }
  /* 决策 9 变更：本期待补做，默认中性灰，值 > 0 时叠加 .warn 切成警示红（复用
     --bad 语义色，不新造颜色，见 CLAUDE.md 工程约定） */
  .bs-kpi-card.k11 { --c:var(--text); --bg1:#fafafa; --bg2:#fcfcfc; --bd:var(--border); }
  .bs-kpi-card.k11:not(.warn) .kpi-icon { color:var(--text-subtle); }
  .bs-kpi-card.k11.warn { --c:var(--bad); --bg1:#fff1f0; --bg2:#fff5f5; --bd:#ffa39e; }

  .bs-section { margin-bottom:20px; }
  .bs-section-title { font-size:16px; font-weight:700; margin:0 0 12px; display:flex; align-items:center; gap:8px; color:var(--text); }
  .bs-section-title .bs-icon { width:28px; height:28px; border-radius:var(--radius-sm); background:var(--brand-bg); color:var(--brand); display:flex; align-items:center; justify-content:center; font-size:15px; }
  .bs-section-title .bs-count { font-size:12px; color:var(--text-subtle); font-weight:400; margin-left:auto; }
  /* 1a：店铺卡区块折叠开关——按钮排在 .bs-count 之后，靠 .bs-count 已有的
     margin-left:auto 把这一组（count+按钮）整体推到标题行最右侧。 */
  .bs-fold { margin-left:8px; min-height:32px; padding:2px 10px; font-size:12px; border:1px solid var(--border); border-radius:var(--radius-sm); background:var(--surface); color:var(--text-muted); cursor:pointer; }
  .bs-fold:hover { border-color:var(--brand); color:var(--brand); }
  .bs-section.is-folded .bs-store-grid { display:none; }
  /* Store progress cards */
  /* align-items:stretch（默认值本就是 stretch，这里显式写出）：同一行内的卡片
     顶边与统计格两条水平线才能对齐——配合 .bs-store-card 的 flex column +
     .bs-store-card-stats 的 margin-top:auto 一起生效，三处缺一不可。 */
  .bs-store-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(300px,1fr)); gap:14px; align-items:stretch; }
  .bs-store-card { display:flex; flex-direction:column; background:var(--surface); border:1px solid var(--border); border-radius:var(--radius); padding:16px; transition:all 0.2s; cursor:pointer; position:relative; box-shadow:var(--shadow-card); }
  .bs-store-card:hover { border-color:var(--brand); box-shadow:0 4px 20px rgba(37,99,235,0.1); transform:translateY(-2px); }
  /* 到期状态左色条：只是视觉提示，不影响可点性——已到期店铺仍可点进详情查看
     历史（决策10）。padding-left 从 16px 减到 13px 补偿 3px 边框宽度，避免
     卡片内容因为多了一条边框而整体右移。 */
  .bs-store-card.is-expired { border-left:3px solid var(--bad); padding-left:13px; }
  .bs-store-card.is-expiring { border-left:3px solid var(--warn); padding-left:13px; }
  /* 已到期只压暗共用骨架（views/store-card.js renderStoreCardHead）产出的头部
     信息——店名/百分比行、元信息、服务期、状态徽章；四格统计数字绝对不减淡
     （决策 10：压暗会让对比度跌破 4.5:1），统计区是 renderStoreCardHead 之外
     另画的兄弟节点，本来就不在这个选择器范围内。头部信息在结构调整后不再
     共享同一个包裹元素（.sc-head-left 已删除，见该文件注释），改成逐个选中
     四个直接子元素，视觉效果与调整前逐字一致。 */
  .bs-store-card.is-expired .sc-top,
  .bs-store-card.is-expired .sc-meta,
  .bs-store-card.is-expired .sc-rows,
  .bs-store-card.is-expired .sc-badges { opacity:.65; }
  .expiry-tag { display:inline-flex; align-items:center; gap:3px; font-size:10.5px; font-weight:600; padding:1px 7px; border-radius:var(--radius-sm); white-space:nowrap; }
  .expiry-tag.expired { background:var(--bad-bg); color:var(--bad); }
  .expiry-tag.expiring { background:var(--warn-bg); color:var(--warn); }
  /* 头部走共用骨架后不再有自己的 flex 行可以并排放进度环——环挪到头部下方，
     居中于卡片宽度（align-self:center 是 flex column 容器下让子项水平居中的写法）。 */
  /* 头部两列：左侧信息占满剩余宽度，右侧进度环定宽不压缩。align-items:flex-start
     让环与店名顶端对齐，而不是随左列高度上下漂。 */
  .bs-card-head { display:flex; align-items:flex-start; gap:14px; margin-bottom:12px; }
  .bs-card-info { flex:1; min-width:0; }
  .bs-ring { width:60px; height:60px; position:relative; flex-shrink:0; }
  .bs-ring svg { transform:rotate(-90deg); }
  .bs-ring circle { fill:none; stroke-width:5; }
  .bs-ring .ring-bg { stroke:#f0f0f0; }
  .bs-ring .ring-fg { stroke:var(--brand); stroke-linecap:round; transition:stroke-dashoffset 0.6s; }
  .bs-ring .ring-fg.dim { stroke:#bfbfbf; }
  .bs-ring .ring-pct { position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); font-size:14px; font-weight:800; color:var(--brand); }
  .bs-ring .ring-pct.dim { color:var(--text-muted); }
  /* margin-top:auto 把四格统计贴到卡片底部——见 .bs-store-grid 头部注释，
     三处配合才能让同一行卡片的顶边与统计格对齐。 */
  .bs-store-card-stats { display:grid; grid-template-columns:repeat(4,1fr); gap:6px; margin-top:auto; }
  .bs-mini-stat { text-align:center; padding:8px 4px; border-radius:var(--radius-sm); background:#fafafa; }
  .bs-mini-stat .num { font-size:18px; font-weight:700; line-height:1.2; }
  .bs-mini-stat .lbl { font-size:9px; color:var(--text-subtle); margin-top:2px; }
  .bs-mini-stat.locked { background:var(--ok-bg); } .bs-mini-stat.locked .num { color:var(--ok); }
  .bs-mini-stat.pending { background:var(--warn-bg); } .bs-mini-stat.pending .num { color:var(--warn); }
  .bs-mini-stat.undone { background:var(--bad-bg); } .bs-mini-stat.undone .num { color:var(--bad); }
  .bs-mini-stat.proof { background:var(--week-bg); } .bs-mini-stat.proof .num { color:var(--week); }
  /* Operator comparison */
  .bs-op-card { background:var(--surface); border:1px solid var(--border); border-radius:var(--radius); padding:16px; margin-bottom:12px; box-shadow:var(--shadow-card); }
  .bs-op-head { display:flex; align-items:center; gap:12px; margin-bottom:12px; }
  .bs-op-avatar { width:40px; height:40px; border-radius:50%; background:linear-gradient(135deg,var(--brand),var(--brand-hover)); color:#fff; display:flex; align-items:center; justify-content:center; font-size:16px; font-weight:700; flex-shrink:0; }
  .bs-op-name { font-size:15px; font-weight:700; }
  .bs-op-stores { font-size:11px; color:var(--text-subtle); margin-top:2px; }
  .bs-op-bar-row { display:flex; align-items:center; gap:10px; margin-bottom:8px; }
  .bs-op-bar-label { width:70px; font-size:12px; color:var(--text-muted); flex-shrink:0; }
  .bs-op-bar-track { flex:1; height:20px; background:#f5f5f5; border-radius:var(--radius-sm); overflow:hidden; position:relative; }
  .bs-op-bar-fill { height:100%; border-radius:var(--radius-sm); transition:width 0.6s; display:flex; align-items:center; justify-content:flex-end; padding-right:8px; font-size:10px; color:#fff; font-weight:600; }
  .bs-op-stats-row { display:grid; grid-template-columns:repeat(5,1fr); gap:8px; margin-top:8px; }
  .bs-op-mini { text-align:center; padding:8px 4px; border-radius:var(--radius-sm); background:#fafafa; }
  .bs-op-mini .num { font-size:18px; font-weight:700; }
  .bs-op-mini .lbl { font-size:9px; color:var(--text-subtle); margin-top:2px; }
  /* Activity timeline */
  .bs-activity { background:#fff; border:1px solid var(--border); border-radius:var(--radius); padding:16px; max-height:440px; overflow-y:auto; }
  .bs-activity::-webkit-scrollbar { width:4px; }
  .bs-activity::-webkit-scrollbar-thumb { background:#ddd; border-radius:2px; }
  .bs-act-item { display:flex; gap:12px; padding:10px 0; border-bottom:1px solid #f5f5f5; align-items:flex-start; }
  .bs-act-item:last-child { border-bottom:none; }
  .bs-act-icon { width:36px; height:36px; border-radius:var(--radius-sm); display:flex; align-items:center; justify-content:center; font-size:16px; flex-shrink:0; }
  .bs-act-icon.done { background:var(--ok-bg); color:var(--ok); }
  .bs-act-icon.log { background:var(--brand-bg); color:var(--brand); }
  .bs-act-body { flex:1; min-width:0; }
  .bs-act-head { display:flex; align-items:center; gap:8px; margin-bottom:3px; flex-wrap:wrap; }
  .bs-act-store { font-size:13px; font-weight:700; color:var(--brand); }
  .bs-act-type { font-size:10px; padding:2px 8px; border-radius:var(--radius-sm); font-weight:600; }
  .bs-act-type.task { background:var(--ok-bg); color:var(--ok); }
  .bs-act-type.log { background:var(--brand-bg); color:var(--brand); }
  .bs-act-time { font-size:10px; color:var(--text-subtle); margin-left:auto; }
  .bs-act-desc { font-size:12px; color:var(--text-muted); line-height:1.6; word-break:break-all; }
  .bs-act-empty { text-align:center; padding:40px; color:var(--text-subtle); font-size:14px; }
  /* Module matrix heatmap */
  .bs-matrix-wrap { overflow-x:auto; border-radius:var(--radius); border:1px solid var(--border); background:#fff; }
  .bs-matrix { width:100%; border-collapse:collapse; font-size:12px; }
  /* 列内边距收到 9px 6px：11 个模块列 + 店铺/运营/总进度共 14 列，1440 宽度下
     刚好不用横向滚动，窄屏靠 .bs-matrix-wrap 的 overflow-x:auto 兜底。 */
  .bs-matrix th { padding:9px 6px; text-align:center; color:var(--text-subtle); border-bottom:2px solid var(--border); font-weight:600; font-size:11px; }
  .bs-matrix td { padding:9px 6px; border-bottom:1px solid #f5f5f5; text-align:center; }
  .bs-matrix tr:hover { background:var(--brand-bg); }
  .bs-matrix tr.is-expired td:first-child { border-left:3px solid var(--bad); }
  .bs-matrix .store-name { font-weight:700; }
  /* 店铺/运营两列横向滚动时固定不动（两层表头+11 模块列比 1440 宽屏还宽是常态）。
     表头层 z-index 高于数据层，避免横向滚动时数据列的内容从表头下方露出来。 */
  .bs-matrix .mx-sticky { position:sticky; background:var(--surface); z-index:1; text-align:left; }
  .bs-matrix .grp { font-weight:700; }
  .bs-matrix .mx-sticky-store { left:0; width:150px; max-width:150px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .bs-matrix .mx-sticky-op { left:150px; }
  .bs-matrix thead .mx-sticky { z-index:3; }
  /* 两层表头上层分组色：SOP 目录用品牌色系，周月节奏用周期色系（--week，与
     清单页周期徽章同一档），总进度用中性灰——三档配色见 store-card.js 同款
     语义色分配原则，不新造颜色。下层模块名 .txt 强制不换行：中文模块名在词
     中间断行很难看；.cnt 是模块条目数，弱化处理。 */
  .bs-matrix .grp.sop { background:var(--brand-bg); color:var(--brand-hover); }
  .bs-matrix .grp.cad { background:var(--week-bg); color:var(--week); }
  .bs-matrix .grp.tot { color:var(--text-muted); }
  .bs-matrix thead th .txt { display:block; white-space:nowrap; font-weight:700; font-size:11px; color:var(--text); }
  .bs-matrix thead th .cnt { display:block; font-size:9.5px; color:var(--text-subtle); font-weight:400; margin-top:1px; }
  .bs-matrix .heat-cell { display:inline-block; padding:4px 10px; border-radius:var(--radius-sm); font-size:11px; font-weight:700; min-width:50px; }
  .bs-matrix .heat-cell.h-green { background:var(--ok-bg); color:var(--ok); }
  .bs-matrix .heat-cell.h-orange { background:var(--warn-bg); color:var(--warn); }
  .bs-matrix .heat-cell.h-red { background:var(--bad-bg); color:var(--bad); }
  .bs-matrix .heat-cell.h-gray { background:var(--bg-muted); color:var(--text-subtle); }
  .bs-matrix .pct-bar { width:60px; height:6px; background:#f0f0f0; border-radius:3px; overflow:hidden; display:inline-block; vertical-align:middle; margin-left:4px; }
  .bs-matrix .pct-fill { height:100%; border-radius:3px; }
