/* ═══════════════════════════════════════════════════════════════════════
   工作台 v3 · 「破局」规范落地位（皮肤层）
   ---------------------------------------------------------------------
   上游依据：teacherdesk/docs/poju/破局设计规范.md + poju.css。
   上面那四份（tokens / ui / app / motion）是现役工作台原样复制过来的，
   一行没改；这个文件是唯一为 demo 写的样式，也是唯一改动落地的地方。

   与 v2 的区别（v2 是「轻穿皮」，v3 是「按规范逐条落地」）：
     1. 雾底补第 4 层：噪点纸感（规范 §2 的「纸感 vs 塑料感」唯一来源）
     2. 玻璃补足四件事：38% 白 / blur(44px) saturate(180%) / 上下双 inset
        （v2 只有顶部高光，缺底部暗边，玻璃没有厚度）/ hover 不位移
     3. 刊头补三层语法：eyebrow 斜体衬线 + 44px 规线 + 衬线 900 大标题
     4. 卡片编号 01/02/03（规范 §6.3，刊物感最便宜的来源）
     5. 今天页 12 栏通铺：.col-main/.col-side 用 display:contents 拆开，
        四张卡在同一行横向铺开，不再一列一列往下堆
     6. 动效按 §7 清单落到工作台组件：rise / chIn / ruleIn / ripple /
        扫光 / toast 上浮；**不做指针迎光与磁吸**（用户明确否掉了跟随光标）
     7. 触屏降级：雾底改 scroll、blur 降到 26px（规范 §9）

   原则仍然是：只写样式，不改 app.js 的业务结构与顺序。
   ═══════════════════════════════════════════════════════════════════════ */

/* ─────────────────────────── 1. token 重定 ───────────────────────────
   现役所有颜色都从 tokens.css / ui.css 的 :root 里取，所以只改这里，
   全站就跟着换 —— 这是当初把 token 收口带来的好处，这次直接用上了。 */
:root{
  /* 字 · 墨色（偏蓝的墨，不用纯黑；四档灰阶保持原有对比度层级）
     ── 2026-11-09 对比度收口 ──
     卡片底是半透明白（--card:rgba(255,255,255,.82)）叠在暖色页底上，
     实际背景比纯白暗 5~12，同样是这四个灰，落在卡片上就比落在白底上少 0.5~1.1 档。
     原来的 ink3/ink4 在白底是 4.86 / 4.22，叠到卡片上只剩 4.45 / 3.76 —— 不达 AA 的 4.5。
     现在按「卡片实底」验算重新取值，四个灰在全站最暗的三处底色
     （页底 247,247,249 / 卡内 241,242,244 / 浅填充 236,237,238）上都 ≥4.7:
        ink3 #5b6072 → 5.05 / 5.26 / 5.33     ink4 #63687a → 4.72 / 4.94 / 5.18
     层级仍然是四档，只是整体压深了一点；不再靠 opacity 去"淡一层"。 */
  --ink:#232634;
  --ink2:#4d5162;
  --ink3:#5b6072;
  --ink4:#63687a;

  /* 线 · 全站只有这一种线，比原来略实一点，才撑得住"纸"的分量 */
  --line:rgba(35,38,52,.105);
  --hairline:rgba(35,38,52,.085);
  --line-soft:rgba(35,38,52,.05);
  --fill:rgba(35,38,52,.04);
  --fill-2:rgba(35,38,52,.06);
  --check-line:rgba(35,38,52,.22);

  /* 唯一强调色：钢靛。品牌色阶、--blue 那一串别名全部指向它 */
  --brand-500:#2f6690;
  --brand-600:#255070;
  --brand-50:rgba(47,102,144,.07);
  --brand-100:rgba(47,102,144,.12);
  --blue:#2f6690;
  --blue-d:#255070;
  --blue-soft:rgba(47,102,144,.09);
  --blue-ring:rgba(47,102,144,.42);
  /* 刊头那条 44px 规线的颜色。破局里是 var(--accent) + opacity:.5，
     这里用一个带 alpha 的同色，因为它画在 background-image 上，
     没有 opacity 可调。 */
  --accent-line:rgba(47,102,144,.5);

  /* 选中态：原来那条绿→青渐变收成单色。
     全站的勾选框、胶囊、开关、下拉选中项都走这几个变量，改一处全改。 */
  --sel-a:#2f6690;
  --sel-b:#2f6690;
  --sel-grad:linear-gradient(135deg,#2f6690,#2f6690);
  --sel-ring:rgba(47,102,144,.42);
  --sel-line:rgba(47,102,144,.5);
  --sel-fill:rgba(47,102,144,.1);

  /* 语义色：往暗里压一档，配纸底不刺眼 */
  --ok:#3c9a63;
  --ok-text:#2c6f47;
  --warn:#b87324;
  --warn-text:#8a5a12;
  --red:#a8392b;
  --red-text:#a8392b;

  /* 卡面：白雾玻璃。和破局同配方（38% 白 + 大模糊），雾底透上来，
     卡片是"浮在雾上的一层磨砂"，不是一块白板。
     取 42% 而不是规范里的 38%：工作台一屏十几张卡、字又密，
     压到 38% 会让正文对比度掉到临界值以下。这 4% 是唯一的偏离，
     再往上加就开始朝"白卡"滑了。 */
  --card:rgba(255,255,255,.42);
  --glass:rgba(255,255,255,.42);
  --field:#ffffff;
  --field-2:rgba(255,255,255,.82);
  --edge:rgba(255,255,255,.7);

  /* 圆角：对齐破局 22/14/10。卡片要圆，圆才有"浮"的资格 */
  --r-xs:6px;
  --r-sm:10px;
  --r-md:14px;
  --r-lg:22px;

  /* 阴影：从"浮起来"改成"纸落下的一点点投影" */
  --sh-1:0 1px 1px rgba(35,38,52,.035),0 20px 44px -32px rgba(35,38,52,.4);
  --sh-2:0 2px 4px rgba(35,38,52,.05),0 28px 56px -32px rgba(35,38,52,.45);
  --sh-3:0 6px 16px -10px rgba(0,0,0,.55);

  /* 字体角色：衬线只在标题和数字上出现，正文永远是黑体 */
  --v2-serif:"Fraunces","Noto Serif SC","Songti SC","STSong","SimSun",Georgia,serif;
  --v2-sans:-apple-system,BlinkMacSystemFont,"SF Pro SC","PingFang SC",
            "HarmonyOS Sans SC","Noto Sans SC","Microsoft YaHei",sans-serif;

  /* ── 破局 §7 的四条曲线 ──
     除磁吸回位外，全页不许出现"弹一下"的过冲。这里没有磁吸，
     所以 --ease-spring 只备用、不启用。 */
  --ease-q:cubic-bezier(.25,1,.5,1);        /* 顺：hover / 颜色 / 位移 */
  --ease-x:cubic-bezier(.16,1,.3,1);        /* 定：入场 / 展开 / 墨线 */
  --ease-io:cubic-bezier(.65,0,.35,1);      /* 对称：来回过渡 */

  /* ── 破局 §5：玻璃的模糊强度 ──
     桌面 44px 才够"厚"；触屏降到 26px（移动端模糊很贵，会在 §23 覆盖） */
  --blur:blur(44px) saturate(180%);
}

/* ─────────────────────── 2. 页底：纯中性灰 ───────────────────────
   2026-11-04 老板要求"紫色一点都不要，全删了"：雾底彩团全部撤掉，
   拍平成纯中性纸灰。空气感靠噪点层（下方 body::after）保留。 */
html{
  background:#f1f2f4;
}
/* 光斑层下线。理由有两条：
   ① 视觉上它和"纸"打架，模糊光晕会把发丝线糊掉；
   ② 性能上它是全站最贵的一层（两个 blur(70px) 的 58vw 圆，还是动的）。 */
.bg{display:none}

/* 页底第 4 层：噪点（规范 §2）。
   雾底给空气，噪点给"纸"。没有这一层，大圆角玻璃会滑向"塑料 App"；
   有了它，同一张卡片读起来是"印在纸上的一层磨砂"。
   §2 的三条硬规矩：pointer-events:none / z-index:0 / 内容层 z-index ≥ 1
   （工作台的 .main 本来就是 z-index:2，满足）。 */
body::after{
  content:"";position:fixed;inset:0;pointer-events:none;z-index:0;
  opacity:.3;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.05'/%3E%3C/svg%3E");
}

body{
  font-family:var(--v2-sans);
  letter-spacing:-.004em;
}
::selection{background:rgba(47,102,144,.18)}

/* 全站焦点环统一成强调色（键盘可达性，别改没了） */
:focus-visible{outline:2px solid var(--blue);outline-offset:2px}

/* ─────────────────────── 3. 卡片：破局玻璃四件事 ──────────────────
   .glass 是现役所有卡片的共同底（KPI、栏目卡、材料表、Copilot 条、
   各种面板）。改这一条，全站一起换皮。

   规范 §5 说得很死：四件事缺一不可，缺一件就从"玻璃"掉回"白卡"。
     ① 38%~42% 白 —— 太实雾就白铺了（v2 用的是 .48，偏实）
     ② 上下两条 inset —— 上亮下暗，平面才有厚度；只写外阴影像贴纸
     ③ saturate(180%) —— 透过来的雾更活，纯 blur 会发灰
     ④ hover 只加深、不位移 —— 玻璃是"光变了"，不是"飘起来了" */
.glass{
  background:var(--glass);
  border:1px solid var(--edge);
  border-radius:var(--r-lg);
  box-shadow:
    0 1px 1px rgba(35,38,52,.04),
    0 20px 48px -14px rgba(35,38,52,.18),
    inset 0 1px 0 rgba(255,255,255,.85),
    inset 0 -1px 0 rgba(35,38,52,.07);
  -webkit-backdrop-filter:var(--blur);
  backdrop-filter:var(--blur);
}
/* 卡片悬浮：v2 还留着 2px 位移，规范里明确禁止（"飘起来"是 SaaS 观感）。
   这里位移归零，只让远处那道柔光加深一点点 —— 像光的角度变了。 */
@media (hover:hover) and (pointer:fine){
  .glass.card:hover,.panel:hover{
    transform:none;
    box-shadow:
      0 1px 1px rgba(35,38,52,.04),
      0 26px 56px -14px rgba(35,38,52,.22),
      inset 0 1px 0 rgba(255,255,255,.85),
      inset 0 -1px 0 rgba(35,38,52,.07);
  }
}
/* 兜底：不支持 backdrop-filter 的浏览器宁可实一点，也不能糊（规范 §5 末） */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .glass{background:rgba(255,255,255,.93)}
}

/* ─────────────────────── 4. 侧栏 ───────────────────────
   同一张玻璃：白雾 + blur，右侧一道发丝线。 */
@media (min-width:1080px){
  .side{
    background:rgba(255,255,255,.42);
    -webkit-backdrop-filter:blur(26px) saturate(170%);
    backdrop-filter:blur(26px) saturate(170%);
    border-right:1px solid var(--edge);
  }
}
.side-brand .av{
  width:30px;height:30px;border-radius:6px;
  font-family:var(--v2-serif);font-size:14.5px;font-weight:700;
  color:#f7f6f2;background:var(--blue);
  box-shadow:none;
}
.side-brand .bm b{
  font-family:var(--v2-serif);font-size:16px;font-weight:700;letter-spacing:.01em;
}
.side-brand .bm em{
  font-size:12px;letter-spacing:.12em;color:var(--ink4);margin-top:3px;
}
/* 分组标题（档案）：斜体衬线 + 大字距，页边注的味道 */
.side-cap{
  font-family:var(--v2-serif);font-style:italic;font-weight:600;
  font-size:12px;letter-spacing:.28em;color:var(--ink4);
  margin:4px 0 7px;
}
.side-nav a{
  border-radius:6px;font-size:13px;letter-spacing:.01em;
}
.side-nav a.on{font-weight:600;letter-spacing:.015em}
/* 选中指示：原来是一块浅蓝胶囊，现在只留左边一根 2px 的竖线 */
.side-ind{background:rgba(47,102,144,.06);border-radius:6px}
.side-nav a.on::before{
  width:2px;height:14px;margin-top:-7px;background:var(--blue);border-radius:0;
}
.badge{border-radius:3px;font-size:12px;letter-spacing:.04em}
.side-nav a.on .badge{color:var(--blue);background:var(--blue-soft)}
.side-new{
  border-radius:7px;font-size:13px;font-weight:600;letter-spacing:.1em;
  background:var(--ink);box-shadow:0 8px 18px -12px rgba(35,38,52,.8);
}
/* 2026-11-09 字号下限收口：侧栏底部只有 203px 可用宽，12px 会把
   「本学期 6 份 / 测试版 · 仅本机 / 第 8 / 20 周」挤成两行，
   这里退回 11px（= --fs-xs，全站最小档）并把字距归零腾出 4px，
   保证三格仍是一行。11px 只留给这种「一屏只出现一处的密排非正文标记」，
   正文与标注一律 12px 起。 */
.side-meta{letter-spacing:0;font-size:11px}
/* 版本号：给"样式没更新"这类问题一个可对照的锚点（demo 专用，新加的类）
   版本串带 hash 有 23 个字符，12px / 11px 都会折行，字距从 .14em 收到 .06em
   后正好一行；它仍是「印章」语感，只是不再撑破侧栏。 */
.side-ver{
  margin-top:10px;padding:9px 4px 0;border-top:1px solid var(--hairline);
  font-size:11px;letter-spacing:.06em;color:var(--ink4);
  font-variant-numeric:tabular-nums;text-transform:uppercase;
}

/* ─────────────────────── 5. 窄屏顶栏 ───────────────────────
   滚动后收成胶囊的那条，也一并换成纸。 */
.nav.compact .nav-in{
  border-radius:9px;
  background:rgba(252,251,249,.9);
  border-color:var(--hairline);
  -webkit-backdrop-filter:blur(18px) saturate(140%);
  backdrop-filter:blur(18px) saturate(140%);
  box-shadow:0 1px 2px rgba(35,38,52,.05),0 18px 34px -26px rgba(35,38,52,.5);
}
.links{border-radius:9px;background:rgba(35,38,52,.055)}
.links a{border-radius:6px;font-size:12px;letter-spacing:.02em}
.links a.on{
  background:rgba(255,255,255,.92);
  box-shadow:inset 0 0 0 1px var(--hairline);
  font-weight:600;
}
.av{border-radius:6px}
.nav-handle{border-radius:0 0 8px 8px;background:rgba(252,251,249,.94)}
.plus{border-radius:7px;box-shadow:0 6px 14px -8px rgba(47,102,144,.9)}
.icon-btn{border-radius:6px}

/* ─────────────────────── 6. 页头：刊头三层 ───────────────────────
   规范 §6.1 的刊头是三层的：eyebrow（衬线斜体大写 + 规线）→ 衬线 900
   大标题 → 拉开字距的一行小注。v2 只做了两层（一条短竖线 + 大标题），
   少了最上面那层"刊物名"，所以读起来还是"页面标题"而不是"一期的一页"。

   eyebrow 的文字不写在 HTML 里（那个文件不动），用伪元素 + CSS 变量取，
   poju-motion.js 在切路由时把栏目名写进 --eyebrow。 */
.top{padding:clamp(58px,5vw,74px) 0 20px}
.top .tt{position:relative}
.top .tt::before,
.pg-head .hl::before{
  content:var(--eyebrow,"教学工作台");
  /* inline-block 是这条的关键：盒子按文字收缩，规线才会紧跟在文字后面。
     写成 display:block 的话盒子占满整行，44px 的线会被甩到版心最右边，
     变成一条和文字毫无关系的横线。 */
  display:inline-block;
  font-family:var(--v2-serif);
  font-style:italic;font-weight:600;
  font-size:12px;letter-spacing:.3em;text-transform:uppercase;
  color:var(--blue);
  margin-bottom:13px;
  /* 44px 规线接在 eyebrow 后面（规范 §6.1）。用背景画而不是再插一个元素：
     文字长度会随栏目名变，线不能跟着变 —— 它度量的是"栏目记号"，
     不是文字宽度。padding-right 给线腾位置，right center 让它贴住这一块。 */
  background-image:linear-gradient(90deg,var(--accent-line),var(--accent-line));
  background-repeat:no-repeat;
  background-position:right center;
  background-size:44px 1px;
  padding-right:56px;
}
.top h1{
  font-family:var(--v2-serif);
  /* 尺寸收到 40px：50px 时首屏被标题吃掉一半，待办和日历都要往下滚才看得到。
     40px 仍然压得住页，但能把下面一行全露出来。 */
  font-size:clamp(28px,3.4vw,40px);
  font-weight:900;
  letter-spacing:.004em;
  line-height:1.22;
  white-space:normal;
  text-wrap:balance;
}
/* 问候语的第二句（"今天还有 2 件事。"）整句占一行。
   app.css 只在 ≤640 时这么干，这里提到全宽度：不这么做，这句话会跟着
   版心宽度在一行 / 两行之间反复横跳（1280 一行、1440 两行），两行时
   末行还只剩一个孤字。拆成"称呼一行、正事一行"，本来就是问候语该有的
   断法，也让 50px 的字号在每种宽度下都稳。 */
.top h1 em.wv{display:block}
/* 大标题里的那个句号：全页唯一"签名"（规范 §6.1 的 .dot）。
   由 poju-motion.js 给句尾那个"。"挂上 .sig。
   注意不能沿用破局的类名 .dot —— 工作台的 ui.css:439 里已经有一个
   .dot{width:6px;height:6px;border-radius:50%}（状态圆点），重名会把
   那个句号裁成 6×6 的一小块。 */
.top h1 .sig{color:var(--blue)}
/* 问候语后半句（"今天还有 2 件事。"）压成次级墨色，做成一句副题 */
.top h1 em,.top h1 em.wv{color:var(--ink3);font-weight:700;font-style:normal}
.top .sub{
  margin-top:11px;font-size:12px;letter-spacing:.16em;
  color:var(--ink4);text-transform:uppercase;
}
.search{
  border-radius:8px;width:236px;height:33px;
  background:rgba(255,255,255,.55);
  border:1px solid var(--hairline);
}
.search:focus-within{
  border-color:var(--blue);
  background:rgba(255,255,255,.85);
  box-shadow:0 0 0 3px rgba(47,102,144,.1);
}
.search input{font-size:12px;letter-spacing:.02em}

/* 内页刊头：同一套语法，只是字号降一档（内页标题是"栏目名"两个字，
   不需要首页那种语气；34px 衬线 900 已经足够把栏目立起来）。 */
.pg-head{padding:24px 0 18px}
.pg-head .hl{position:relative}
.pg-head h1{
  font-family:var(--v2-serif);
  font-size:clamp(28px,2.6vw,34px);font-weight:900;
  letter-spacing:.01em;line-height:1.22;
}
.pg-head .sub{
  margin-top:8px;font-size:12px;letter-spacing:.15em;color:var(--ink4);
}

/* ─────────────────────── 7. 指标带：四格通线 ───────────────────────
   全站改动最大的一处，也是最能看出"换了套设计"的地方：
   四张独立圆角卡 → 上下两根通线切出来的四格（像刊物里的数字条）。
   结构完全没变（还是 .kpis > .kpi×4），只是把卡片的"底"抽掉了。 */
.kpis{
  gap:0;
  margin-top:10px;
  padding:0;
  border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);
}
.kpis > .kpi{
  background:transparent;
  border:0;
  border-radius:0;
  box-shadow:none;
  padding:19px 22px 17px;
}
.kpis > .kpi + .kpi{border-left:1px solid var(--line)}
/* 悬停：不再整块上浮（通线会被带歪），改成极淡的一层底色 */
.kpis > .kpi:hover{background:rgba(47,102,144,.028)}
.kpis > .kpi.is-go:hover,
.kpis > .kpi.kpi-ring:hover{transform:none;box-shadow:none}
.kpis > .kpi .tilt::after{
  background:radial-gradient(220px circle at var(--mx,50%) var(--my,50%),
    rgba(47,102,144,.06),transparent 66%);
}
.kpis .kpi .kr{min-height:60px;margin:10px 0 4px}
/* 标签行：小字 + 大字距，页边注 */
.kpi .k{
  font-size:12px;letter-spacing:.18em;color:var(--ink4);
  text-transform:uppercase;font-weight:600;
}
.kpi .k u{font-size:12px;letter-spacing:.06em;color:var(--ok-text)}
/* 数字：衬线。这是全站"刊物感"最直接的来源 —— 数字一换衬线，气质就变了 */
.kpi .v{
  font-family:var(--v2-serif);
  font-size:31px;font-weight:600;letter-spacing:-.018em;
}
.kpi .v small{
  font-family:var(--v2-sans);font-size:12px;font-weight:500;
  letter-spacing:.04em;color:var(--ink4);margin-left:3px;
}
.kpis .kpi .v{min-width:60px}
.kpi .d{
  font-size:12px;letter-spacing:.02em;color:var(--ink3);line-height:1.65;
}
/* 环形卡：环的粗细和数字都往"图版"上靠。
   衬线数字比原版黑体宽，「29/32」两位数会顶出 62px 的环。
   注意 ui.css 在手机断点里有 .kpis .kpi .kr .mini-ring .rt b 的高权重写法，
   这里必须用同一条完整路径才能两头都压住。 */
.mini-ring .rt b{font-family:var(--v2-serif);font-weight:600;letter-spacing:-.02em}
.kpis .kpi .kr .mini-ring .rt b{font-size:14.5px}
.kpis .kpi .kr .mini-ring .rt small{font-size:12px;letter-spacing:0}
/* 手机断点：环盒缩到 44px（内半径≈15.5px），14.5px 的衬线数字半宽会溢出，
   补一档更小的字。同样用完整路径压住 ui.css 的同权重手机规则。 */
@media (max-width:640px){
  .kpis .kpi .kr .mini-ring .rt b{font-size:13px}
  .kpis .kpi .kr .mini-ring .rt small{font-size:12px}
}
@media (max-width:980px){
  .kpis > .kpi:nth-child(odd){border-left:0}
  .kpis > .kpi:nth-child(n+3){border-top:1px solid var(--line)}
}
@media (max-width:780px){
  .kpis > .kpi{padding:16px 16px 14px}
  .kpi .v{font-size:27px}
}

/* ─────────────────────── 8. 栏目头 ───────────────────────
   .card-h 是每张卡的第一行（标题 + 计数 + 全部→）。
   加一道下通线，卡片内部就有了"栏"的层次。 */
.card-h{
  padding:0 0 9px;margin:0 0 10px;
  border-bottom:1px solid var(--hairline);
}
.card-h h2{
  font-family:var(--v2-serif);
  font-size:14.5px;font-weight:800;letter-spacing:.03em;
}
.card-h .cnt{font-size:12px;letter-spacing:.1em;color:var(--ink4)}
.card-h .more{
  font-size:12px;letter-spacing:.1em;color:var(--blue);
  text-transform:uppercase;font-weight:600;
}
.tblwrap .card-h{margin:13px 0 10px}
.sec-h h2{font-family:var(--v2-serif);font-weight:800;letter-spacing:.02em}
.sec-h .cnt,.sec-h .num{letter-spacing:.12em;font-size:12px}

/* ─────────────────────── 9. 待办 / 事件 / 本周 ─────────────────────── */
.card{padding:17px 20px 16px}
/* 勾选框：圆 → 方。方形勾是"清单"，圆形勾是"开关" */
.tick{border-radius:3px;border-color:var(--check-line)}
.todo.done .tick{background:var(--blue);box-shadow:none}
.t-body b{font-size:13px;letter-spacing:0}
.t-body span{font-size:12px;letter-spacing:.02em}
.tag{
  border-radius:3px;font-size:12px;letter-spacing:.08em;padding:3px 6px;
  text-transform:uppercase;font-weight:600;
}
.tag.hot{background:rgba(168,57,43,.1);color:var(--red-text)}
.tag.today{background:var(--blue-soft);color:var(--blue)}
.tag.okt{background:rgba(44,111,71,.1);color:var(--ok-text)}
.todo-add{border-radius:7px;border-color:var(--hairline);font-size:12px;letter-spacing:.06em}
.todo-add:hover{border-color:var(--blue);color:var(--blue);background:rgba(47,102,144,.03)}

.ev-time{letter-spacing:.06em}
.ev-body p{font-size:13px;letter-spacing:0;line-height:1.7}
.ev-meta em{border-radius:3px;letter-spacing:.06em;font-size:12px}

.dnum b{font-family:var(--v2-serif);font-weight:700;font-size:18px;letter-spacing:-.01em}
.dnum span{font-size:12px;letter-spacing:.14em}
.wb b{font-size:13px;letter-spacing:0}
.wb em{font-size:12px;letter-spacing:.04em}

/* 学生覆盖热力格：底色那五档写死在 app.css 里（rgba(0,113,227,…)），
   不跟着 --blue 走，这里按档位重描一遍。 */
.board .kid{border-radius:4px}
.kid[data-l="0"]{background:rgba(184,115,36,.1);box-shadow:inset 0 0 0 1px rgba(184,115,36,.22)}
.kid[data-l="0"] b{color:#7d5312}
.kid[data-l="0"] em{color:rgba(125,83,18,.62)}
.kid[data-l="1"]{background:rgba(47,102,144,.06)}
.kid[data-l="2"]{background:rgba(47,102,144,.15)}
.kid[data-l="3"]{background:rgba(47,102,144,.32)}
.kid[data-l="4"]{background:var(--blue);box-shadow:0 3px 9px -6px rgba(47,102,144,.6)}
.kid b{letter-spacing:0}
.kid em{letter-spacing:.04em}
/* 图例的小方块是内联样式（heatLegend() 里写死的 #0071E3 / rgba(0,113,227,…)），
   内联只能靠 !important 压，这一处躲不掉。 */
.heat-ft .legend:nth-child(1) i{
  background:rgba(184,115,36,.12)!important;box-shadow:inset 0 0 0 1px rgba(184,115,36,.26)!important}
.heat-ft .legend:nth-child(2) i{background:rgba(47,102,144,.05)!important}
.heat-ft .legend:nth-child(3) i{background:rgba(47,102,144,.16)!important}
.heat-ft .legend:nth-child(4) i{background:rgba(47,102,144,.34)!important}
.heat-ft .legend:nth-child(5) i{background:#2f6690!important}
.legend i{border-radius:2px}
.legend span{letter-spacing:.06em;font-size:12px}

/* ─────────────────────── 10. 材料库表格 ───────────────────────
   这是最像"纸"的一块，只差一道字距：表头拉成小字距大写。 */
.tblwrap{padding:6px 20px 14px}
.tr{font-size:12px;letter-spacing:.02em}
.tr.head{
  font-size:12px;letter-spacing:.18em;color:var(--ink4);
  text-transform:uppercase;font-weight:600;padding:9px 0 8px;
}
.tr .nm2{font-size:13px;letter-spacing:0}
.tr .ty{border-radius:3px;font-size:12px;letter-spacing:.08em;background:rgba(35,38,52,.045)}
.tr .lk,.tr .wc,.tr .tm{letter-spacing:.04em}

/* ─────────────────────── 11. Copilot 条 / 写稿条 ─────────────────────── */
.adv-bar,.ai-bar{border-radius:var(--r-lg)}
.adv-ic{border-radius:6px;background:var(--blue-soft);color:var(--blue)}
.adv-tt b{font-family:var(--v2-serif);font-size:13px;font-weight:800;letter-spacing:.02em}
.adv-tt em{font-size:12px;letter-spacing:.04em;color:var(--ink4)}
.ai-bar .ic{border-radius:6px;background:var(--blue-soft);color:var(--blue)}
.ai-bar .t b{font-family:var(--v2-serif);font-size:13px;font-weight:800;letter-spacing:.02em}
.ai-bar .t em{font-size:12px;letter-spacing:.04em;color:var(--ink4)}
.ai-bar .t{letter-spacing:0}

/* ─────────────────────── 12. 按钮 / 控件 ───────────────────────
   胶囊 → 小圆角方块 + 拉开字距。全站的按钮语言一次换完。 */
.btn{
  border-radius:7px;
  letter-spacing:.09em;
  font-weight:600;
}
.btn.sm{border-radius:6px;font-size:12px;letter-spacing:.08em}
.btn.pri{background:var(--ink);box-shadow:0 8px 18px -12px rgba(35,38,52,.75)}
.btn.pri:hover{background:#31354a}
.btn.ghost{
  background:rgba(255,255,255,.58);
  border:1px solid var(--hairline);
  -webkit-backdrop-filter:none;backdrop-filter:none;
}
.btn.ghost:hover{background:rgba(255,255,255,.9)}
.btn.pale{background:rgba(35,38,52,.045)}
.btn.danger{background:rgba(168,57,43,.08);color:var(--red-text)}

/* 输入类控件：白纸底 + 发丝边 + 小圆角 */
.inp,.sel,.ta{
  border-radius:6px;
  border:1px solid var(--hairline);
  background:var(--field-2);
  letter-spacing:.01em;
}
.inp:focus,.sel:focus,.ta:focus{
  background:var(--field);
  border-color:var(--blue);
  box-shadow:0 0 0 3px rgba(47,102,144,.1);
}
.fld > label{font-size:12px;letter-spacing:.1em;color:var(--ink4);text-transform:uppercase}
/* 胶囊类：文种 chip / 分段 / 多选 */
.chip{border-radius:5px;letter-spacing:.02em}
.chip.on,.chip.gt.on{background:var(--blue);box-shadow:none}
.seg{border-radius:8px;background:rgba(35,38,52,.055)}
.seg .ind{border-radius:6px;box-shadow:0 1px 2px rgba(35,38,52,.1)}
.seg button{border-radius:6px;letter-spacing:.04em}
.chips.grp > .chip.gt{letter-spacing:.02em}

/* 弹层：一律白纸 */
.sheet{border-radius:14px 14px 0 0;background:rgba(252,251,249,.97)}
.sbox{border-radius:12px;background:rgba(252,251,249,.985);border:1px solid var(--hairline)}
.ms-in{border-radius:14px 14px 0 0;background:rgba(252,251,249,.985)}
.ms-a{border-radius:7px;font-size:13px;letter-spacing:.02em}
.ms-a.on{background:var(--blue);box-shadow:none}
.grip{border-radius:0}

/* ─────────────────────── 13. 页脚 ─────────────────────── */
.foot{
  margin-top:34px;padding-top:16px;
  font-size:12px;letter-spacing:.12em;color:var(--ink4);
  text-transform:uppercase;
}
.foot b{color:var(--ink3)}

/* ─────────────────────── 14. demo 标记 ─────────────────────── */
.v2-demo-tag{
  position:fixed;right:14px;bottom:14px;z-index:120;
  padding:6px 11px;border-radius:4px;
  background:rgba(252,251,249,.92);
  border:1px solid var(--hairline);
  box-shadow:0 8px 20px -14px rgba(35,38,52,.6);
  font-size:12px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--ink4);font-weight:600;
  pointer-events:none;
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
}
@media (max-width:780px){
  .v2-demo-tag{right:10px;bottom:10px;font-size:12px;padding:5px 9px;letter-spacing:.12em}
}

/* ─────────────────────── 15. 小尺寸兜底 ───────────────────────
   780px 以下现役会切成单列，页头字号也跟着降一档，上面已经写了几条；
   这里再补几处字距相关的（否则手机窄屏上拉开字距会顶到边）。 */
@media (max-width:780px){
  .top{padding:74px 0 16px}
  .top h1{font-size:23px;letter-spacing:-.008em}
  .top .sub{font-size:12px;letter-spacing:.12em}
  .pg-head h1{font-size:21px}
  .pg-head .sub{letter-spacing:.1em;font-size:12px}
  .card-h h2{font-size:13px}
  .search{width:100%;height:35px;border-radius:7px}
  .kpi .k{letter-spacing:.14em}
  .board .kid b{font-size:12px}
  .foot{letter-spacing:.08em}
}

/* ─────────────────── 16. 漏网的硬写死色（pass 2 补） ───────────────────
   这一节是拿计算样式全站扫出来的，不是看着猜的：
   逐路由遍历 DOM，读每个元素的 backgroundColor / boxShadow / backgroundImage，
   命中 rgba(0,113,227,…) 的只有下面这几处。
   现役里它们是直接写死苹果蓝的（没走 --blue），所以 token 一换它们不跟，
   在米白纸上就成了一块块发亮的天蓝 —— 单独补掉。 */
.kid .kav{
  color:var(--blue);
  background:rgba(47,102,144,.085);
  box-shadow:inset 0 0 0 1px rgba(47,102,144,.13);
}
.mv{
  border-radius:8px;                 /* 11px 在 32px 方块上偏圆，收一档 */
  color:var(--blue);
  background:rgba(47,102,144,.085);
}
.mtag{color:var(--blue);background:rgba(47,102,144,.085)}
.avgrid i:hover{box-shadow:0 0 0 2px rgba(47,102,144,.42)}

/* 成员页那排透明小片（.pk）原本是青绿→蓝的渐变，
   token 里 --sel-grad 已经收成单色，这里只把「开着」的那颗压平一点，
   别让它在纸面上跳出来 */
.pk{border-radius:6px;letter-spacing:.02em}
.pk.on{box-shadow:none}

/* ─────────────────── 17. 开关 ───────────────────
   motion.css:330 把 .sw.on 写成了 iOS 绿 #34C759（还带一圈绿光）。
   整站只有一个主色，这颗绿是全场唯一的"第三种颜色" ——
   换成本色；「已完成 / 两处都有」那些语义绿仍走 --ok，不动。 */
.sw.on{
  background:var(--blue);
  box-shadow:0 2px 8px -5px rgba(47,102,144,.9);
}
.sw.on:hover{box-shadow:0 0 0 4px var(--brand-100)}
.utag.adm{color:var(--blue);background:rgba(47,102,144,.085)}

/* ─────────────────── 18. 热力格的三处小修 ───────────────────
   档位越高底越深，格子里的字要跟着走，否则深格上的名字还算清楚、
   下面那行小数字就发灰了（那行是 <em>，现役统一给了 ink4）。
   另外首字圈（.kav）在深格上是「深蓝字压在浅蓝圈上」，
   到第 4 档（整格铺色）就彻底看不见了 —— 那一档反过来给白字。 */
.kid em{color:var(--ink3)}
.kid[data-l="2"] em,.kid[data-l="3"] em{color:var(--ink2)}
.kid[data-l="3"] .kav{background:rgba(255,255,255,.5);box-shadow:inset 0 0 0 1px rgba(47,102,144,.16)}
.kid[data-l="4"] b,.kid[data-l="4"] em{color:#fff}
.kid[data-l="4"] .kav{color:#fff;background:rgba(255,255,255,.17);box-shadow:inset 0 0 0 1px rgba(255,255,255,.22)}
/* 一档都没记的（琥珀）连首字圈一起收成琥珀调，别留一颗蓝珠子 */
.kid[data-l="0"] .kav{
  color:#7d5312;
  background:rgba(184,115,36,.1);
  box-shadow:inset 0 0 0 1px rgba(184,115,36,.22);
}

/* ─────────────────── 19. 使用情况页的四格 ───────────────────
   首页那条指标带是「通线切四格」，这一页的四格却是四张浮起来的小卡，
   同一个产品里两套语法。这里把它并到首页那套：
   抽掉卡底、四格之间只留竖线、上下各一条通线。 */
.usg-kpi{gap:0;margin-top:2px}
.usg-kpi > .kpi{
  background:transparent;border:0;border-radius:0;box-shadow:none;
  padding:15px 18px 13px;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
}
.usg-kpi > .kpi + .kpi{border-left:1px solid var(--line)}
.usg-kpi > .kpi:hover{background:rgba(47,102,144,.028)}
.usg-kpi .kpi .k{font-size:12px;letter-spacing:.16em;text-transform:uppercase;color:var(--ink4);font-weight:600}
.usg-kpi .kpi .v{font-family:var(--v2-serif);font-size:24px;font-weight:600;letter-spacing:-.014em}
@media (max-width:640px){
  .usg-kpi > .kpi:nth-child(odd){border-left:0}
  .usg-kpi > .kpi:nth-child(n+3){border-top:1px solid var(--line)}
}

/* ═══════════════════════════════════════════════════════════════════════
   §20 · 今天页：12 栏通铺（"一张纸上的四个栏目"）
   ---------------------------------------------------------------------
   这是这一版最主要的结构变化，也是用户说的「所有卡片铺开、不要层叠」。

   改之前：.board = 1.62fr / 1fr 两栏，每栏里的卡片再竖着往下堆。
           视觉上是两摞纸，读完上面才看下面，越往下越像"抽屉"。
   改之后：
     · .col-main / .col-side 用 display:contents 把包裹层"解掉"，
       四张卡直接变成 .board 的栅格项 —— HTML 一个字没改；
     · .board 自己升格成"一张纸"：玻璃底 + 22px 圆角 + 一层外阴影；
       四张卡抽掉各自的底/边/圆角/阴影，只用发丝线分区。
       这就是规范纪律①「全站只有一个面，卡里不套卡，分区只用发丝线」；
     · 2×2 铺开：待办 7 栏 / 事件 5 栏，学生 7 栏 / 本周 5 栏。
       四张卡同屏可见，不用滚。

   为什么不是四张并排：1440 宽减去侧栏和内距只剩 ~1080，
   四等分每张 260px，待办标题放两行就折了。2×2 是「铺开」和「可读」
   的交叉点。
   ═══════════════════════════════════════════════════════════════════════ */
@media (min-width:1080px){
  .board{
    display:grid;
    grid-template-columns:repeat(12,1fr);
    gap:0;
    /* ui.css 给 .board 写了 align-items:start（原来两栏各自独立堆叠时是对的），
       通铺之后必须改回 stretch：不然同一行的两张卡各自按内容高度收边，
       中间那条竖的发丝线就会在半空断掉，看起来像画错了的表格。 */
    align-items:stretch;
    margin-top:16px;
    background:var(--glass);
    border:1px solid var(--edge);
    border-radius:var(--r-lg);
    box-shadow:
      0 1px 1px rgba(35,38,52,.04),
      0 20px 48px -14px rgba(35,38,52,.18),
      inset 0 1px 0 rgba(255,255,255,.85),
      inset 0 -1px 0 rgba(35,38,52,.07);
    -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
    /* 四张卡都是透明底，圆角靠这一层裁，不用给每张卡单独算圆角 */
    overflow:hidden;
  }
  /* 解掉两个包裹层。display:contents 让子元素直接参与父级栅格，
     元素本身不生成盒子 —— 所以 .col-main 的 flex-direction 之类全部失效，
     这正是我们要的。 */
  .board > .col-main,
  .board > .col-side{display:contents}

  .board > .col-main > .card,
  .board > .col-side > .card{
    margin:0;
    padding:20px 24px 22px;
    background:none;
    border:0;
    border-radius:0;
    box-shadow:none;
    -webkit-backdrop-filter:none;backdrop-filter:none;
    /* 卡片自己变成竖向 flex：为了把"＋ 加一条"压到栏底（见下面那条）。
       原来卡片是 block，.todos 身上那句 ui.css:406 的 flex:1 是空转的。 */
    display:flex;flex-direction:column;
  }
  /* hover：规范要求"只加深不位移"。四格通铺里连阴影都不该有，
     改成极淡的一层白 —— 像手指按住这一栏时纸被压亮了一点。 */
  .board > .col-main > .card:hover,
  .board > .col-side > .card:hover{
    background:rgba(255,255,255,.24);
    box-shadow:none;
  }

  /* 2×2：DOM 顺序是 待办 → 事件 → 本周 → 学生，
     栅格按 7+5 排两行，正好错开，不用手动指定行号。 */
  .board > .col-main > .card:nth-child(1){grid-column:span 7;border-right:1px solid var(--hairline);border-bottom:1px solid var(--hairline)}
  .board > .col-main > .card:nth-child(2){grid-column:span 5;border-bottom:1px solid var(--hairline)}
  /* 日历搬出去之后，右栏只剩「学生覆盖」一张，让它独占第二行通铺 */
  .board > .col-side > .card:nth-child(1){grid-column:span 12;border-top:1px solid var(--hairline)}

  /* 通铺里四张卡并排，"学生覆盖"只分到 5 栏（约 450px），
     原来固定 8 列的格子会挤成一条，改成按最小宽度自动填。 */
  .board .kids{grid-template-columns:repeat(auto-fill,minmax(58px,1fr));gap:7px}

  /* 等高是 align-items:stretch 的代价：待办卡 5 条、事件卡 10 条，
     同一行被拉齐之后，左边会多出三百多像素空档，"＋ 加一条"就悬在
     这块空白的上沿 —— 看着像没对齐，而不是留白。
     ui.css:406 本来给 .todos 写了 flex:1，但卡片是 block，那句一直空转；
     这里把卡片改成 flex 列、让 .todos 真的长起来，再把按钮压到底边。
     空白就变成"栏末留白"，正是纸面分栏该有的样子。 */
  .board .todos{flex:1 1 auto;min-height:0}
  .board .todo-add{margin-top:auto}

  /* 关掉卡片自带的浮动。ui.css:282 / app.css:786 给 .col-side .card 挂了
     9~11.5 秒一轮的 cardFloat（translateY -5px 循环）—— 那是"卡片浮在
     雾上"时的小呼吸；现在四张卡是一张纸上被发丝线分开的四个格子，
     格子会自己上下动，整张纸就散架了。 */
  .board .card.in{animation:none!important}
}

/* 781~1179 的间距调整（16 → 20px）放在文件末尾那条 781~1179 里写。
   这里不能写：那条规则的 `.col-main,.col-side` 只有 (0,1,0)，
   会被下面 max-width:1179 里的 `.board > .col-main`(0,2,0) 压掉，
   结果两列之间 20px、列内 16px，横竖间距对不上。 */

/* ═══════════════════════════════════════════════════════════════════════
   §21 · 卡片编号 01 / 02 / 03
   ---------------------------------------------------------------------
   规范 §6.3：卡片标题前面挂一个衬线斜体序号，是"刊物章节号"的暗示，
   也是整套风格里成本最低、识别度最高的一处。
   编号只挂在今天页通铺的四栏上 —— 全站每张卡都编号就成了图鉴，
   那就不是刊物了。 */
.board{counter-reset:col}
.board .card{counter-increment:col}
.board .card-h h2::before{
  content:counter(col,decimal-leading-zero);
  font-family:var(--v2-serif);
  font-style:italic;font-weight:600;
  font-size:12px;letter-spacing:.02em;
  color:var(--blue);
  margin-right:11px;
  font-variant-numeric:tabular-nums;
}

/* ═══════════════════════════════════════════════════════════════════════
   §22 · 动效（规范 §7 的清单，落到工作台已有的组件上）
   ---------------------------------------------------------------------
   工作台本来就有入场（ui.css 的 rvIn：26px + blur(6px) + .9s），
   但那是"现代 App 的浮入"：位移大、时间长、带模糊，读起来软。
   破局要的是 10px / .55s 的"抬一下就有"。

   注意这里**没有**做规范 §7 的第 4 条（指针迎光）和第 8 条（磁吸）：
   用户明确要求取消电脑端跟随光标的特效。第 8 条被显式关掉，见 22.5。
   ═══════════════════════════════════════════════════════════════════════ */

/* 22.1 rise：10px + .55s --ease-x。卡片 0 / .07 / .14 三档错峰 */
.rv.in{animation:pojuRise .55s var(--ease-x) both}
@keyframes pojuRise{
  from{opacity:0;transform:translateY(10px)}
  to{opacity:1;transform:none}
}
.rv.d1{animation-delay:.07s}.rv.d2{animation-delay:.14s}
.rv.d3{animation-delay:.21s}.rv.d4{animation-delay:.28s}

/* 22.2 逐字刊头 chIn：
   每个字从 translateY(.55em) + rotate(2.5deg) + blur(5px) 归位。
   工作台把逐字放在 h1 的 em.wv 里（app.js 的 spell() 逐字拆开），
   这里只换参数 —— 原来 15px/无旋转/.62s，现在是"字从纸下翻上来"。 */
.tt h1 em.wv i{animation:pojuChIn .72s var(--ease-x) both}
@keyframes pojuChIn{
  0%{opacity:0;transform:translateY(.55em) rotate(2.5deg);filter:blur(5px)}
  100%{opacity:1;transform:none;filter:blur(0)}
}

/* 22.3 规线生长 ruleIn：eyebrow 后面那根 44px 线从左边长出来 */
.top .tt::before,.pg-head .hl::before{
  animation:pojuRule .8s var(--ease-x) .35s both;
  transform-origin:left center;
}
@keyframes pojuRule{
  from{background-size:0 1px}
  to{background-size:44px 1px}
}

/* 22.5 磁吸下线（用户要求：不要跟随光标）。
   motion.js 每帧往 .btn 上写 --mgx/--mgy，内联样式压不过 !important，
   这两行就能把位移锁死在 0，同时保留 --lift / --press 那两条正规的反馈。 */
.btn{--mgx:0px!important;--mgy:0px!important}

/* 22.6 按钮按下去：translateY(1px) scale(.96)。
   规范 §6.6 里这条是"手电气"的根，不能只剩一个 scale(.965)。 */
.btn:active,.btn.btn:active{
  transform:translate3d(0,0,0) translateY(1px) scale(.96)!important;
}

/* 22.7 主按钮扫光：105deg、22% 白、.55s，只在 hover 走一次（规范 §7-9） */
.btn.pri{position:relative;overflow:hidden}
.btn.pri::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(105deg,transparent 32%,rgba(255,255,255,.22) 50%,transparent 68%);
  transform:translateX(-130%);
}
@media (hover:hover){
  .btn.pri:hover::after{animation:pojuSweep .55s var(--ease-x)}
}
@keyframes pojuSweep{
  from{transform:translateX(-130%)}
  to{transform:translateX(130%)}
}

/* 22.8 涟漪（规范 §7-7）：JS 负责插入 span.ripple 并按"指尖到最远角"定直径、
   定位到真实点击坐标，这里只管形状与扩散。

   底色用径向渐变而不是纯色：纯色在 67×33 这种扁按钮上，圆一旦比按钮高
   就是整块均匀提亮，读起来是"按钮闪了一下"，没有"一圈光从指尖推开"的形。
   中心亮、边缘淡，即使圆已经盖满按钮，亮斑仍然钉在点击点，方向感才在。
   峰值定在 .55（上一版 .40 实测只把 #232634 提到 #444651，画面上几乎读不出）。 */
.ripple{
  position:absolute;border-radius:50%;pointer-events:none;
  background:radial-gradient(circle at center,
    rgba(246,245,241,.55) 0%,
    rgba(246,245,241,.34) 58%,
    rgba(246,245,241,.14) 100%);
  transform:translate(-50%,-50%) scale(0);
  /* 曲线用 --ease-x（起步就冲、末端收住）：涟漪要"啪"地散开再慢慢褪，
     用对称曲线会卡在小圈上。透明度单独用关键帧压，不跟着曲线的形状走。 */
  animation:pojuRipple .62s var(--ease-x) forwards;
}
/* 浅色控件（ghost / pale / 待办加号）上是深色涟漪，透明度只有深色按钮的一半：
   墨色 .26 压在纸上就已经很明显，再重就脏了。 */
.btn.ghost .ripple,.btn.pale .ripple,.todo-add .ripple{
  background:radial-gradient(circle at center,
    rgba(35,38,52,.24) 0%,
    rgba(35,38,52,.15) 58%,
    rgba(35,38,52,.06) 100%);
}
@keyframes pojuRipple{
  0%{transform:translate(-50%,-50%) scale(0);opacity:.95}
  55%{opacity:.8}
  100%{transform:translate(-50%,-50%) scale(1);opacity:0}
}

/* 22.9 Toast：深色磨砂玻璃（规范 §6.12），不是 iOS 黑胶囊 */
.toast{
  border-radius:9px;
  background:rgba(35,38,52,.78);
  border:1px solid rgba(255,255,255,.16);
  -webkit-backdrop-filter:blur(20px) saturate(160%);
  backdrop-filter:blur(20px) saturate(160%);
  color:#f4f3ef;font-size:13px;font-weight:500;letter-spacing:.03em;
  padding:11px 18px;
  transform:translate(-50%,12px);
  transition:opacity .3s,transform .32s var(--ease-q);
  box-shadow:0 14px 34px -18px rgba(35,38,52,.7);
}
.toast.on{transform:translate(-50%,0)}

/* 22.10 等待态：主按钮提交中，一道 38% 白光横扫（规范 §7-10）。
   is-busy 是破局自己的类名；工作台用的是 aria-busy + .btn[disabled]，
   两个都覆盖，谁先出现都能对上。 */
.btn.pri.is-busy,.btn.pri[aria-busy="true"]{
  color:transparent;
  background:var(--ink);
}
.btn.pri.is-busy::before,.btn.pri[aria-busy="true"]::before{
  content:"";position:absolute;top:0;bottom:0;left:-60%;width:220%;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.38) 45%,transparent);
  animation:pojuBusy 1.15s linear infinite;
}
@keyframes pojuBusy{
  from{transform:translateX(-45%)}
  to{transform:translateX(45%)}
}

/* 22.11 降级：不是可选项（规范 §7 末）。
   工作台自己的 @media reduce 散在四份 CSS 里，这里补一条总兜底，
   连新增的涟漪/扫光/规线一起关掉。 */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;
    animation-iteration-count:1!important;
    transition-duration:.01ms!important;
  }
  .btn.pri::after{display:none}          /* 扫光 */
  .ripple{display:none}                  /* 涟漪 */
  .top .tt::before,.pg-head .hl::before{background-size:44px 1px} /* 规线直接给终态 */
}

/* ═══════════════════════════════════════════════════════════════════════
   §23 · 触屏与窄屏降级（规范 §9 那张表）
   ═══════════════════════════════════════════════════════════════════════ */
@media (pointer:coarse){
  /* iOS 上 background-attachment:fixed 会抖，雾底改回 scroll */
  html{background-attachment:scroll}
  /* 移动端 blur 很贵：44px → 26px（规范 §9 指名这一档） */
  :root{--blur:blur(26px) saturate(170%)}
  body::after{opacity:.22}
}

/* 通铺在窄屏必须散掉，否则 12 栏会挤成一条线。
   1180 以下 ui.css 本来就把 .board 收成单栏（788 行），这里只补一条兜底，
   防止将来有人调断点时漏掉。 */
@media (max-width:1179px){
  .board{display:grid;grid-template-columns:1fr}
  /* 间距一律交给 ui.css 的 16px（604 / 605 行），这里不重复写 gap：
     写了就会把下面 781~1179 那条的 20px 压掉，出现"横 20 竖 16"的错位。 */
  .board > .col-main,.board > .col-side{display:flex;flex-direction:column;min-width:0}
  .board .card-h h2::before{font-size:12px;margin-right:8px}
}

/* 781~1179：没有右侧栏，两栏铺得开，间距从 16px 提到 20px
   —— 规范 §6.4 的卡片间距是 20px，16px 偏挤。
   必须写在上面那条之后、并且用 `.board >` 前缀对齐特异性，
   否则会被 `.board > .col-main{...}` 压回 16px。 */
@media (min-width:781px) and (max-width:1179px){
  .board{gap:20px}
  .board > .col-main,.board > .col-side{gap:20px}
}

/* 560 以下：eyebrow 的字距要收（规范 §9：10.5px / .16em，规线缩到 26px） */
@media (max-width:560px){
  .top .tt::before,.pg-head .hl::before{
    font-size:12px;letter-spacing:.16em;
    padding-right:38px;
    background-size:26px 1px;
  }
  .top h1{font-size:clamp(26px,7.2vw,34px)}
  .pg-head h1{font-size:26px}
}

/* ═══════════════════════════════════════════════════════════════════════
   §24 · B 方案：把破局的「骨架」搬过来（撤销 §20 的四卡通铺）
   ---------------------------------------------------------------------
   为什么还有这一节 —— 前一轮只搬了「皮」（雾底、玻璃、衬线、发丝线、
   字距、动效），A/B 采样证明两边背景完全同值 (227,223,234)、字体族同一
   串，但用户仍然说「完全不一样」。差异全部在版面：

     指标          破局原版            v3（§20 通铺）
     版心宽度      680px（占 47%）     1072px（占 74%，加侧栏 91%）
     页内距        40 / 20 / 120       0 / 0 / —
     页面总高      954px（1.06 屏）    2275px（2.53 屏）
     正文          16px / 1.75         14.5px / 1.68，外加 -.058px 负字距
     h1 字距       2.52px（.045em）    0.2px（.004em）—— 差 12 倍
     h1 行高       1.02               1.22
     卡片内距      26 / 26 / 28        20 / 24 / 22

   也就是说：破局的气质八成来自**版面纪律**，一条都没搬。另外三件
   「后台语法」是致命的 —— 232px 竖排侧栏、四栏 KPI（大数字 + 竖线 +
   环）、5 列材料表格。破局全篇没有同类物：它的导航是几个 15px 文字
   Tab，数字是页边注小字，列表是记录行。§20 把四张卡压成「一张纸上的
   2×2 发丝线网格」也是自创的（规范 §5 写的是每张卡各一块独立玻璃、
   纵向 20px 排），压成格子立刻被读成表格。

   本节只写 CSS，一个字节的业务文件都没动：
     · 侧栏只是不显示（CSS 断点），DOM 还在，JS 里 .side-new 之类的
       选择器只是选不到元素，不会报错；
     · 13 个栏目一个都没丢 —— 顶部 Tab 给最常用的 6 个，
       其余 11 个仍在「全部功能」抽屉里（#moreBtn → MORE 列表）；
     · 四张卡的 DOM 结构（.board > .col-main×2 / .col-side×2）原样，
       只是不用 display:contents 把它们压进同一张栅格。

   保留 §20 不删：万一要退回「一屏看全」的版本，删掉本节即可。
   ═══════════════════════════════════════════════════════════════════════ */

/* ── 24.1 版心与页内距（规范 §4） ─────────────────────────────────────
   680px → 760px：这是相对规范唯一一处**有意的**偏离。规范那句「再宽一行
   中文超过 38 字，眼睛就累了」针对的是纯阅读页面；工作台每张卡里要放
   待办标题 + 标签 + 时间三种信息，680 会把「家长沟通记录」这类标题挤到
   换行。760 是「一行 36~38 字」的上限附近，读起来仍是刊物栏宽。
   页内距照抄规范：上 40 / 下 120（下留白是给「翻页感」的）。 */
.wrap{
  max-width:760px;
  padding:40px 20px 120px;
}

/* ── 24.2 排版纪律（规范 §3） ────────────────────────────────────────
   规范里这是三条硬指标，之前一条都没落地：
     · 正文 16px / 1.75 —— 之前 14.5 / 24.36（1.68），并且 body 上还压着
       一个 -.058px 的负字距，中文加负字距会让字挤成一团；
     · h1 字距 .045em、行高 1.02 —— 之前 .004em / 1.22，刊头的「压得住
       一页」全靠这两条，字距差 12 倍，气质就完全不同；
     · 卡片标题 21px / 700 / 0 / 1.28 —— 之前 14px + 正字距。 */
body{
  font-size:16px;
  line-height:1.75;
  letter-spacing:0;              /* 撤掉 -.058px */
}
.top h1{
  letter-spacing:.045em;
  line-height:1.02;
}
/* 卡片标题：规范 §6.3 的 h3 规格。序号（01/02）由 §21 用伪元素挂在前面，
   字号要跟着抬到 12px，否则压在 19px 的中文边上是颗灰点。 */
.card-h h2{
  font-size:19px;
  font-weight:700;
  letter-spacing:0;
  line-height:1.28;
}
.card-h h2::before{font-size:12px;margin-right:12px}
/* 卡片内部那道标题下划线撤掉：四张卡现在是各自一块独立玻璃，卡与卡之间
   已经有 20px 空气和各自的边，标题下面再压一根线就成了「表格表头」。 */
.card-h{
  padding:0 0 8px;
  margin:0 0 6px;
  border-bottom:0;
}
.card-h .cnt{font-size:12px;letter-spacing:.16em}
.card-h .more{font-size:12px;letter-spacing:.14em}

/* 卡片内距与圆角：规范 §5 的 26 / 26 / 28（下比上多 2px，视觉重心才不
   会往下坠）。全站统一 —— 内页的卡片也一起变，否则从今天页点进去像换
   了个产品。 */
.card{
  padding:26px 26px 28px;
  border-radius:22px;
}

/* ── 24.3 侧栏退役 → 顶部文字 Tab（规范 §6.2） ────────────────────────
   破局的导航是三个 15px 的文字 Tab，底下一条发丝线，选中的挂 2px 蓝线。
   工作台在桌面是 232px 的竖排侧栏 + 药丸底槽，这是「后台」最典型的
   形状，一进页面就先被读成控制台。

   做法：桌面把 .side 关掉，把窄屏那条 .nav 从「浮在顶部、滚动收起」改成
   「页面顶上的一条静态横带」。不碰 JS —— .nav 里本来就有那 6 个链接的
   <a>，JS 加的 .compact / .hide 状态在这里一并压平（静态横带不需要收起，
   收起会让内容在滚动时跳动）。

   ⚠️ 断点用 1080 而不是 ui.css 的 1180：1180 是「侧栏什么时候出现」的值，
   不是破局的值。骨架层（§4 侧栏皮肤、§20 通铺、§24.3、§24.4）统一挂在
   1080 上，否则 1080~1179 这一档（常见的小笔记本视口）会掉回浮动胶囊
   导航 + 两栏 grid，宽一点窄一点就换一张脸。版心 760 + 左右各 20 = 800，
   1080 放得下。 */
@media (min-width:1080px){
  .side{display:none}
  .main{margin-left:0}

  .nav{
    /* ui.css:151 在同一个断点里把 .nav 关掉了（桌面走侧栏），这里必须显式
       打开，否则侧栏退役之后顶部就是空的 —— 整页只剩刊头，没有导航。 */
    display:block;
    position:static;
    padding:0;
    transition:none;
  }
  /* 静态状态下不收起、不缩身：这两条都是「浮动胶囊」的语法 */
  .nav.hide{pointer-events:auto}
  .nav.hide .nav-in{transform:none;opacity:1;pointer-events:auto}
  .nav-handle{display:none}

  .nav-in{
    max-width:760px;
    margin:0 auto;
    padding:26px 20px 0;
    gap:10px;
    align-items:flex-end;
    background:none;
    border:0;
    /* 下沿这道线就是破局 .tabs 的那条 —— 它同时把「导航」和「正文」分开 */
    border-bottom:1px solid var(--hairline);
    border-radius:0;
    box-shadow:none;
    -webkit-backdrop-filter:none;backdrop-filter:none;
    transition:none;
  }
  .nav.compact{padding:0}
  .nav.compact .nav-in{
    max-width:760px;
    padding:26px 20px 0;
    background:none;
    border:0;
    border-bottom:1px solid var(--hairline);
    border-radius:0;
    box-shadow:none;
    -webkit-backdrop-filter:none;backdrop-filter:none;
  }
  /* 头像那一块在刊头里是重复的（h1 已经在说「早安，林老师」），撤掉 */
  .nav .id{display:none}

  .links{
    flex:1 1 auto;
    gap:26px;
    margin:0;
    padding:0;
    background:none;
    border-radius:0;
    box-shadow:none;
  }
  .links a{
    padding:0 0 12px;
    font-size:16px;
    font-weight:500;
    letter-spacing:.01em;
    color:var(--ink3);
    background:none;
    border-radius:0;
    box-shadow:none;
  }
  .links a:hover{color:var(--ink);background:none}
  .links a:active{transform:none}
  .links a.on{
    color:var(--ink);
    font-weight:600;
    background:none;
    box-shadow:none;
    position:relative;
  }
  .links a.on::after{
    content:"";
    position:absolute;left:0;right:0;bottom:-1px;height:2px;
    background:var(--blue);
  }
  /* 三个按钮：从「蓝色实心圆 + 药丸」退回没底的小图标，贴着 Tab 的基线。
     它们是功能，不能删，但也不该抢刊头的注意力。＋ 原来是蓝色实心圆，
     在这条刊头里像个按钮贴纸，改成一根发丝线框出来的方框（印刷里的「框」）。 */
  .plus,.icon-btn{
    width:26px;height:26px;
    margin-bottom:8px;
    border-radius:4px;
    box-shadow:none;
  }
  .plus{
    background:none;
    border:1px solid var(--hairline);
    color:var(--ink2);
  }
  .plus:hover{background:rgba(35,38,52,.05);color:var(--ink);transform:none;box-shadow:none}
  .plus:active{transform:none}
  .icon-btn{color:var(--ink4)}
  .icon-btn:hover{color:var(--ink);background:rgba(35,38,52,.05)}

  /* 刊头：顶部已经有导航带，页头不用再让 74px 出来。规范 .hd 是 8px 起 */
  .top{padding:6px 0 28px}
  /* 搜索框缩成页边注，挪到 eyebrow 那一行的右侧 —— 破局的刊头右上是空的，
     一块 236px 的药丸会立刻把「刊物」拽回「应用」。 */
  .top{display:block;position:relative}
  .search{
    position:absolute;right:0;top:10px;
    width:186px;height:28px;
    border-radius:6px;
  }
  .search input{font-size:12px}
}

/* ── 24.4 四张卡：各自一块玻璃，纵向铺开（规范 §5） ────────────────────
   这一条是对 §20 的正面撤销。§20 里 .board 自己变成「一张纸」，四张卡
   display:contents 摊上去，用发丝线切 2×2 —— 用户要的「铺开不要层叠」
   被实现成了「一张表格」。规范 §5 写得很直白：每张卡各一块玻璃，
   margin-bottom 20px，纵向排。「全站只有一个面」说的是**卡片不套卡片**，
   不是**整页只有一张纸**。

   撤销清单（每条都对着 §20 的一行写，靠层叠覆盖，不改旧块）：
     .board           grid 12 栏 + 玻璃底 → flex 纵向
     .col-main/side   display:contents   → 普通 flex 列
     .card            抽掉底/边/圆角     → 还原全副玻璃
     :nth-child(1/2)  grid-column + 分区线 → 归零
     :hover           一层白            → 只加深阴影、不位移 */
@media (min-width:1080px){
  .board{
    display:flex;
    flex-direction:column;
    gap:20px;
    align-items:stretch;
    margin-top:0;
    background:none;
    border:0;
    border-radius:0;
    box-shadow:none;
    -webkit-backdrop-filter:none;backdrop-filter:none;
    overflow:visible;
  }
  .board > .col-main,
  .board > .col-side{
    display:flex;
    flex-direction:column;
    gap:20px;
    width:100%;
    min-width:0;
  }
  .board > .col-main > .card,
  .board > .col-side > .card{
    margin:0;
    padding:26px 26px 28px;
    border-radius:22px;
    background-color:var(--glass);
    /* §3 那条 180deg 高光带：玻璃上沿有一点亮，卡才有厚度 */
    background-image:linear-gradient(180deg,rgba(255,255,255,.12),rgba(255,255,255,0) 32%);
    border:1px solid var(--edge);
    box-shadow:
      0 1px 1px rgba(35,38,52,.04),
      0 20px 48px -14px rgba(35,38,52,.18),
      inset 0 1px 0 rgba(255,255,255,.85),
      inset 0 -1px 0 rgba(35,38,52,.07);
    -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
    display:block;
  }
  /* 归零 §20 的 2×2 分区：:nth-child(n) 的特异性与 :nth-child(1|2) 相同
     （都是 0,4,0），写在后面就能压住那两条 border-right / border-bottom。
     不这么写，四张卡的右边和下边会各多一根发丝线，看起来像没切干净的格子。 */
  .board > .col-main > .card:nth-child(n),
  .board > .col-side > .card:nth-child(n){
    grid-column:auto;
    border:1px solid var(--edge);
  }
  /* hover：规范 §5「只加深、不位移」 */
  .board > .col-main > .card:hover,
  .board > .col-side > .card:hover{
    transform:none;
    background-color:rgba(255,255,255,.5);
    box-shadow:
      0 1px 1px rgba(35,38,52,.04),
      0 26px 56px -14px rgba(35,38,52,.22),
      inset 0 1px 0 rgba(255,255,255,.85),
      inset 0 -1px 0 rgba(35,38,52,.07);
  }
  /* 卡片不再是等高格子，「把加号压到栏底」的两条就没有对象了，复位 */
  .board .todos{flex:0 0 auto}
  .board .todo-add{margin-top:14px}
}

/* ── 24.5 KPI：四栏卡 → 页边注数字条（规范 §6.4） ──────────────────────
   破局里没有「指标卡」这种东西，数字是排在页边的小字。§7 已经把卡片的
   底抽掉、换成上下两根通线 + 四格，方向是对的，但还留着三件后台语法：
     · 31px 的数字（比卡片标题 14px 大一倍多，一进页面眼睛先看数字）；
     · 62px 高的主体行，把数字条撑成一排「卡」；
     · 「学生覆盖」那个 62px 的进度环 —— 环是仪表盘，不是刊物。
   这里全部收掉：数字降到 20px 衬线、主体行归零、环换成文字分数（29/32）。
   数据一个没少，只是从「图表」变回「排版」。 */
.kpis{
  display:grid;
  grid-template-columns:repeat(4,1fr);
  gap:0;
  margin-top:0;
  padding:0;
  border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);
}
.kpis > .kpi{
  display:block;
  padding:13px 20px 12px;
  background:transparent;
  border:0;
  border-radius:0;
  box-shadow:none;
  transform:none;
  transition:none;
}
.kpis > .kpi + .kpi{border-left:1px solid var(--line)}
.kpis > .kpi:hover,
.kpis > .kpi.is-go:hover,
.kpis > .kpi.kpi-ring:hover{
  background:rgba(47,102,144,.028);
  transform:none;
  box-shadow:none;
}
.kpis > .kpi:active{transform:none}
.kpi .k{
  font-size:12px;letter-spacing:.2em;font-weight:600;
  color:var(--ink4);text-transform:uppercase;
  display:block;
}
.kpi .k u{font-size:12px;letter-spacing:.1em}
/* 主体行：从「62px 高的 flex 行」收回成普通的一行字 */
.kpis .kpi .kr{
  display:block;
  min-height:0;
  margin:6px 0 0;
}
/* 特异性要写成 .kpis .kpi .v（0,3,0）：ui.css:319 就是三段的，且带
   font-size:var(--fs-xl)=24px。写成 .kpi .v（0,2,0）会被它压住，
   数字条就退回「后台仪表盘」那个 24px 大数字的体量了。 */
.kpis .kpi .v{
  display:block;
  min-width:0;
  margin:0;
  font-family:var(--v2-serif);
  font-size:20px;
  font-weight:600;
  line-height:1.15;
  letter-spacing:-.01em;
}
.kpi .v small{font-family:var(--v2-sans);font-size:12px;font-weight:500;color:var(--ink4)}
.kpi .d{
  margin:4px 0 0;
  font-size:12px;
  line-height:1.6;
  letter-spacing:.02em;
  color:var(--ink4);
  -webkit-line-clamp:2;
}
/* 环 → 分数。dial 是 conic-gradient 画的圆弧，直接不显示；
   .rt 从绝对居中的圆环内芯变回一个行内基线盒，数字沿用衬线。 */
.kpi-ring .mini-ring{position:static;width:auto;height:auto;flex:none}
.kpi-ring .mini-ring .dial{display:none}
.kpi-ring .mini-ring .rt{
  position:static;inset:auto;
  display:inline-flex;align-items:baseline;justify-content:flex-start;gap:1px;
}
.kpis .kpi .kr .mini-ring .rt b{font-size:20px;font-weight:600;line-height:1.15}
.kpis .kpi .kr .mini-ring .rt small{font-size:12px;letter-spacing:0;color:var(--ink4)}
/* 窄屏：四格仍然铺四格，但内距收一档（数字条在手机上本来就窄） */
@media (max-width:780px){
  /* 780 以下四格并排只剩 87px 一格，字会挤成竖条 —— 回到 2×2。
     这条必须写在这里：§24 的 .kpis 是全局无条件的，会压掉 ui.css 那条
     手机断点（同特异性、但它在前）。 */
  .kpis{grid-template-columns:repeat(2,1fr)}
  .kpis > .kpi{padding:12px 14px 11px}
  .kpis > .kpi:nth-child(odd){border-left:0}
  .kpis > .kpi:nth-child(n+3){border-top:1px solid var(--line)}
  /* 同上：三段选择器，才压得住 ui.css:319 的 --fs-xl */
  .kpis .kpi .v{font-size:18px}
  .kpis .kpi .kr .mini-ring .rt b{font-size:18px}
  /* 手机上版心就是屏幕宽，26px 的卡片内距太吃字：收到 20 / 18 */
  .card{padding:20px 18px 22px}
  .wrap{padding:40px 16px 96px}
}
@media (max-width:560px){
  /* 刊头在手机上要还回破局那种「压得住一屏」的分量（9vw ≈ 35px@390） */
  .top h1{font-size:clamp(28px,8.6vw,40px)}
}

/* ── 24.5b 中间档（561~1079）── 这一段之前是空的 ───────────────────────
   实测验出来的两个断层，都只在「平板 / 半屏浏览器」这一档出现：

   1) 刊头 h1 掉到 23px（§15 那条 max-width:780 的兜底），比手机上
      的 33.5px 还小 —— 大屏小字，整页的分量全丢了。
   2) .top 在 561~640 仍是 ui.css 的 flex 行（它 ≤640 才转列），而 .search
      在 ≤780 被写成 width:100%，于是搜索框把标题挤到 180px 宽：
      768 下「早安，林老师。今天还有 2 件事。」被折成四行，搜索框还顶出
      版心右边界（overflow 实测 ['search','INPUT']）。

   做法：这一段统一按列排（标题独占一行、搜索框缩成标题下方一枚 240px 的
   页边注），字号给一条连续斜坡 —— 561→39px、768→46px、1079→46px，
   正好接上 1080 起的 clamp(32, 4.2vw, 50)=45.4px，不跳。
   上限卡在 561 是有意的：≤560 交给上面那条 8.6vw（手机上要更凶一点）。 */
@media (min-width:561px) and (max-width:1079px){
  .top{display:block}
  .top h1{font-size:clamp(30px,7vw,46px)}
  .top .search{width:240px;max-width:100%;height:34px;margin-top:14px}
  .pg-head h1{font-size:clamp(24px,4.4vw,36px)}
}

/* ── 24.6 材料库：5 列表格 → 记录行（规范 §8） ─────────────────────────
   规范 §8 的记录行是「无表格边框的排版块」：标题一行衬线，元信息一行小字，
   行与行之间一根发丝线。原来是 1fr/104/82/72/80 五列硬对齐 + 表头 ——
   那是最标准的后台表格，五根视觉竖线一出现，"刊物"就没了。
   改成两行：名称（衬线 15.5）+ 元信息（10px 大字距，用 · 分隔）。
   表头整行不显示 —— 元信息自带标签（关联 / 字数 / 更新），表头就是多余的。 */
.tblwrap{padding:26px 26px 14px}
.tblwrap .card-h{margin:0 0 6px;padding:0 0 8px}
.tr{
  display:flex;
  flex-wrap:wrap;
  align-items:baseline;
  gap:5px 16px;
  padding:15px 0 14px;
  border-bottom:1px solid var(--hairline);
  background:none;
  font-size:12px;
  letter-spacing:.02em;
  transition:none;
}
.tr.head{display:none}
.tr:not(.head):hover{background:transparent}
.tr .nm2{
  flex:1 1 100%;
  min-width:0;
  font-family:var(--v2-serif);
  font-size:16px;
  font-weight:600;
  letter-spacing:.01em;
  display:flex;
  align-items:center;
  gap:8px;
}
.tr .nm2 .kbind{
  font-family:var(--v2-sans);
  font-style:normal;
  font-size:12px;
  font-weight:500;
  letter-spacing:.12em;
  color:var(--ink4);
}
.tr .ty{
  font-size:12px;
  font-weight:600;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--blue);
  background:none;
  padding:0;
  border-radius:0;
  white-space:nowrap;
}
.tr .lk,.tr .wc,.tr .tm{
  font-size:12px;
  letter-spacing:.08em;
  color:var(--ink4);
  text-align:left;
  font-variant-numeric:tabular-nums;
}
/* 元信息自带标签，取代被撤掉的表头 */
.tr .lk::before{content:"关联 ";letter-spacing:.1em}
.tr .wc::before{content:"字数 ";letter-spacing:.1em}
.tr .tm::before{content:"更新 ";letter-spacing:.1em}
.tr:last-child{border-bottom:0;padding-bottom:4px}

/* ── 24.7 卡内正文的字号：把「密度」从 2.4 倍降回 1 倍 ─────────────────
   规范 §3 的卡片正文是 17px / 1.9，工作台是 12.5px —— 版心收到 760 之后，
   12.5px 的字在 720px 的栏里会显得又小又空（这也是"不像"的一部分：
   破局的字大、行松、留白多）。这里按层级各抬一档，不改变任何结构。 */
.t-body b{font-size:14.5px;line-height:1.55}
.t-body span{font-size:12px}
.ev-body p{font-size:14.5px;line-height:1.75}
.wb b{font-size:14.5px}
.wb em{font-size:12px}
.dnum b{font-size:19px}
.adv-tt b{font-size:14.5px}
.adv-tt em{font-size:12px}
.ai-bar .t b{font-size:14.5px}

/* ── 24.8 节奏 ────────────────────────────────────────────────────────
   ui.css 给 #view 的直接子元素补 13px（那是"卡片瀑布"的节奏）。破局的
   节奏是 20px，且卡片之间由 .board 的 gap 承担。 */
#view > * + *{margin-top:20px}

/* ── 24.9 按钮：去掉那圈「App 味的投影」 ──────────────────────────────
   ui.css:273 给主按钮挂了 0 8px 24px -12px rgba(0,0,0,.6)，深色按钮下面
   糊一团黑雾 —— 在一张纸上，按钮应该是印上去的一块墨，不是浮起来的塑料。
   破局全站按钮都是平的（规范 §7 里按钮的反馈只有按压位移和一圈涟漪）。 */
.btn.pri{box-shadow:0 1px 2px rgba(35,38,52,.16)}
.btn.pri:hover{box-shadow:0 2px 8px -3px rgba(35,38,52,.3)}
.btn.ghost,.btn.pale{box-shadow:none}

/* ═══════════════════════════════════════════════════════════════════════
   §25 · 首屏账：把版心放开，让「今天」在第一屏就说完
   ═══════════════════════════════════════════════════════════════════════
   §24 把骨架换成了破局的刊物体（760 版心 / 单栏纵向），骨架对了，但
   落到工作台上撞了两件事：

   一是版心太窄。760 是「一篇纯阅读文章」的栏宽，1200 以上的显示器上它
   只占 43%~50%，左右两大片空场，卡片里每行字又短又碎，读起来是把手
   机版原样摊在大屏上。破局的 680 之所以成立，是因为它一屏只有一篇文章；
   工作台一屏要同时放待办、事件、本周、学生四件事，版心必须比文章宽。

   二是首屏被「前置」吃光了。实测 1440×900（改前）：

       导航横带   65px   ← 0
       刊头      206px   ← 105    ← 问候语被拆成两行 50px 大字
       Copilot条 129px   ← 331    ← 两行：输入行 + 身份行
       数字条     94px   ← 480
       .board 起点       ← 594

   首屏 900px 里，留给内容的只有 306px，而「今日待办」这张卡本身就有
   464px —— 用户进页面看到的第一屏是「一个标题 + 四个数字 + 半张卡」，
   要想知道今天要做什么，必须往下滚。这正是「一眼看不清重点」。

   本节两刀，都是纯 CSS：

   ① 版心 760 → 1160（内宽 1112）。1440 下占 77%，1748 下占 64% ——
      两侧不再是空场，卡片内一行约 30~34 字，仍是舒服的读速。
   ② .board 从「单栏纵向铺开」改成「左主右辅两栏」：左栏待办 + 事件，
      右栏本周安排 + 学生覆盖。四张卡的总高从 1817 降到 ~1180，
      首屏能在同一屏里看到「今天要做什么 / 这周什么时候 / 谁还没写」。
      信息主次没变（待办仍在左上第一眼位），只是从「一列纵队」改成
      「一张摊开的工作台」。

   加上刊头 / Copilot 条 / 数字条三处瘦身，前置从 594 压到 ~430，
   首屏留给内容 ~470px：待办卡整张可见，右栏两张可见。

   注意：§24 的规则一条没删。本节全部写在后面，靠层叠与更靠后的位置
   覆盖它 —— 想退回「760 单栏刊物体」，把 §25 整段删掉即可。
   ═══════════════════════════════════════════════════════════════════════ */

/* ── 25.1 版心：放开到 1160（内宽 1112） ───────────────────────────────
   规范 §4 的 680 是「一篇文章」的栏宽；工作台首页是「一屏四件事」的
   板面，用文章的栏宽会把四件事全挤到中缝里。
   1160 这个数不是拍的：减去左右各 24 的内距是 1112，两栏（1.52 : 1）
   分下来是 660 / 434 —— 660 正好是规范那个 680 的阅读栏宽，左栏的
   待办与事件仍然按「一行 30~34 字」在读；右栏 434 放本周安排与学生
   九宫格不挤。也就是说：**版心放开了，但阅读栏宽没有破。**

   上限之外再留 48px 侧风：窗口收窄时版心跟着收，不会一直顶到屏幕边
   （1179 宽的笔记本上，1160 会让左右各只剩 2px，读起来像全屏表格）。
   calc 用 100% 而不是 100vw —— 100vw 把滚动条算进去，会撑出横向滚动。

   ⚠️ 这条 calc 只能在宽屏用：手机（390）上 100%-96 = 294，会把版心
   砍掉四分之一。所以基础值写死 1160，带侧风的 min() 放进 1080 断点。 */
.wrap{
  max-width:1160px;
  padding:28px 24px 96px;
}

/* ── 25.2 刊头：把问候语的第二句降成「副题」，与称呼同一行 ──────────────
   §24 里 em.wv 是 display:block，于是「早安，林老师。」和「今天还有
   2 件事。」都是 50px —— 两行 102px，和破局的刊头（一行大标题 + 一行
   小注）根本不是一回事。规范 §6.1 写的是「衬线 900 大标题 → 拉开字距
   的一行小注」，第二句本来就该是小注那一层。

   降成 .5em / ink3 并改回行内之后：版心 1112 放得下整句（370 + 215 =
   585），刊头从 206 落到 148，而「称呼 + 正事」这句话反而读得更连贯 ——
   它本来就是一句话，被折断成两行 50px 才是硬伤。
   窄屏（<1080）放不下一行时，inline-block 会自然折到第二行，此时它
   看起来就是副题，正好是我们要的形态，不需要另写断点。 */
.top h1{line-height:1.06}
.top h1 em.wv{
  display:inline-block;
  font-size:.5em;           /* 50px → 25px */
  font-weight:700;
  line-height:1.34;
  letter-spacing:.01em;
  margin-left:.5em;
  color:var(--ink3);
  /* 折行时第二行不要缩进 */
  text-indent:0;
}
.top .sub{margin-top:9px}
/* 手机/平板必须回到独占一行：行内副题会跟大标题抢同一行的宽度，
   390 下把「林老师。」挤成「林老 / 师。」—— 中文大标题断在词中间
   是最难看的一种断法。宽屏放得下才用行内。 */
@media (max-width:1079px){
  .top h1 em.wv{display:block;margin-top:.08em;margin-left:0}
}

/* ── 25.3 前置瘦身：Copilot 条 + 数字条 ────────────────────────────────
   这两块都是「进页面之前的过道」。过道不该占掉半屏。
   adv-bar 从 129 压到 ~84：内距收一档，身份行（.adv-ctx）的间距与字号
   各收一档 —— 它仍在那，只是从「第二段正文」变回「脚注」。
   数字条从 94 压到 ~76：破局里数字是页边注，不是仪表盘，19px 已经比
   卡片标题还大，再高就抢戏。 */
.adv-bar{padding:10px 16px}
.adv-l1{gap:14px}
.adv-ic{width:26px;height:26px;border-radius:5px}
.adv-inp{height:34px}
/* 身份 / 对象 / 场合三个 select 从 34px 的「表单控件」收到 24px 的
   「行内注」：它们的作用是让你不用再选一遍，不是让'你在这里填表。 */
.adv-ctx{margin-top:7px;padding-top:0;border-top:0;gap:7px}
.adv-ctx .adv-sel{
  height:24px;
  min-width:104px;
  font-size:12px;
  letter-spacing:.04em;
  padding:0 22px 0 8px;
  border-radius:4px;
  background:rgba(35,38,52,.045);
}

.kpis > .kpi{padding:11px 18px 10px}
.kpis .kpi .v{font-size:19px}
.kpi .v small{font-size:12px}
.kpi .d{margin:3px 0 0;font-size:12px;line-height:1.55}
.kpi .k{font-size:12px;letter-spacing:.22em}
.kpis .kpi .kr .mini-ring .rt b{font-size:19px}

/* ── 25.4 骨架：单栏纵向 → 左主右辅两栏（首屏装下今天） ────────────────
   断点与 §24 一致（1080），并且写在 §24.4 之后 —— 同特异性靠层叠压住
   它的 display:flex / flex-direction:column。
   1.52 : 1 不是随手比：左栏 660 = 规范阅读栏宽，右栏 434 放得下
   本周安排的行和九宫格。gap 24（纵向）/ 28（横向）比 §24 的 20 更松，
   两栏挤在一起时会读成一张大表，横向给到 28 才分出「两块板」。 */
@media (min-width:1080px){
  /* 宽屏才给侧风：此时版心可能触到上限，需要让两边各留 48。
     上限从 1160 抬到 1760 —— 原来一到 1920 的屏幕上版心就只剩 60%，
     2560 只剩 45%，两侧空得能再放一栏。仪表盘不是阅读栏，
     它的宽度该由「一屏能并排放几块信息」决定，而不是 38 字。
     小屏完全不受影响：100% - 96 本来就小于 1760，min() 取小的那个。 */
  .wrap{max-width:min(1760px, calc(100% - 96px))}
  .board{
    display:grid;
    grid-template-columns:minmax(0,1.52fr) minmax(0,1fr);
    gap:24px 28px;
    align-items:start;
  }
  .board > .col-main,
  .board > .col-side{
    display:flex;
    flex-direction:column;
    gap:24px;
    width:auto;
    min-width:0;
  }
  /* 卡片内距在宽屏保持规范的 26/26/28，只把标题抬到规范的 21px */
  .card-h h2{font-size:21px}

  /* 导航横带跟着版心走，否则导航比内容窄一截，两侧对不齐 */
  .nav-in{max-width:min(1160px, calc(100% - 96px));padding:22px 24px 0}
  .top{padding:4px 0 18px}
  /* ui.css:715 在 max-width:1179 里给 .main 补了 88px，那是给「fixed 的
     窄屏顶栏」让位的。1080~1179 这一档顶栏已经被下面改成静态（占流），
     这 88px 就变成了凭空一段空白 —— 实测 1179 下首屏白掉 88px，
     刊头被推到 y=177。这里归零。 */
  .main{padding-top:0}
}

/* ── 25.5 材料库：宽屏下记录行回到「一行一条」 ──────────────────────────
   §24.6 的两段式（标题一行 + 元信息一行）是给 760 版心写的：那时一行
   放不下「标题 + 类型 + 关联 + 字数 + 更新」。版心到了 1112，一行完全
   放得下，再坚持两段式就变成「每张卡上下各空一半」。
   宽屏改回单行：标题吃掉剩余宽度，元信息靠右排一行，用间距和字重分
   层级（不用竖线，也不用表头）。 */
@media (min-width:1080px){
  .tr{
    flex-wrap:nowrap;
    align-items:baseline;
    gap:0 20px;
    padding:13px 0 12px;
  }
  .tr .nm2{flex:1 1 auto;min-width:0;font-size:16px}
  .tr .ty{flex:0 0 auto;order:2}
  .tr .lk,.tr .wc,.tr .tm{flex:0 0 auto;order:3;text-align:right}
  .tr .lk{min-width:74px}
  .tr .wc{min-width:76px}
  .tr .tm{min-width:78px}
  .tblwrap{padding:22px 26px 12px}
}

/* ── 25.6 节奏：24px ────────────────────────────────────────────────────
   版心放开之后，20px 的节奏在两栏之间会显得粘连（卡片本身变宽了，
   间距没变，视觉密度反而升高）。24px 是「能看出是两块板」的最小值。 */
#view > * + *{margin-top:24px}

/* ── 25.7 卡内正文在宽栏里的字号 ───────────────────────────────────────
   §24.7 把字号按 720 栏宽抬过一档；栏宽到 1112 之后，14.5px 的待办
   标题在一张 660 宽的卡里偏小，与 21px 的卡片标题层级差被拉得太开。
   再抬半档，差价落在 21 : 15 这个刊物常用的比例上。 */
@media (min-width:1080px){
  .t-body b{font-size:16px}
  .ev-body p{font-size:14.5px}
  .wb b{font-size:14.5px}
  .dnum b{font-size:20px}
}

/* ── 25.8 信息层级：把「今天的账」排到「学期的账」前面 ──────────────────
   前置从 594 压到 367 之后，首屏还是差最后一道：数字条（本周事件 /
   材料完成 / 学生覆盖 / 待办清掉）横在刊头和四张卡之间，占了 89px 加
   一圈外距 —— 而它回答的是「这学期过得怎么样」，不是「今天要做什么」。

   用户的原话是「一眼看清重点，不用一直往下滚」。「重点」在这个页面上
   只有一个：今天的待办和这周要交的东西。所以按叙事把顺序改成：

       刊头 → 问一句 → 今天/这周（四张卡） → 本学期累计（数字条）
            → 材料库 → 写稿条

   这不是把数字藏起来 —— 它就在四张卡下面一层，滚半屏就到，而且作为
   「今年的账」放在材料库前面，正好把「今天」「本周」「本学期」三个
   时间尺度按由近到远排开。

   实现用 flex order，不改 DOM：只调整绘制顺序，读屏软件拿到的仍是
   DOM 里的原始顺序（导航 → 刊头 → 主体），不会出现焦点顺序错乱。
   默认 order:50 是兜底 —— 內页的 .pg-head / .wgrid 等落在 50 上，
   彼此相对顺序不变，所以内页一条规则都不受影响。

   这条不挂断点、全宽度生效：手机上「越滚才能看到待办」的问题更严重
   （390 的首屏里，刊头 + 搜索 + 提问条 + 两排数字就把 844 吃完了），
   同样需要把今天的四张卡顶上来。 */
#view{display:flex;flex-direction:column}
/* 今日页改版后加了「四格数字」和「日历带」两条，这里必须一起排进去，
   否则它们拿到默认的 50，会被推到两栏卡片下面去（四格和日历本该在首屏）。 */
#view > *{order:50}
#view > .top{order:10}
#view > .kpi-grid{order:20}
#view > .calband{order:30}
#view > .board{order:40}
#view > .adv-bar{order:50}
#view > .kpis{order:55}
#view > .tblwrap{order:56}
#view > .ai-bar{order:60}
#view > .foot{order:70}

/* 「问一句」得被看见（老板原话：不然用户会忘记用）。桌面端把它从页尾
   提到刊头正下方：视觉顺序 刊头 → 问一句 → 今天（.desk）。手机保持
   四张卡优先，不跟着提 —— 小屏首屏要留给「今天要做什么」。 */
@media (min-width:1080px){
  #view > .adv-bar{order:20;margin-bottom:0}
  #view > .desk{order:40}
}

/* ── 25.9 手机上的「问一句」：从三行表单收回一行 ────────────────────────
   390 实测（改前）：这一条在手机上占 240px —— 标题一行、解释一句、输入一行、
   按钮一行、三个 select 又三行，比「今日待办」整张卡还高。它是入口，不是
   主体。收法：去掉那句解释（标题已经说清了「遇到事，先问一句」），
   按钮与输入框同一行，select 的内距跟着 §25.3 收。

   ⚠️ 手机上字号不许再往下收 —— app.css 在 max-width:640 里给 .sel 钉了
   `font-size:16px!important` / `min-height:38px`，那是为了 iOS 在聚焦表单
   控件时不自动放大页面（用户的原话：点输入框不要缩放）。皮肤层不跟这条
   抢：手机上这三个 select 就该是 16px、38 高，只是**排布**由下面这段接管。 */
@media (max-width:780px){
  .adv-bar{padding:10px 12px}
  .adv-tt em{display:none}
  .adv-tt b{font-size:13px}
  .adv-l1{gap:8px;flex-wrap:nowrap}
  .adv-tt{flex:0 0 auto;max-width:34%}
  .adv-tt b{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .adv-inp{height:32px;font-size:12px}
  .adv-inp::placeholder{text-overflow:ellipsis}
  .adv-go{height:32px;padding:0 10px;font-size:12px}
  .adv-ctx{gap:6px;margin-top:7px}
  .adv-ctx .adv-sel{height:26px;min-width:0;font-size:12px;padding:0 18px 0 7px}
}

/* ── 25.9b 更窄的手机：三个 select 的**排布**（600 以下才需要）───────────
   ⚠️ 关键：flex 的子项不是 .adv-sel，是包在它外面的 .uisel（ui-select.js:106
   把每个 <select> 换成了 div.uisel > button.uisel-btn.adv-sel，原 <select>
   被隐藏）。所以只给 .adv-sel 写 flex-basis 是无效的 —— 上一版就是这么写的，
   390 上表现为「班主任 213 / 年级组长 94 / 当面说 180」：三块宽度全由文字
   长短决定，前两块刚好挤满第一行，第三块被顶到第二行，看着像随手歪的。
   这里改成给 .uisel 排：身份独占一行（它是句子的主语），对象与场合平分第二行。

   断点卡在 600 而不是 780：三块的自然宽度加起来约 487px + 间距 12 = 499，
   600 的可用内宽还有 512，一行放得下 —— 那就不用换行，768 的平板会白白
   多出一行 42px。只有在 600 以下（499 > 可用宽）才换成 1+2。 */
@media (max-width:600px){
  .adv-ctx > .uisel{flex:0 0 calc(50% - 3px);min-width:0}
  .adv-ctx > .uisel:first-child{flex:0 0 100%}
  /* 按钮要撑满上面分的格，而不是按最长选项文字自带宽度：
     ui-select.js 的 fitWidth() 会给按钮写内联 min-width（"年级组长"=94、
     "当面说"=180），前一个比 155 的格子窄、后一个直接溢出格子。
     内联样式压不过类选择器，但压不过 !important —— 这里用 !important
     把内联 min-width 钉回 0，width:100% 让按钮老老实实填满格子。
     字号仍是 16px：那是 app.css 在 max-width:640 里为 iOS 防聚焦缩放
     钉的 !important，这里不碰。 */
  .adv-ctx > .uisel .uisel-btn{width:100%;min-width:0 !important;max-width:100%}
}

/* ── 25.10 手机导航：Tab 不再被「+」压掉半个字 ──────────────────────────
   390 实测（改前）：.nav-in 内宽 341，里面要塞 头像 32 + 6 个 Tab + 三个
   38 的圆钮。Tab 们被 flex 一路压缩，'事件' 的宽度被压成 0（整格直接消失、
   点不到），'材料' 被压到只剩半个字，还被「+」圆钮盖住 —— 用户看到的就是
   「元素全都挤在一起」。
   解法的方向不是把字缩小（12px 的中文再缩就糊了），而是让该让位的让位：
     · 头像让位 —— 刊头第二行就是「早安，林老师」，导航上再挂一颗「林」是重复；
     · 导航里的搜索钮让位 —— 同一个搜索框就在刊头下面，正文那颗不用横滑也够大；
     · Tab 轨道自己横滑 —— 320 级的屏幕上 6 个 Tab 一定放不下，那就允许滑动，
       但每一个 Tab 必须保持完整字形（flex:0 0 auto），不许再被压扁。 */
@media (max-width:560px){
  .nav{padding:11px 12px}
  .nav-in{gap:8px;padding:7px 7px 7px 9px}
  .id{display:none}
  #searchBtn{display:none}
  .links{
    flex:1 1 auto;
    min-width:0;
    margin-left:0;
    overflow-x:auto;
    overflow-y:hidden;
    scrollbar-width:none;
    -ms-overflow-style:none;
    -webkit-overflow-scrolling:touch;
  }
  .links::-webkit-scrollbar{display:none}
  .links a{flex:0 0 auto;padding:6px 10px}
}

/* ─────────── 26. 今日页月历 ───────────────────────────────────
   细发丝网格 + 衬线数字，不用圆角胶囊，尽量像一页台历。
   点：实心钢靛 = 普通待办 / 实心赭红 = 硬截止 / 空心 = 当天有记录。 */
.cal-h{display:flex;align-items:baseline;justify-content:space-between;margin:0 0 10px}
.cal-h b{font-family:var(--v2-serif);font-size:16px;font-weight:700;letter-spacing:.01em;color:var(--ink)}
.cal-h .cn{display:flex;align-items:center;gap:1px}
.cal-h .cn button{width:22px;height:22px;display:grid;place-items:center;border:0;background:transparent;
  color:var(--ink3);font-size:14.5px;line-height:1;border-radius:3px;cursor:pointer;font-family:var(--v2-serif)}
.cal-h .cn button:hover{background:var(--fill);color:var(--ink)}
.cal-h .cal-nowbtn{width:auto;padding:0 6px;font-family:var(--v2-sans);font-size:12px;
  letter-spacing:.06em;color:var(--blue)}
.cal-wk{display:grid;grid-template-columns:repeat(7,1fr);margin-bottom:2px}
.cal-wk span{text-align:center;font-size:12px;letter-spacing:.1em;color:var(--ink4);padding:3px 0;
  border-bottom:1px solid var(--line-soft)}
.cal-grid{display:grid;grid-template-columns:repeat(7,1fr);row-gap:1px}
.cd{position:relative;display:flex;flex-direction:column;align-items:center;gap:3px;
  height:36px;padding:5px 0 0;border:0;background:transparent;cursor:pointer;border-radius:2px;
  color:var(--ink2);font-variant-numeric:tabular-nums;transition:background .18s}
.cd i{font-style:normal;font-family:var(--v2-serif);font-size:13px;line-height:1}
.cd:hover{background:var(--fill)}
.cd.out{color:var(--ink4)}
.cd.today i{color:var(--blue);font-weight:700}
.cd.today::before{content:"";position:absolute;left:50%;top:2px;width:3px;height:3px;margin-left:-1.5px;
  background:var(--blue);border-radius:50%}
.cd.sel{background:var(--blue-soft);box-shadow:inset 0 0 0 1px var(--blue-ring)}
.cd.sel i{color:var(--blue-d);font-weight:700}
.dots{display:flex;align-items:center;gap:2px;height:4px}
.dots b{display:block;width:3px;height:3px;border-radius:50%}
.d-todo{background:var(--blue)}
.d-hard{background:var(--red)}
.d-ev{background:transparent;box-shadow:inset 0 0 0 1px rgba(35,38,52,.42)}
.d-more{font-style:normal;font-size:12px;line-height:1;color:var(--ink4);letter-spacing:0}
.cal-more{display:block;width:100%;margin:8px 0 0;padding:5px 0;border:0;background:transparent;
  color:var(--ink3);font-size:12px;letter-spacing:.06em;cursor:pointer;border-top:1px solid var(--line-soft)}
.calday{scroll-margin-top:calc(var(--nav-h) + 14px)}
.cal-dayh{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin:0 0 2px}
.cal-dayh b{font-family:var(--v2-serif);font-size:14.5px;font-weight:700;letter-spacing:.01em;color:var(--ink)}
.cal-dayh em{flex:0 0 auto;font-style:normal;font-size:12px;letter-spacing:.06em;color:var(--ink4)}
.cl{display:flex;flex-direction:column}
.cl .todo{border-bottom:1px solid var(--line-soft)}
.cl .todo:last-child{border-bottom:0}
.cl-row{display:flex;align-items:baseline;gap:8px;padding:9px 0;border-bottom:1px solid var(--line-soft);cursor:pointer}
.cl-row:last-child{border-bottom:0}
.cl-row b{flex:1;min-width:0;font-size:13px;font-weight:600;color:var(--ink);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cl-row em{flex:0 0 auto;font-style:normal;font-size:12px;letter-spacing:.06em;color:var(--ink4)}
.cl .empty b{font-size:12px}
@media (max-width:640px){
  .cd{height:40px}
  .cd i{font-size:14.5px}
}

/* ─────────── 27. 顶部数字：压成一行 ─────────────────────────
   原来四张玻璃卡各占一格高度，把日历和待办整个压下去。
   这里只保留「标签 + 数字」，用发丝线分栏，读起来像一行注脚。 */
.kline{display:flex;align-items:baseline;margin:22px 0 26px;padding:13px 0;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.kline .kl{display:flex;align-items:baseline;gap:8px;flex:1 1 0;min-width:0;padding:0 16px;
  border-left:1px solid var(--line-soft)}
.kline .kl:first-child{border-left:0;padding-left:2px}
.kline .kl em{font-style:normal;font-size:12px;letter-spacing:.11em;color:var(--ink4);white-space:nowrap}
.kline .kl b{font-family:var(--v2-serif);font-size:17px;font-weight:700;color:var(--ink);
  font-variant-numeric:tabular-nums;white-space:nowrap;letter-spacing:-.01em}
.kline .kl b u{font-style:normal;text-decoration:none;font-family:var(--v2-sans);
  font-size:12px;font-weight:500;color:var(--ink4);margin-left:2px}
@media (max-width:640px){
  .kline{flex-wrap:wrap;margin:18px 0 20px;padding:10px 0}
  .kline .kl{flex:0 0 50%;padding:7px 12px}
  .kline .kl:nth-child(3){border-left:0;padding-left:2px}
}

/* ─────────── 28. 手机端：日历已挪到两栏上面 ───────────────────
   日历和「这天安排」现在是独立的 .calband，排在两栏之前，
   所以手机上不用再做顺序重排；两栏自然叠成 待办 → 记录 → 学生覆盖。 */

/* ─────────── 29. 顶部四格 ────────────────────────────────────
   一行四格：标签 / 衬线大数字 / 一行注脚。比原来的玻璃卡薄，
   但数字放到 26px，一眼能看到本周的量。 */
.kpi-grid{display:grid;grid-template-columns:repeat(4,1fr);margin:20px 0 22px;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.kpi-grid .kg{padding:14px 18px;border-left:1px solid var(--line-soft)}
.kpi-grid .kg:first-child{border-left:0;padding-left:2px}
.kpi-grid .kg.warn b{color:#a8392b}
.kg em{display:block;font-style:normal;font-size:12px;letter-spacing:.11em;color:var(--ink4)}
.kpi-grid .kg b{display:block;margin-top:7px;font-family:var(--v2-serif);font-size:26px;font-weight:700;
  line-height:1.1;letter-spacing:-.02em;color:var(--ink);font-variant-numeric:tabular-nums}
.kpi-grid .kg b u{font-style:normal;text-decoration:none;font-family:var(--v2-sans);
  font-size:12px;font-weight:500;color:var(--ink4);margin-left:3px}
.kpi-grid .kg span{display:block;margin-top:5px;font-size:12px;color:var(--ink4)}

/* ─────────── 30. 日历带 ──────────────────────────────────────
   日历(7 栏) + 这天安排(5 栏)，单独一行，排在四格下面、两栏上面。
   点日期滚动的目标就是右边这张「这天安排」。 */
.calband{display:grid;grid-template-columns:repeat(12,1fr);gap:16px;margin:0 0 18px;align-items:start}
.calband > .card{margin:0}
.calband > .card:nth-child(1){grid-column:span 7}
.calband > .card:nth-child(2){grid-column:span 5}
@media (max-width:1079px){
  .calband{grid-template-columns:1fr;gap:12px}
}
@media (max-width:640px){
  .kpi-grid{grid-template-columns:1fr 1fr}
  .kpi-grid .kg{padding:12px 14px}
  .kpi-grid .kg:nth-child(3){border-left:0;padding-left:2px}
  .kpi-grid .kg:nth-child(n+3){border-top:1px solid var(--line-soft)}
  .kpi-grid .kg b{font-size:23px}
}

/* ─────────── 31. 桌面恢复左侧栏（老板定的） ──────────────────
   原破局在 ≥1080 把侧栏退役、换成顶部静态横带。老板要求桌面要侧栏，
   这里把侧栏装回来：232px 竖排 + 内容区让位，顶部横带在桌面关掉。
   手机/平板不受影响（这条只在 ≥1080 生效）。 */
@media (min-width:1080px){
  .side{display:flex;flex-direction:column;position:fixed;left:0;top:0;bottom:0;
    width:232px;z-index:55;padding:20px 14px 16px}
  .main{margin-left:232px}
  .nav{display:none!important}
  .top{padding-top:28px}
}

/* ─────────── 32. 今日页：方案 C 环绕布局 ──────────────────────
   大卡「今日待办」靠左上、跨满左列（视觉焦点）；月历在右上横跨两列；
   今日工作、学生覆盖两张小卡在右下环绕。整体错落有致、主次分明。
   卡片内部超出的部分自己滚，标题和页脚钉住，不会把卡撑变形。 */
.quad{display:grid;grid-template-columns:1fr;gap:12px;margin:0 0 18px}
.quad > .card{margin:0;display:flex;flex-direction:column;min-height:0;overflow:hidden}
@media (min-width:700px){
  /* 方案 C 四周环绕（对照原图）：34/28/38 三列 ——
     · 大卡「今日待办」占列 1+2（62%），跨行 1+2；
     · 右侧列 38% 上下叠「月历（矮）」+「今日工作（高）」；
     · 底部行「问一句」左下 34% +「学生覆盖」右下 66%。
     行高 auto，卡片随内容高矮，不再锁死容器高度。 */
  /* 与原图 1:1 同比例：卡片区整体 648×374（aspect-ratio 1.733），
     行按原图像素比 64:174:112、列按 34:28:38 做 fr。
     这样不管窗口多宽，大卡恒为 62% 宽 × 2/3 高，月历恒为右上薄条——
     卡片区永远是一块横向的、和原图同比例的板，而不是被内容拉成长条。 */
  .quad{grid-template-columns:minmax(0,34fr) minmax(0,28fr) minmax(0,38fr);
    grid-template-rows:minmax(0,64fr) minmax(0,174fr) minmax(0,112fr);
    gap:14px;align-items:stretch;
    aspect-ratio:648 / 374;
    /* .desk-l 是 flex 列：默认 min-height:auto 会按内容把卡片区顶高，
       必须归零，否则 aspect-ratio 永远失效、又变回长条 */
    min-height:0;
    grid-template-areas:
      "todo todo cal"
      "todo todo recent"
      "ask  kids kids"}
  .quad .q-todo{grid-area:todo}
  .quad .q-cal{grid-area:cal}
  .quad .q-recent{grid-area:recent}
  .quad .q-kids{grid-area:kids}
  .quad .q-ask{grid-area:ask}
  /* 大卡焦点：标题再大一号，描边加一道主色，跟几张小卡拉开层级 */
  .quad .q-todo{box-shadow:inset 0 0 0 1px var(--blue-ring)}
  .quad .q-todo .card-h h2{font-size:20px}
}
.quad .card-h{flex:none;margin-bottom:8px}
.quad .todos{flex:1;min-height:0;overflow-y:auto}
.quad .cl{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:2px}
/* 最近记录：标题一行 + 孩子/时间一行，发丝线分隔 */
.quad .recs{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column}
.quad .rec{display:flex;flex-direction:column;gap:2px;padding:7px 0;
  border-bottom:1px solid var(--line-soft);cursor:pointer}
.quad .rec:last-child{border-bottom:0}
.quad .rec b{font-size:12px;font-weight:600;color:var(--ink);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.quad .rec em{font-style:normal;font-size:12px;color:var(--ink4);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.quad .rec:hover b{color:var(--blue-d)}
/* 收起时只露前 4 条；放大后自然露出第 5–8 条，不用重绘 */
.quad .q-recent:not(.is-open) .rec:nth-child(n+5){display:none}
/* 宽屏上这张卡高了近一半，4 条会把下半截留空 —— 放宽到 6 条 */
@media (min-width:1500px){
  .quad .q-recent:not(.is-open) .rec:nth-child(n+7){display:none}
}
.quad .kids{flex:1;min-height:0;overflow-y:auto;align-content:start;
  grid-template-columns:repeat(8,1fr);gap:8px}
.quad .kid{padding:9px 1px 8px;border-radius:9px;min-width:0;overflow:hidden}
.quad .kid b{font-size:12px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.quad .kids + .heat-ft{margin-top:auto;flex:none}

/* 今日工作：四行指标，两个带进度条 */
.stats{display:grid;grid-template-columns:1fr 1fr;flex:1;min-height:0}
.stats .st{padding:14px 16px 12px;border-left:1px solid var(--line-soft);display:flex;flex-direction:column}
.stats .st:nth-child(1),.stats .st:nth-child(2){padding-top:2px}
.stats .st:nth-child(odd){border-left:0;padding-left:2px}
.stats .st:nth-child(n+3){border-top:1px solid var(--line-soft)}
.stats em{font-style:normal;font-size:12px;letter-spacing:.11em;color:var(--ink4);display:block}
.stats b{display:block;margin-top:6px;font-family:var(--v2-serif);font-size:30px;font-weight:700;
  line-height:1.05;letter-spacing:-.02em;color:var(--ink);font-variant-numeric:tabular-nums}
.stats b u{font-style:normal;text-decoration:none;font-family:var(--v2-sans);font-size:12px;
  font-weight:500;color:var(--ink4);margin-left:3px}
.stats .bar{height:3px;border-radius:3px;background:var(--line-soft);margin-top:9px;overflow:hidden}
.stats .bar i{display:block;height:100%;border-radius:3px;background:var(--blue)}
.stats .st span{margin-top:auto;padding-top:6px;font-size:12px;color:var(--ink4)}

/* 日历放大：日期 12.5→15，圆点 3→5，格子 36→42，一眼能看清 */
.quad .cal-h{flex:none}
.quad .cal-h b{font-size:17px}
.quad .cal-h .cn button{width:22px;height:22px;font-size:13px}
.quad .cal-wk{flex:none}
.quad .cal-wk span{font-size:12px;padding:5px 0}
/* 网格吃掉卡片剩下的高度，6 行按 1fr 均分 —— 卡高了格子就高，
   卡矮了也自动收，图例永远有位置，不会被裁掉 */
.quad .cal-grid{flex:1;min-height:0;grid-auto-rows:1fr;row-gap:2px}
/* 环绕布局里日历只是一张小卡（双周 2 行），不能让 2 行去均分整卡高度
   （否则日期格又高又空）。未选中时网格按内容自然高度排；选中展开时
   整月 5–6 行也按内容排，格子稍微加高一点，刚好完整装下、不铺满整屏。 */
.quad .q-cal:not(.is-open) .cal-grid{flex:0 0 auto;grid-auto-rows:minmax(28px,auto)}
.quad .q-cal.is-open .cal-grid{flex:0 0 auto;grid-auto-rows:minmax(32px,auto)}
.quad .q-cal.is-open .cd{min-height:30px}
.quad .cd{height:100%;min-height:26px;padding-top:5px;gap:4px;border-radius:4px}
.quad .cd i{font-size:16px}
.quad .dots{gap:3px;height:7px}
.quad .dots b{width:5px;height:5px}
.quad .d-more{font-size:12px}

/* 今日工作卡标题右边的日期 */
.wk-date{font-style:normal;font-weight:400;font-size:12px;color:var(--ink4);
  margin-left:auto;white-space:nowrap;font-variant-numeric:tabular-nums}

/* 图例脚：三种圆点各自的含义写在卡里，别让人猜 */
.cal-ft{display:flex;align-items:center;justify-content:space-between;gap:10px;
  margin-top:auto;padding-top:10px;border-top:1px solid var(--line-soft);flex:none}
.cal-lg{display:flex;align-items:center;gap:11px;font-size:12px;color:var(--ink4)}
.cal-lg span{display:inline-flex;align-items:center;gap:4px}
.cal-lg .dot{width:6px;height:6px;border-radius:50%;display:inline-block}
.cal-lg .dot.d-hard{background:var(--red)}
.cal-lg .dot.d-todo{background:var(--blue)}
.cal-lg .dot.d-ev{background:transparent;box-shadow:inset 0 0 0 1px rgba(35,38,52,.45)}
.cal-n{font-size:12px;color:var(--ink4);font-variant-numeric:tabular-nums;white-space:nowrap}
/* 放大成整月后，网格和脚注之间那行「选中那天」摘要 */
.cal-sel{display:flex;align-items:baseline;gap:6px;flex:none;padding:6px 0 3px;
  border-top:1px solid var(--line-soft);font-size:12px;color:var(--ink3);overflow:hidden}
.cal-sel b{font-size:12px;font-weight:600;color:var(--ink);white-space:nowrap}
.cal-sel span{white-space:nowrap;color:var(--ink4)}
.cal-sel em{font-style:normal;min-width:0;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;color:var(--ink3)}

@media (max-width:640px){
  .quad .cd{height:38px}
  .quad .cd i{font-size:14.5px}
  .quad .cal-lg{gap:8px;font-size:12px}
}

/* ── 31b. 与原图同比例的卡片区：薄月历 / 密热力格 / 紧凑问一句 ─────────
   卡片区被 aspect-ratio 压回原图的 648×374 后，几张卡的内距必须跟着收，
   否则内容会把格子撑破。这里只调「未展开」形态；展开态（.card-open）不受影响。 */
@media (min-width:700px){
  /* 月历：原图是 232×64 的薄条 —— 去掉图例，只留月份头 + 周标 + 一行日期 */
  .quad .q-cal:not(.is-open){padding:7px 15px 4px;justify-content:center}
  .quad .q-cal:not(.is-open) .cal-h{margin:0 0 2px}
  .quad .q-cal:not(.is-open) .cal-h b{font-size:14.5px}
  .quad .q-cal:not(.is-open) .cal-h .cn button:not(.cal-toggle):not(.cal-nowbtn){width:17px;height:17px;font-size:12px}
  .quad .q-cal:not(.is-open) .cal-h .cn .cal-toggle{width:auto;height:22px;padding:0 8px;font-size:12px}
  .quad .q-cal:not(.is-open) .cal-wk span{padding:0;font-size:12px;line-height:12px;border-bottom:0}
  .quad .q-cal:not(.is-open) .cal-grid{flex:0 0 auto;grid-auto-rows:minmax(20px,1fr);row-gap:0}
  .quad .q-cal:not(.is-open) .cd{height:20px;min-height:20px;padding-top:0;gap:0}
  .quad .q-cal:not(.is-open) .cd i{font-size:12px;line-height:1}
  .quad .q-cal:not(.is-open) .dots{height:8px;gap:2px;align-items:center}
  .quad .q-cal:not(.is-open) .dots b{width:4px;height:4px}
  .quad .q-cal:not(.is-open) .d-more{font-size:12px;line-height:1}
  .quad .q-cal:not(.is-open) .cal-ft{display:none}

  /* 最近记录：行距收一档，让卡高里多露一条 */
  .quad .q-recent{padding:12px 16px 10px}
  .quad .q-recent .card-h{margin-bottom:6px}
  .quad .q-recent .card-ft{padding-top:6px}

  /* 问一句：内距按 138 高倒推，见 §32c（那里也压过基础样式） */

  /* 学生覆盖：原图是一条 416×112 的宽卡。人数多、卡宽又随窗口变，
     固定 16 列在 1280 会把名字挤没 —— 用 auto-fill 让列数跟着宽度走 */
  .quad .q-kids{padding:10px 16px 8px}
  .quad .q-kids .card-h{margin-bottom:4px}
  .quad .q-kids .kids{grid-template-columns:repeat(auto-fill,minmax(30px,1fr));gap:3px;
    align-content:start;grid-auto-rows:minmax(23px,auto)}  .quad .q-kids .kid{padding:1px 0;border-radius:4px}
  .quad .q-kids .kid b{font-size:12px;line-height:1.1}
  .quad .q-kids .kid em{font-size:12px;line-height:1.05}
  .quad .q-kids .heat-ft{padding-top:3px}
  .quad .q-kids .heat-ft .legend span{font-size:12px}
}

/* ─────────── 32b. 四卡统一 + 适中放大交互 ─────────────────────────
   统一形式：四张卡都是「标题 + 正文 + 脚注」三段；标题统一衬线。
   脚注 .card-ft 与日历的 .cal-ft、学生的 .heat-ft 用同一条发丝线收底。

   适中放大：点标题区的「展开」按钮，选中卡（.is-open）铺满第一行、高度只
   随内容长到「刚好装下全部内容」，不铺满整屏；其余三张不收成摘要条，
   自动排到第二行、内容照旧可见（第二行 200–340 内按需内部滚动）。
   .quad 高度不再锁死，随内容自然伸缩，FLIP 动画把高度变化一起过渡。 */

/* 标题统一：四张卡都用衬线做标题、同一字号，别让「今日待办」是无衬线、
   「月历」是衬线两套字体打架 */
.quad .card-h h2{font-family:var(--v2-serif);font-size:17px;font-weight:700;letter-spacing:.005em}
.quad .cal-h b{font-size:17px}

/* 统一脚注：待办/工作这两张用 .card-ft，与日历 .cal-ft、学生 .heat-ft
   三者的发丝线、字号、左右两端对齐保持一致 */
.quad .card-ft{display:flex;align-items:center;justify-content:space-between;gap:10px;
  margin-top:auto;padding-top:9px;border-top:1px solid var(--line-soft);flex:none;
  font-size:12px;color:var(--ink4)}
.quad .card-ft em{font-style:normal;white-space:nowrap;font-variant-numeric:tabular-nums}

/* 展开按钮：日历里跟 ‹ › 排在一排，其余卡挂在标题行右侧，都别占一整行。
   特意把选择器写到 .cn / .card-h 里，压过 .cal-h .cn button 的 22px 固定宽 */
.quad .cal-h .cn .cal-toggle,
.quad .card-h .cal-toggle{width:auto;height:22px;padding:0 8px;font-family:var(--v2-sans);
  font-size:12px;letter-spacing:.02em;color:var(--blue-d);background:var(--blue-soft);
  border-radius:7px;white-space:nowrap;flex:none}
.quad .cal-h .cn .cal-toggle:hover,
.quad .card-h .cal-toggle:hover{background:var(--blue-ring);color:var(--blue-d)}
.card-h .cal-toggle{margin-left:auto}

/* 放大态（≥700px）：**容器宽高一个像素都不变**（aspect-ratio 继续锁死）。
   选中卡占 6×6 网格的左上 4×4 主位（约 2/3 × 2/3），其余四张缩到
   右侧两格 + 底部两格 —— 位置由 app.js 写内联 grid-column/row。
   缩小后的卡保留标题与正文（可滚动），只是内距、字号、脚注一起让位。 */
@media (min-width:700px){
  .quad.card-open{
    grid-template-columns:repeat(6,minmax(0,1fr));
    grid-template-rows:repeat(6,minmax(0,1fr));
    grid-template-areas:none;
    aspect-ratio:648 / 374;
    min-height:0;align-items:stretch;gap:14px}
  .quad.card-open > .card{grid-column:auto;grid-row:auto;min-height:0}
  .quad.card-open > .card.is-open{grid-column:1 / 5;grid-row:1 / 5;z-index:3;
    box-shadow:inset 0 0 0 1px var(--blue-ring)}
  .quad.card-open > .card.is-open .card-h h2{font-size:20px}
  .quad.card-open > .card.is-open .todos,
  .quad.card-open > .card.is-open .cl,
  .quad.card-open > .card.is-open .kids{flex:1;min-height:0}
  /* 放大的日历：整月按可用高度均分，不溢出、不留大片空白 */
  .quad.card-open > .card.is-open.q-cal .cal-grid{flex:1;min-height:0;grid-auto-rows:minmax(24px,1fr)}
  .quad.card-open > .card.is-open.q-cal .cal-ft{display:flex}
  /* 缩小的四张 */
  /* 缩小的四张：展开按钮统一缩到 18，跟 14px 的标题同一档 */
  .quad.card-open > .card:not(.is-open) .cal-toggle{height:18px;padding:0 6px;font-size:12px}
  .quad.card-open > .card:not(.is-open){padding:10px 12px 8px}
  .quad.card-open > .card:not(.is-open) .card-h{margin-bottom:5px}
  .quad.card-open > .card:not(.is-open) .card-h h2{font-size:14.5px}
  .quad.card-open > .card:not(.is-open) .card-h .cnt{display:none}
  .quad.card-open > .card:not(.is-open) .more{display:none}
  .quad.card-open > .card:not(.is-open) .card-ft{display:none}
  .quad.card-open > .card:not(.is-open) .kids{grid-template-columns:repeat(auto-fill,minmax(38px,1fr));gap:3px}
  .quad.card-open > .card:not(.is-open) .kid{padding:2px 0 1px;border-radius:4px}
  .quad.card-open > .card:not(.is-open) .kid b{font-size:12px}
  .quad.card-open > .card:not(.is-open) .kid em{font-size:12px}
  .quad.card-open > .card:not(.is-open) .heat-ft,
  .quad.card-open > .card:not(.is-open) .cal-ft{display:none}
  /* 月历当配角时也是整月（2026-11-04 统一，app.js 不再给 14 格窗口）：
     槽位只有 ~170px 高，格子压到 14px 一档、圆点藏掉、图例藏掉，
     只留「日期 + 红色节假日底」这个最关键的信息量。 */
  .quad.card-open > .card:not(.is-open).q-cal .cal-wk{display:grid}
  .quad.card-open > .card:not(.is-open).q-cal .cal-wk span{font-size:12px;line-height:12px;padding:0}
  .quad.card-open > .card:not(.is-open).q-cal .cal-grid{grid-auto-rows:minmax(14px,1fr);row-gap:1px;column-gap:1px}
  .quad.card-open > .card:not(.is-open).q-cal .cd{gap:2px;padding:0;border-radius:3px}
  .quad.card-open > .card:not(.is-open).q-cal .cd i{font-size:12px}
  .quad.card-open > .card:not(.is-open).q-cal .cd .dots{display:none}
  .quad.card-open > .card:not(.is-open).q-cal .cal-ft{display:none}
  .quad.card-open > .card:not(.is-open) .ask-tip,
  .quad.card-open > .card:not(.is-open) .adv-ctx{display:none}
  /* 缩小后内容只剩一小截，垂直居中比顶在上沿好看 */
  .quad.card-open > .card:not(.is-open).q-cal,
  .quad.card-open > .card:not(.is-open).q-ask{justify-content:center}
  /* 放大的学生格：8 列大格子，把 2/3 的版面用起来 */
  .quad.card-open > .card.is-open.q-kids .kids{grid-template-columns:repeat(auto-fill,minmax(64px,1fr));gap:6px}
  .quad.card-open > .card.is-open.q-kids .kid{padding:7px 0 6px;border-radius:7px}
  .quad.card-open > .card.is-open.q-kids .kid b{font-size:12px}
  .quad.card-open > .card.is-open.q-kids .kid em{font-size:12px}
  .quad.card-open .q-todo:not(.is-open){box-shadow:none}
  /* 放大的「问一句」：按大卡尺度重排，别还是一颗小按钮 */
  .quad.card-open > .q-ask.is-open{padding:22px 24px}
  .quad.card-open > .q-ask.is-open .ask-tip{font-size:13px;margin:0 0 16px}
  .quad.card-open > .q-ask.is-open .adv-inp{height:40px;font-size:13px}
  .quad.card-open > .q-ask.is-open .adv-go{height:40px;font-size:13px;padding:0 18px}
  .quad.card-open > .q-ask.is-open .adv-ctx{margin-top:20px;padding-top:14px;gap:10px}
  .quad.card-open > .q-ask.is-open .uisel .uisel-btn{height:30px;font-size:12px;padding:0 8px}
}

/* 小于 700px 一律单列：放大态写过的内联 grid-column/row 在这里必须让位，
   否则把桌面窗口拖窄后卡片会飞到不存在的列上 */
@media (max-width:699.98px){
  .quad > .card{grid-column:auto !important;grid-row:auto !important}
}

/* ─────────── 32c. 「问一句」环绕卡（桌面左下 CTA） ──────────────────
   对照原图：220×112 的琥珀行动卡，不是顶部通栏条。只在 ≥700px 出现，
   由 app.js 放进 .quad 的 ask 区域（列 1、行 3）。整套内距按「138px 高」
   倒推，保证标题 / 一句说明 / 输入行 / 三个身份注全部落在卡内。 */
.quad .q-ask{
  padding:10px 14px 9px;
  background:linear-gradient(155deg,#d49c37,#c8902a 52%,#b27c1f);
  color:#fff;
  box-shadow:0 12px 26px -14px rgba(184,115,36,.55);
}
.quad .q-ask .card-h{margin-bottom:2px;padding-bottom:0}
.quad .q-ask .card-h h2{color:#fff}
.quad .q-ask .card-h .cnt{color:rgba(255,255,255,.72)}
.quad .q-ask .ask-tip{margin:0 0 5px;font-size:12px;letter-spacing:.02em;
  line-height:1.35;color:rgba(255,255,255,.9);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.quad .q-ask .ask-row{display:flex;gap:8px;margin-top:0}
.quad .q-ask .adv-inp{flex:1;min-width:0;height:26px;font-size:12px;background:#fff;
  border-color:transparent;color:var(--ink)}
.quad .q-ask .adv-inp::placeholder{color:var(--ink4)}
.quad .q-ask .adv-go{height:26px;font-size:12px;padding:0 9px;background:#fff;
  color:#a9781b;border-color:transparent;flex:none}
.quad .q-ask .adv-go:hover{background:#f6ead2;color:#8f6415}
/* 身份 / 对象 / 场合三个行内注：一行排开，琥珀底上用深琥珀半透明 + 白字 */
.quad .q-ask .adv-ctx{margin-top:5px;padding-top:4px;flex-wrap:nowrap;gap:5px;
  border-top:1px solid rgba(255,255,255,.28);color:rgba(255,255,255,.85)}
.quad .q-ask .adv-ctx > .uisel{flex:1 1 0;min-width:0}
.quad .q-ask .adv-ctx .adv-sel,
.quad .q-ask .uisel .uisel-btn{background:rgba(58,36,6,.24);color:#fff;
  border-color:rgba(255,255,255,.22);width:100%;max-width:100%;min-width:0 !important;
  height:18px;font-size:12px;padding:0 3px;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.quad .q-ask .uisel .uisel-btn:hover{background:rgba(58,36,6,.34)}
/* 「试试这样问」只在放大后出现：收起的小卡没地方放，也不需要 */
.quad .q-ask .ask-eg{display:none}
.quad.card-open > .q-ask.is-open .ask-eg{display:flex;flex-wrap:wrap;align-items:center;gap:6px;
  margin-top:auto;padding-top:14px;border-top:1px solid rgba(255,255,255,.22)}
.quad .q-ask .ask-eg span{font-size:12px;letter-spacing:.1em;color:rgba(255,255,255,.7)}
.quad .q-ask .ask-eg button{height:26px;padding:0 11px;border:0;border-radius:13px;cursor:pointer;
  background:rgba(255,255,255,.18);color:#fff;font:inherit;font-size:12px;letter-spacing:.02em;
  transition:background .15s}
.quad .q-ask .ask-eg button:hover{background:rgba(255,255,255,.32)}

/* ─────────── 33. 今日调度（桌面右侧栏） ────────────────
   老板反馈「桌面上要素太少」。四张卡只管摆事实，这一栏负责判断：
   今天最要紧的是什么、先做哪个、还有谁没记录。桌面常驻，窄屏落到卡片下面。 */
.desk{display:grid;grid-template-columns:minmax(0,1fr) 296px;gap:18px;align-items:start;margin:0 0 18px}
/* 右栏跟着画布一起长：296 在 1160 版心里是 26%，到 1760 就只剩 17%，
   面板被压成一根细条。分两档抬到 336 / 368，比例回到 21% 上下。 */
@media (min-width:1600px){
  .desk{grid-template-columns:minmax(0,1fr) 336px;gap:20px}
}
@media (min-width:2100px){
  .desk{grid-template-columns:minmax(0,1fr) 368px;gap:22px}
}
.desk-l{min-width:0;display:flex;flex-direction:column}
.desk > .quad{margin:0}
.desk-l > .kpi-grid{margin-top:0}

/* 以「今日调度」为标尺：右栏在的宽度（≥1280）左栏拉伸到与它等高，
   卡片区吃掉 KPI 条以外剩下的高度 —— 两块下底自然齐平。
   更窄时调度栏落到卡片下面，没有对齐可言，维持原来的内容高度。 */
@media (min-width:1280px){
  .desk{align-items:stretch}
  .desk-l{min-height:0}
  .desk-l > .quad{flex:1 1 0;min-height:0;aspect-ratio:auto;margin-bottom:0}
}

.brief{position:sticky;top:24px;display:flex;flex-direction:column;
  padding:16px 18px 14px;margin:0;min-height:0}

.brf-h{display:flex;align-items:center;gap:8px;margin-bottom:13px}
.brf-ic{width:27px;height:27px;border-radius:9px;flex:none;display:flex;align-items:center;justify-content:center;
  background:var(--blue-soft);color:var(--blue-d)}
.brf-h b{font-size:14.5px;font-weight:620;letter-spacing:-.012em;color:var(--ink)}
.brf-h em{font-style:normal;margin-left:auto;font-size:12px;letter-spacing:.12em;color:var(--ink4)}

.brf-say{margin:0 0 15px;font-size:13px;line-height:1.75;color:var(--ink2)}
.brf-sub{font-size:12px;letter-spacing:.12em;color:var(--ink4);margin-bottom:2px;margin-top:2px}

.brf-list{list-style:none;margin:0 0 13px;padding:0;counter-reset:exp}
.brf-list li{counter-increment:exp;position:relative;padding:8px 0 8px 24px;
  border-top:1px solid var(--line-soft);display:flex;flex-direction:column;gap:3px}
.brf-list li:first-child{border-top:0}
.brf-list li::before{content:counter(exp);position:absolute;left:0;top:8px;width:15px;height:15px;
  border-radius:50%;background:var(--fill);color:var(--ink3);
  font-size:12px;font-weight:600;display:flex;align-items:center;justify-content:center;
  font-variant-numeric:tabular-nums}
.brf-list b{font-size:13px;font-weight:560;color:var(--ink);line-height:1.4;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.brf-list span{font-size:12px;color:var(--ink4)}
.brf-list li.brf-none{border-top:0;padding-left:0;color:var(--ink4);font-size:12px}
.brf-list li.brf-none::before{content:none}

.brf-note{font-size:12px;line-height:1.55;color:var(--ink3);background:var(--fill);
  border-radius:8px;padding:7px 9px;margin-bottom:10px}

.brf-foot{margin-top:auto;display:flex;gap:8px;padding-top:2px}
.brf-foot .btn{flex:1;justify-content:center}

@media (max-width:1279px){
  .desk{grid-template-columns:1fr;gap:12px}
  .brief{position:static}
}
@media (max-width:640px){
  .brief{padding:14px 15px 12px}
  .brf-say{font-size:13px}
  .brf-list b{white-space:normal}
}

/* ─────────── 33b. 今日调度的四层信息（补 33 的层级） ──────────
   L1 焦点块 → L2 接下来 → L3 三条底子 + 7 天节奏 → L4 动作。
   视觉靠「底色块 / 分割线 / 字号」分层，不靠堆颜色。 */
.brief{padding:15px 17px 13px;max-height:calc(100vh - 40px);overflow-y:auto;overscroll-behavior:contain}
.brief::-webkit-scrollbar{width:6px}
.brief::-webkit-scrollbar-thumb{background:rgba(0,0,0,.13);border-radius:6px}

.brf-t{display:flex;flex-direction:column;gap:1px;min-width:0}
.brf-t b{font-size:14.5px;font-weight:620;letter-spacing:-.012em;color:var(--ink)}
.brf-t em{font-style:normal;font-size:12px;letter-spacing:.1em;color:var(--ink4);margin-left:0}
.brf-live{margin-left:auto;flex:none;display:inline-flex;align-items:center;gap:4px;
  font-size:12px;letter-spacing:.08em;color:var(--ink4)}
.brf-live::before{content:"";width:5px;height:5px;border-radius:50%;background:var(--ok)}
.brf-say{margin:0 0 8px;font-size:12px;line-height:1.55;color:var(--ink2)}

/* L1 焦点：整栏只有这一块有底色，视线第一落点 */
.brf-focus{position:relative;padding:10px 12px 11px;border-radius:12px;margin-bottom:12px;
  background:rgba(58,81,153,.055);box-shadow:inset 0 0 0 1px rgba(58,81,153,.16)}
.brf-focus.done{background:rgba(0,0,0,.022);box-shadow:inset 0 0 0 1px var(--line-soft)}
.brf-tag{display:block;font-size:12px;letter-spacing:.14em;color:var(--blue-d);margin-bottom:6px}
.brf-ft{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  font-size:14.5px;line-height:1.45;font-weight:600;color:var(--ink)}
.brf-meta{display:flex;align-items:center;gap:8px;margin-top:7px}
.brf-chip{font-size:12px;padding:2px 6px;border-radius:5px;background:rgba(0,0,0,.05);color:var(--ink3)}
.brf-chip.hard{background:var(--red-soft);color:var(--red)}
.brf-left{font-size:12px;color:var(--ink4);font-variant-numeric:tabular-nums;margin-left:auto}
.brf-do{width:100%;margin-top:8px;height:27px;border:0;border-radius:8px;cursor:pointer;
  background:var(--ink);color:#fff;font:inherit;font-size:12px;font-weight:500;letter-spacing:.01em;
  transition:background .2s,transform .12s}
.brf-do:hover{background:#000}
.brf-do:active{transform:scale(.985)}

/* L2 接下来：可点，点了定位到下面那张待办卡 */
.brief .brf-list li{cursor:pointer;padding:6px 0 6px 21px}
.brief .brf-list li:hover{background:linear-gradient(90deg,rgba(58,81,153,.06),transparent)}
.brief .brf-list li:hover b{color:var(--blue-d)}

/* L3 三条底子：标签 / 数值 / 细条，整行可点跳对应页 */
.brf-kpis{display:flex;flex-direction:column;gap:5px;margin-bottom:11px}
.brf-kpi{display:grid;grid-template-columns:auto 1fr;column-gap:8px;align-items:center;
  cursor:pointer;padding:1px 0}
.brf-kpi:hover .brf-kn{color:var(--ink2)}
.brf-kn{font-size:12px;color:var(--ink3)}
.brf-kv{font-size:12px;color:var(--ink);text-align:right;font-variant-numeric:tabular-nums;font-weight:500}
.brf-kb{grid-column:1 / -1;display:block;height:2px;border-radius:2px;background:var(--line-soft);
  margin-top:3px;overflow:hidden}
.brf-kb u{display:block;height:100%;background:var(--blue);border-radius:2px}

/* L3b 还没记录的孩子：直接点名，点了就进那个孩子的页 */
.brf-kids{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:0 0 11px}
.brf-kids b{font-size:12px;font-weight:400;letter-spacing:.06em;color:var(--ink4)}
.brf-kid{height:23px;padding:0 9px;border:0;border-radius:6px;cursor:pointer;
  background:var(--red-soft);color:var(--ink2);font:inherit;font-size:12px;
  transition:background .15s}
.brf-kid:hover{background:rgba(0,0,0,.09)}
.brf-quiet{font-size:12px;color:var(--ink4);padding:2px 0 9px}

/* 焦点卡的次要动作：顺延一天 / 改到某天 */
.brf-acts{display:flex;gap:6px;margin-top:6px}
.brf-min{flex:1;height:25px;border:0;border-radius:7px;cursor:pointer;
  background:rgba(0,0,0,.055);color:var(--ink2);font:inherit;font-size:12px;
  transition:background .15s}
.brf-min:hover{background:rgba(0,0,0,.1)}

/* ── 33b. 今日调度的时间轴（上午 / 下午） ─────────────────────────
   两段都是拖放目标：拖上去亮一层浅蓝，松手就把这条事挪到那一段。
   触屏没有拖放，每行右侧留一个 ↑/↓ 小按钮做等价操作。 */
.brf-tlwrap{display:flex;flex-direction:column;gap:2px;margin:0 0 9px}
.brf-seg{border:1px dashed transparent;border-radius:10px;padding:5px 7px 6px;
  transition:background .15s,border-color .15s}
.brf-seg.over{background:rgba(58,81,153,.07);border-color:rgba(58,81,153,.35)}
.brf-seg-h{display:flex;align-items:baseline;gap:6px;margin-bottom:2px}
.brf-seg-h b{font-size:12px;font-weight:600;letter-spacing:.08em;color:var(--ink)}
.brf-seg-h em{font-style:normal;font-size:12px;color:var(--ink4)}
.brf-tl{list-style:none;margin:0;padding:0}
.brf-ti{position:relative;display:flex;align-items:center;gap:7px;padding:5px 3px;
  border-radius:6px;cursor:pointer}
.brf-ti + .brf-ti{box-shadow:0 -0.5px 0 var(--line-soft)}
.brf-ti:hover{background:rgba(58,81,153,.055)}
.brf-ti.dragging{opacity:.35}
.brf-ti-d{width:6px;height:6px;border-radius:50%;background:var(--blue);flex:none}
.brf-ti-d.hard{background:var(--red)}
.brf-ti b{flex:1;min-width:0;font-size:12px;font-weight:400;color:var(--ink);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.brf-ti em{font-style:normal;font-size:12px;color:var(--ink4);white-space:nowrap}
.brf-ti-mv{width:16px;height:16px;flex:none;border:0;background:transparent;border-radius:4px;
  color:var(--ink4);font-size:12px;line-height:1;cursor:pointer;opacity:.45}
.brf-ti:hover .brf-ti-mv,.brf-ti-mv:focus{opacity:1}
.brf-ti-mv:hover{background:var(--fill);color:var(--ink)}
.brf-seg-e{font-size:12px;color:var(--ink4);padding:4px 2px 6px}
.brf-week{font-size:12px;color:var(--ink4);margin:0 0 9px}
.brf-week a{color:var(--blue);text-decoration:none}
.brf-wk{margin:0 0 10px}
.brf-wk .brf-sub{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:2px}
.brf-wk .brf-sub em{font-style:normal;font-size:12px;color:var(--ink4)}
.brf-wk-i{display:flex;align-items:baseline;gap:8px;padding:5px 2px;border-radius:6px;cursor:pointer}
.brf-wk-i:hover{background:rgba(58,81,153,.05)}
.brf-wk-i b{flex:1;min-width:0;font-size:12px;font-weight:400;color:var(--ink2);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.brf-wk-i em{font-style:normal;font-size:12px;color:var(--ink4);white-space:nowrap}
.brf-wk-more{display:inline-block;margin-top:2px;font-size:12px;color:var(--blue);text-decoration:none}

/* 近 7 天记录：7 根柱子，今天那根实心；点柱子去事件池 */
.brf-7d{margin:0 0 10px}
.brf-7d .brf-sub{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin-bottom:5px}
.brf-7d .brf-sub em{font-style:normal;font-size:12px;color:var(--ink4)}
.brf-bars{display:flex;align-items:flex-end;gap:5px;height:82px}
.brf-bar{flex:1;display:flex;flex-direction:column;justify-content:flex-end;align-items:center;
  gap:3px;border:0;background:transparent;padding:0;cursor:pointer}
.brf-bar i{display:block;width:100%;max-width:16px;border-radius:3px;background:rgba(58,81,153,.16)}
.brf-bar u{text-decoration:none;font-size:12px;line-height:1;color:var(--ink4)}
.brf-bar.on i{background:var(--blue)}
.brf-bar:hover i{background:rgba(58,81,153,.32)}
.brf-bar.on:hover i{background:var(--blue)}

/* 底部三颗按钮：记录 / 加待办 / 收工。等宽一行，都真做事。
   「记一条」是产品的地基动作（所有材料都从记录长出来），所以只给它一层淡蓝 */
.brf-act{display:flex;gap:7px;margin-top:12px;padding-top:11px;
  border-top:1px solid rgba(35,38,52,.09)}
.brf-btn{flex:1 1 0;min-width:0;height:30px;display:inline-flex;align-items:center;
  justify-content:center;gap:5px;padding:0 6px;
  border:1px solid rgba(35,38,52,.13);border-radius:7px;background:rgba(255,255,255,.62);
  color:var(--ink2);font:inherit;font-size:12px;letter-spacing:.01em;
  cursor:pointer;transition:background .15s,border-color .15s,color .15s}
.brf-btn svg{flex:none;opacity:.8}
.brf-btn:hover{background:rgba(58,81,153,.075);border-color:rgba(58,81,153,.26);color:var(--blue-d)}
.brf-btn:hover svg{opacity:1}
.brf-btn:active{background:rgba(58,81,153,.13)}
.brf-btn.pri{background:rgba(58,81,153,.1);border-color:rgba(58,81,153,.24);
  color:var(--blue-d);font-weight:500}
.brf-btn.pri:hover{background:rgba(58,81,153,.17)}
.brf-btn.pri svg{opacity:1}

/* 右栏在的宽度：面板给个下限，否则内容变轻后卡片区会被带着变矮；
   多出来的高度由时间轴吸收（两段之间留白），底部三块仍然贴底 */
@media (min-width:1280px){
  /* 面板高度跟着视口走：原来锁死 644，在 1280 高的屏幕上内容只到页面 2/3，
     下面空一大截。现在 900 高的窗口不动（644 保底），1000～1280 的窗口
     一路长到 780，卡片区（flex:1 1 0）跟着长高，下底始终齐平。 */
  .brief{min-height:clamp(644px, calc(100vh - 300px), 780px)}
  /* 底部记录区贴底：上半是今天的排班，下半是记录的账，中间留白当分隔 */
  .brief .brf-7d{margin-top:auto}
}
.brf-dtl{flex:1;display:flex;align-items:center;gap:4px;padding:0 7px;height:25px;
  border-radius:7px;background:rgba(0,0,0,.055);cursor:pointer}
.brf-dtl em{font-style:normal;font-size:12px;color:var(--ink4);flex:none}
.brf-dtl input{flex:1;min-width:0;border:0;background:transparent;padding:0;
  font:inherit;font-size:12px;color:var(--ink2);outline:none;cursor:pointer}

/* 点建议后，被指到的那条待办闪一下 */
@keyframes expFlash{0%{background:rgba(58,81,153,.15)}100%{background:transparent}}
.fx-flash{animation:expFlash 1s ease-out;border-radius:8px}

/* ─────────── 34. 布局方案 B：通栏调度带（去右栏） ────────────────
   ?layout=b 时今日页从「左内容 + 右 296 调度栏」改成通栏：
   KPI 条 → 调度带（左焦点 / 中清单 / 右底子三段横排）→ 2×2 四卡。
   同一份 DOM 由 deskBrief(band=true) 生成，这里只排位置；交互不变。 */
.desk-b{grid-template-columns:minmax(0,1fr);gap:0}
.desk-b > .brief{display:none}

.briefband{margin:0 0 18px;padding:15px 18px 14px}
.briefband .brf-h{margin-bottom:11px}
.bb-main{display:grid;grid-template-columns:minmax(0,5fr) minmax(0,4fr) minmax(0,3fr);
  gap:20px;align-items:start}
.bb-col{min-width:0}
.bb-a{display:flex;flex-direction:column}
.bb-a .brf-say{margin-bottom:10px}
.bb-a .brf-focus{margin-bottom:0}
.bb-b,.bb-c{padding-left:18px;border-left:1px solid var(--line-soft)}
.bb-b .brf-sub:first-child,.bb-c .brf-sub:first-child{margin-top:0}
/* 底部动作跟焦点走（左列），不横铺整行 —— 横铺会变成两条巨型按钮 */
.bb-a .brf-foot{margin-top:12px;padding-top:0;border-top:0}

@media (min-width:1080px){
  /* B 少了右栏，但多了调度带；高度按「视口 - 刊头 - 问一句 - KPI - 调度带 - 余量」给 */
  .desk-b .quad{height:clamp(540px,calc(100vh - 580px),780px)}
}
@media (max-width:1279px){
  .bb-main{grid-template-columns:1fr 1fr;gap:16px}
  .bb-c{grid-column:1 / -1;display:grid;grid-template-columns:1fr 1fr;gap:18px;
    padding-left:0;border-left:0;padding-top:14px;border-top:1px solid var(--line-soft)}
  .bb-b{padding-left:16px}
}
@media (max-width:699px){
  .bb-main{grid-template-columns:1fr}
  .bb-b{border-left:0;padding-left:0;padding-top:12px;border-top:1px solid var(--line-soft)}
  .bb-c{display:block;padding-top:12px}
}

/* ─────────── 36. 宽屏自适应（≥1500 / ≥2100） ────────────────────────
   1160 版心是为「一栏 38 字」定的阅读宽度，工作台不是阅读页。
   但宽度放开后会出现另一半问题：卡片被拉宽，里面的条目没变多，
   于是空得更多。所以这一段只做一件事 —— 让内容的密度跟着画布一起长。
   窄屏（<1500）一条都不生效，老样子。 */

@media (min-width:1500px){
  /* 学生覆盖：32 个人固定排 16 列 × 2 行。
     原来 auto-fill 在宽卡里会算到 22~28 列，最后一行只剩几个，
     右侧空出半张卡；锁 16 列后正好两行占满。 */
  .quad .q-kids .kids{grid-template-columns:repeat(16,minmax(0,1fr));gap:5px;
    grid-auto-rows:minmax(26px,auto)}
  .quad .q-kids .kid{padding:3px 0 2px;border-radius:5px}
  .quad .q-kids .kid b{font-size:12px}
  .quad .q-kids .kid em{font-size:12px}

  /* 待办 / 最近记录的条数由 JS 与上面的 nth-child 一并放宽到 6 条，
     这里补的是行距：条目多了，间距得松一点才不挤 */
  .quad .q-todo .todos .todo{padding:11px 0}
  .quad .q-recent .rec{padding:7px 0}

  /* 月历：宽屏格子变宽，数字跟着放大一档，不然七个数字浮在格子中间 */
  .quad .q-cal:not(.is-open) .cd i{font-size:12px}
  .quad .q-cal:not(.is-open) .cal-h b{font-size:16px}
}

@media (min-width:2100px){
  /* 再次拉宽后，卡片高度走到 650+ : 格子再大一号，行高再松一点 */
  .quad .q-kids .kids{gap:6px;grid-auto-rows:minmax(30px,auto)}
  .quad .q-todo .todos .todo{padding:13px 0}
  .quad .q-recent .rec{padding:9px 0}
}

/* 宽屏月历给两行（app.js 里 win=14）：行高跟着抬到 28，
   免得两周的数字挤在 20px 的窄格里。 */
@media (min-width:1500px){
  .quad .q-cal:not(.is-open) .cal-grid{grid-auto-rows:minmax(28px,1fr);row-gap:1px}
  .quad .q-cal:not(.is-open) .cd{height:28px;min-height:28px}
  .quad .q-cal:not(.is-open) .cal-wk span{font-size:12px;line-height:14px}
}

/* ═══════════ 37. 日历独立成宽卡 + 四卡重排 + 字号上调 ═══════════
   老板原话：日历太局促、允许它不受窄卡限制、卡片里字太小。
   做法：月历从五卡网格里提出来，跨整宽、直接看整月，格子里还露一行事；
   剩下的四张（待办/问一句/最近记录/学生覆盖）重排成 2 列 3 行。 */

/* ── 37.1 刊头日期行：放大 + 接一枚 24 小时制的钟 ── */
.top .sub{font-size:12px;letter-spacing:.13em}
.top .sub .sub-time{
  margin-left:14px;padding-left:14px;border-left:1px solid var(--line);
  font-variant-numeric:tabular-nums;letter-spacing:.06em;color:var(--ink3);
  font-weight:500;
}

/* ── 37.2 日历宽卡 ── */
.cal-wide{margin:0 0 14px;padding:15px 18px 14px;
  display:flex;flex-direction:column;min-width:0}
.cw-h{display:flex;align-items:baseline;gap:10px;margin-bottom:11px;min-width:0}
.cw-h b{font-family:var(--v2-serif);font-size:21px;font-weight:800;
  letter-spacing:.02em;color:var(--ink);line-height:1.1}
.cw-h .cw-sub{font-size:12px;color:var(--ink4);letter-spacing:.06em}
.cw-h .cn{margin-left:auto;display:flex;align-items:center;gap:3px;flex:none}
.cw-h .cn button{width:24px;height:24px;border:0;border-radius:7px;background:transparent;
  color:var(--ink3);font-size:14.5px;line-height:1;cursor:pointer;transition:background .15s,color .15s}
.cw-h .cn button:hover{background:rgba(58,81,153,.09);color:var(--blue-d)}
.cw-h .cn .cal-nowbtn{width:auto;padding:0 9px;font-size:12px;color:var(--blue-d);
  background:rgba(58,81,153,.09)}
.cw-lg{margin-left:18px;flex:none;display:flex;align-items:center;gap:12px;
  font-size:12px;color:var(--ink4)}
.cw-lg span{display:inline-flex;align-items:center;gap:4px}

.cw-body{display:grid;grid-template-columns:minmax(0,1fr) 310px;gap:18px;
  min-width:0;align-items:stretch}
.cw-cal{min-width:0;display:flex;flex-direction:column}
.cw-cal .cal-wk{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:5px;
  margin-bottom:5px}
.cw-cal .cal-wk span{font-size:12px;letter-spacing:.1em;color:var(--ink4);
  text-align:center;padding:2px 0;border-bottom:0}
.cw-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));
  grid-auto-rows:minmax(0,1fr);gap:5px;flex:1;min-height:0}
/* 格子：日期在左上、圆点在右上、事情标题在下面一行 */
.cw-grid .cd{display:grid;grid-template-columns:auto 1fr;grid-template-rows:auto auto;
  align-content:start;gap:3px 4px;height:auto;min-height:52px;padding:7px 8px;
  border-radius:9px;text-align:left;background:rgba(255,255,255,.5);
  border:1px solid transparent;transition:background .15s,border-color .15s}
.cw-grid .cd:hover{background:#fff;border-color:var(--blue-ring)}
.cw-grid .cd i{grid-column:1;font-style:normal;font-size:14.5px;font-weight:600;
  line-height:1.15;color:var(--ink);font-variant-numeric:tabular-nums}
.cw-grid .cd .dots{grid-column:2;justify-self:end;align-self:center;
  display:flex;gap:3px;height:auto}
.cw-grid .cd .dots .dot{width:5px;height:5px}
.cw-grid .cd-t{grid-column:1 / -1;font-size:12px;line-height:1.35;color:var(--ink3);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.cw-grid .cd-t u{text-decoration:none;color:var(--ink4);margin-left:3px;font-size:12px}
.cw-grid .cd.out{background:transparent}
.cw-grid .cd.today{border-color:var(--blue-ring);background:#fff}
.cw-grid .cd.today i{color:var(--blue-d)}
.cw-grid .cd.sel{background:#fff;border-color:var(--blue);
  box-shadow:inset 0 0 0 1px var(--blue)}
.cw-grid .cd.sel i{color:var(--blue-d);font-weight:700}

/* 右侧当天清单 */
.cw-day{display:flex;flex-direction:column;min-width:0;
  border-left:1px solid var(--line-soft);padding-left:18px}
.cw-dayh{display:flex;align-items:baseline;gap:8px;margin-bottom:9px;flex:none}
.cw-dayh b{font-size:14.5px;font-weight:700;color:var(--ink)}
.cw-dayh em{font-style:normal;font-size:12px;color:var(--ink4)}
.cw-dayh span{margin-left:auto;font-size:12px;color:var(--ink4)}
.cw-cl{flex:1;min-height:0;overflow-y:auto}
.cw-dayf{flex:none;display:flex;align-items:center;gap:10px;padding-top:9px;
  margin-top:6px;border-top:1px solid var(--line-soft);
  font-size:12px;color:var(--ink4)}
.cw-add{margin-left:auto;border:0;background:transparent;color:var(--blue-d);
  font:inherit;font-size:12px;cursor:pointer;padding:2px 4px;border-radius:5px}
.cw-add:hover{background:rgba(58,81,153,.08)}

/* ── 37.3 四卡重排：待办占左 62%，右列问一句 + 最近记录，学生覆盖整宽 ── */
@media (min-width:700px){
  .quad{grid-template-columns:minmax(0,62fr) minmax(0,38fr);
    grid-template-rows:minmax(0,1fr) minmax(0,1fr) auto;
    aspect-ratio:auto;
    grid-template-areas:
      "todo ask"
      "todo recent"
      "kids kids"}
  .quad .q-ask{grid-area:ask}
  .quad .q-recent{grid-area:recent}
  .quad .q-kids{grid-area:kids}
  .quad .q-todo{grid-area:todo}
}

/* ── 37.4 卡片内字号上调（原来 9~12px，一眼看着像注释） ── */
.card-h h2{font-size:16px}
.quad .q-todo .card-h h2{font-size:21px}
.quad .card-h .cnt{font-size:12px}
.quad .rec b{font-size:14.5px}
.quad .rec em{font-size:12px}
.quad .q-kids .kid b{font-size:13px}
.quad .q-kids .kid em{font-size:12px}
.quad .kid{border-radius:7px}
.quad .card-ft{font-size:12px}
.cw-cl .cl-row b,.cw-cl .todo b{font-size:13px}
.cw-cl .cl-row em,.cw-cl .todo em{font-size:12px}

/* ── 37.5 问一句：从琥珀改为深钢靛蓝，与全站强调色同源；布局重排 ── */
.quad .card.q-ask{
  padding:14px 16px 13px;
  background:linear-gradient(162deg,#43609f,#3a5199 56%,#31457f);
  border:0;
  box-shadow:0 18px 36px -24px rgba(35,38,52,.6);
  display:flex;flex-direction:column;
}
.quad .card.q-ask .card-h{margin-bottom:2px;align-items:center}
.quad .card.q-ask .card-h h2{color:#fff;font-size:18px}
.quad .card.q-ask .cal-toggle{
  width:auto;height:22px;padding:0 9px;font-size:12px;border-radius:7px;
  background:rgba(255,255,255,.16);border-color:rgba(255,255,255,.24);color:#fff}
.quad .card.q-ask .cal-toggle:hover{background:rgba(255,255,255,.28);color:#fff}
.quad .q-ask .ask-badge{
  margin-left:auto;margin-right:6px;font-size:12px;letter-spacing:.1em;
  color:rgba(255,255,255,.62)}
.quad .card.q-ask .ask-tip{
  margin:2px 0 10px;font-size:12px;line-height:1.5;
  color:rgba(255,255,255,.76);letter-spacing:.01em}
.quad .card.q-ask .ask-row{display:flex;gap:7px;flex:none}
.quad .card.q-ask .adv-inp{
  flex:1;min-width:0;height:36px;background:#fff;border:0;border-radius:8px;
  color:var(--ink);font-size:12px;padding:0 11px}
.quad .card.q-ask .adv-inp::placeholder{color:var(--ink4)}
.quad .card.q-ask .ask-go{
  flex:none;height:36px;min-width:52px;padding:0 15px;border:0;border-radius:8px;
  background:#fff;color:#334c8f;font:inherit;font-size:13px;font-weight:600;
  letter-spacing:.04em;cursor:pointer;transition:background .15s,color .15s}
.quad .card.q-ask .ask-go:hover{background:#eef2fb;color:#263a6b}
.quad .card.q-ask .ask-ctxl{
  margin-top:12px;padding-top:10px;border-top:1px solid rgba(255,255,255,.18);
  font-size:12px;letter-spacing:.1em;color:rgba(255,255,255,.56)}
.quad .card.q-ask .adv-ctx{margin:6px 0 0;padding:0;border-top:0;
  display:flex;gap:6px;flex-wrap:nowrap;color:rgba(255,255,255,.8)}
.quad .card.q-ask .adv-ctx > .uisel{flex:1 1 0;min-width:0}
.quad .card.q-ask .uisel .uisel-btn{
  width:100%;min-width:0 !important;height:27px;font-size:12px;padding:0 8px;
  background:rgba(255,255,255,.14);border:1px solid rgba(255,255,255,.2);
  border-radius:7px;color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.quad .card.q-ask .uisel .uisel-btn:hover{background:rgba(255,255,255,.24)}
.quad .card.q-ask .ask-eg{
  margin-top:auto;padding-top:10px;display:none;flex-wrap:wrap;gap:6px;align-items:center}
.quad .card.q-ask.is-open .ask-eg{display:flex;margin-top:14px}
.quad .card.q-ask .ask-eg span{
  font-size:12px;color:rgba(255,255,255,.55);letter-spacing:.08em;margin-right:2px}
.quad .card.q-ask .ask-eg button{
  border:1px solid rgba(255,255,255,.22);background:rgba(255,255,255,.1);
  color:#fff;font:inherit;font-size:12px;padding:5px 10px;border-radius:20px;cursor:pointer}
.quad .card.q-ask .ask-eg button:hover{background:rgba(255,255,255,.22)}

/* 窄屏（单列）：日历宽卡不出现，问一句也不在卡片里，这里只兜字号 */
@media (max-width:699px){
  .top .sub{font-size:12px}
  .top .sub .sub-time{margin-left:9px;padding-left:9px}
}

/* ── 37.6 高度分配修正 ──────────────────────────────────────────
   日历横卡进左栏后，原来那条 `.desk-l > .quad{flex:1 1 0}` 会让
   卡片区去抢剩余高度 —— 但日历是按内容撑高的，卡片区抢不到就被压成一条。
   现在反过来：日历和四卡各按内容给高度，desk 的总高由左栏决定，
   右栏（align-items:stretch）跟着长。 */
@media (min-width:1280px){
  .desk-l > .quad{flex:0 0 auto;min-height:430px}
}
.cw-grid{grid-auto-rows:minmax(46px,auto)}

/* ── 37.7 高度收口 ─────────────────────────────────────────────
   1fr 那版让「问一句」和「最近记录」被拉成一样高（334），可它俩内容差一半，
   白白多出 130px，整页被顶到 1.8 屏。改成各行按内容高：
   待办跨两行 = 问一句 + 最近记录 + 间距，自然贴合。
   宽屏那条「待办 6 条」也收回 4 条 —— 卡宽从 795 变成 719，6 条会顶到滚动。 */
@media (min-width:700px){
  .quad{grid-template-rows:auto auto auto}
}
@media (min-width:1500px){
  .quad .q-recent:not(.is-open) .rec:nth-child(n+5){display:none}
}
.cw-grid{grid-auto-rows:minmax(44px,auto)}
.cw-grid .cd{min-height:44px}

/* ── 37.8 整页再压低一档 + 右栏跟随左栏高度 ────────────────────
   日历原来是被右侧当天清单（7 件）顶到 473 高的。清单给个上限自己滚，
   日历就按 6 行格子说话（约 390）。
   右栏内容撑不到左栏那么高之后，sticky 会让它的底部永远看不见，
   这里改成随页滚动，并把多出来的高度摊给时间轴和记录区（不再中间一大片白）。 */
.cw-day{max-height:298px}
.cw-cl{overflow-y:auto}
@media (min-width:1280px){
  .brief{position:static;max-height:none}
  .brief .brf-tlwrap{flex:1 1 auto}
  .brief .brf-7d{margin-top:auto}
  .brief .brf-bars{height:96px}
}
.quad .rec{padding:6px 0}

/* ── 37.9 末轮收口：日历再矮一档、窄屏字号回退 ─────────────── */
.cw-grid{grid-auto-rows:minmax(40px,auto)}
.cw-grid .cd{min-height:40px;padding:6px 7px}
.cw-grid .cd i{font-size:13px}
.cw-grid .cd-t{font-size:12px;-webkit-line-clamp:1}
@media (max-width:699px){
  .card-h h2{font-size:14.5px}
  .quad .rec b{font-size:13px}
  .quad .q-kids .kid b{font-size:12px}
}

/* ── 37.10 最近记录改单行 ─────────────────────────────────────
   原来是两行一条（标题上、时间下），4 条就顶到 310 高，把待办卡一起拽高。
   这个宽度下一条一行完全放得开：标题在左、孩子和时间在右。 */
.quad .rec{flex-direction:row;align-items:baseline;gap:10px;padding:7px 0}
.quad .rec b{flex:1;min-width:0;font-size:14.5px}
.quad .rec em{flex:none;font-size:12px}

/* ── 37.11 平板档（700~1099）：日历优先给宽度 ──────────────────
   768 这类宽度下，右侧当天清单固定吃 310，日历只剩 344、7 列挤成 49px。
   这个档位先把清单收起来（当天的事「今日待办」和「最近记录」里都有），
   把整宽让给日历；问一句的三个选择器也跟着换两行，不硬挤一行。 */
@media (max-width:1099px){
  .cw-body{grid-template-columns:minmax(0,1fr);gap:0}
  .cw-day{display:none}
  .quad .card.q-ask .adv-ctx{flex-wrap:wrap;gap:6px}
  .quad .card.q-ask .adv-ctx > .uisel{flex:1 1 30%}
}

/* ── 37.12 右栏填满 + 问一句选择器换行 ─────────────────────────
   右栏被左栏拉到 1100 高，原来多出的 400px 一坨空白堆在「这周内」下面。
   现在让近 7 天记录这块把剩余高度吃掉（柱子改成按百分比，跟着容器长），
   上半是今天的排班，下半是记录趋势，中间不再空一块。 */
@media (min-width:1280px){
  .brief .brf-tlwrap{flex:0 0 auto}
  .brief .brf-7d{flex:1 1 auto;display:flex;flex-direction:column;min-height:120px;margin-top:auto}
  .brief .brf-bars{flex:1 1 auto;height:auto;min-height:90px}
  .brief .brf-bar i{min-height:8px}
}
/* 选择器一律允许换行：1440 那档卡宽 340，三个药丸硬排一行会把字挤没 */
.quad .card.q-ask .adv-ctx{flex-wrap:wrap}
.quad .card.q-ask .adv-ctx > .uisel{flex:1 1 45%;min-width:96px}

/* ── 37.13 展开态：容器总高钉住，内容在卡内滚 ─────────────────
   flipCardOpen 会把展开前的高度写进 --quad-h。这里用它把卡片区锁死，
   两行各占一半，选中卡内容多就自己滚，整页不再跟着窜。 */
@media (min-width:700px){
  .quad.card-open{height:var(--quad-h,auto);
    grid-template-rows:minmax(0,1fr) minmax(0,1fr)}
  .quad.card-open > .card{min-height:0}
  .quad.card-open > .card.is-open .todos,
  .quad.card-open > .card.is-open .recs,
  .quad.card-open > .card.is-open .kids,
  .quad.card-open > .card.is-open .cw-cl{flex:1 1 auto;min-height:0;overflow-y:auto}
}

/* ═══════════ 38. 回到「主体 + 环绕」五卡结构，只做可读性 ═══════════
   上一版把日历提成整宽横卡是走偏了：待办不再是最大区块，页面也被拉长。
   这里恢复五卡环绕（待办左上跨两行、月历右上、最近记录右中、问一句左下、
   学生覆盖右下）。2026-11-04 老板定稿：日历固定显示完整月份，
   行高从写死的 fr 比例（86:158:112）改成 auto 按内容撑 ——
   整月 6 行格子需要 ~250px，死比例塞不下；多余空间仍会被均摊
   （grid 的 align-content 默认 stretch 会把 auto 行摊平），
   待办卡跨 1、2 行继续吃满两行的高度。 */

@media (min-width:700px){
  .quad{
    grid-template-columns:minmax(0,34fr) minmax(0,28fr) minmax(0,38fr);
    grid-template-rows:auto auto auto;
    aspect-ratio:auto;
    grid-template-areas:
      "todo todo cal"
      "todo todo recent"
      "ask  kids kids";
  }
  .quad .q-todo{grid-area:todo}
  .quad .q-cal{grid-area:cal}
  .quad .q-recent{grid-area:recent}
  .quad .q-kids{grid-area:kids}
  .quad .q-ask{grid-area:ask}
  /* 卡片区重新吃满左栏剩余高度（上一版为了日历横卡把它改成 0 0 auto） */
  .desk-l > .quad{flex:1 1 0;min-height:0}
}

/* ── 38.1 月历可读性：日期放大、对比加深、格子有辨识度 ──────────
   原来日期 10.5px + ink4 的灰，在浅底卡片上要凑近才认得出；
   格子又没有边界，七个数字像浮着。现在：日期 13px/600、墨色 ink2，
   格子给一层浅底 + 圆角，今天和选中日各有明确标记，圆点也加大到 4.5。
   收回来的高度：头、周标各压一档，把空间全给日期行。 */
.quad .card.q-cal:not(.is-open){padding:10px 14px 9px}
.quad .card.q-cal:not(.is-open) .cal-h{margin:0 0 4px}
.quad .card.q-cal:not(.is-open) .cal-h b{font-size:16px;letter-spacing:.01em}
.quad .card.q-cal:not(.is-open) .cal-h .cn button{width:19px;height:19px;font-size:12px}
.quad .card.q-cal:not(.is-open) .cal-h .cn .cal-toggle{width:auto;height:19px;padding:0 7px;font-size:12px}
.quad .card.q-cal:not(.is-open) .cal-wk span{
  font-size:12px;line-height:15px;padding:0;color:var(--ink4);letter-spacing:.06em}
.quad .card.q-cal:not(.is-open) .cal-grid{
  /* 整月 6 行的下限：159 = 6 行 × 24px + 5 道 3px 缝。flex-shrink 归零、
     min-height 抬到 159，卡片行（auto 行）就必须撑到整月的高度，
     不会再被右栏「今日调度」的高度上限压扁（2026-11-04 实测踩过）。 */
  flex:1 1 auto;min-height:159px;flex-shrink:0;
  grid-auto-rows:minmax(24px,1fr);row-gap:3px;column-gap:3px}
.quad .card.q-cal:not(.is-open) .cd{
  height:auto;min-height:24px;padding:2px 0 1px;gap:2px;border-radius:6px;
  background:rgba(255,255,255,.52);transition:background .14s}
.quad .card.q-cal:not(.is-open) .cd:hover{background:#fff}
.quad .card.q-cal:not(.is-open) .cd i{
  font-size:13px;font-weight:600;line-height:1.05;color:var(--ink2);
  font-variant-numeric:tabular-nums}
.quad .card.q-cal:not(.is-open) .cd.out{background:transparent}
.quad .card.q-cal:not(.is-open) .cd.out i{color:#c5c9d3}
.quad .card.q-cal:not(.is-open) .cd.today{background:#fff;box-shadow:inset 0 0 0 1px var(--blue-ring)}
.quad .card.q-cal:not(.is-open) .cd.today i{color:var(--blue-d);font-weight:700}
.quad .card.q-cal:not(.is-open) .cd.sel{background:var(--blue-soft);
  box-shadow:inset 0 0 0 1px rgba(58,81,153,.35)}
.quad .card.q-cal:not(.is-open) .cd.sel i{color:var(--blue-d);font-weight:700}
.quad .card.q-cal:not(.is-open) .cd .dots{height:auto;gap:3px}
.quad .card.q-cal:not(.is-open) .cd .dot{width:4.5px;height:4.5px}
.quad .card.q-cal:not(.is-open) .cal-ft{display:none}

/* ── 38.2 高度来源分档 ─────────────────────────────────────────
   日历改整月（2026-11-04）后，行高全部按内容撑，aspect-ratio 的
   死比例框（648:374 / 648:500）在窄档会把整月裁掉，全部放开：
   卡片区高度 = 五张卡内容的自然和；≥1280 有右栏时仍先吃满剩余高度，
   不够再由内容把整体撑高。 */
@media (min-width:700px) and (max-width:1279px){
  .desk-l > .quad{flex:0 0 auto;aspect-ratio:auto;min-height:0}
}
@media (min-width:1280px){
  /* flex:1 0 auto（2026-11-04 日历改整月后）：growth 照旧吃满剩余高度，
     但 shrink 归零 + basis auto —— 整月内容（~573px）超过右栏
     「今日调度」给的剩余高度（~502px）时，quad 按内容撑、不再被压，
     页面滚动兜底。原 flex:1 1 0 的 shrink 1 会把它压回 502，
     整月底部两行被裁（实测踩过）。 */
  .desk-l > .quad{flex:1 0 auto;aspect-ratio:auto;min-height:0}
}

/* ── 38.3 日历格子的辨识度：白卡上再放白块 = 没有边界 ─────────
   改成浅灰块 + 日期与圆点同排（原来圆点压在日期下面，30px 高里两层挤），
   周标也提亮一档。今天/选中日仍用白底+主色描边，三者一眼能分开。 */
.quad .card.q-cal:not(.is-open) .cd{
  flex-direction:row;align-items:center;justify-content:center;gap:4px;
  background:rgba(35,38,52,.045)}
.quad .card.q-cal:not(.is-open) .cd:hover{background:rgba(35,38,52,.085)}
.quad .card.q-cal:not(.is-open) .cd .dots{flex:none}
.quad .card.q-cal:not(.is-open) .cd.out{background:transparent}
.quad .card.q-cal:not(.is-open) .cd.today{background:#fff;
  box-shadow:inset 0 0 0 1.5px var(--blue)}
.quad .card.q-cal:not(.is-open) .cd.sel{background:var(--blue-soft);
  box-shadow:inset 0 0 0 1.5px var(--blue-d)}
.quad .card.q-cal:not(.is-open) .cal-wk span{
  font-size:12px;color:var(--ink3);font-weight:500;line-height:16px}

/* 圆点实际是 .dots > b（不是 .dot），尺寸要按这个选择器给 */
.quad .card.q-cal:not(.is-open) .cd .dots{display:flex;gap:3px;align-items:center;height:auto}
.quad .card.q-cal:not(.is-open) .cd .dots b{width:4.5px;height:4.5px;border-radius:50%}
.quad .card.q-cal:not(.is-open) .cd .dots .d-hard{background:#b5453a}
.quad .card.q-cal:not(.is-open) .cd .dots .d-todo{background:rgba(58,81,153,.55)}
.quad .card.q-cal:not(.is-open) .cd .dots .d-ev{background:rgba(58,81,153,.26)}

/* 超过 3 件的 +N 是原有标记，缩小一档、退成辅助信息，不再和圆点抢位置 */
.quad .card.q-cal:not(.is-open) .cd .dots .d-more{
  font-style:normal;font-size:12px;line-height:1;color:var(--ink2);margin-left:1px;
  font-variant-numeric:tabular-nums}

/* ═══════════ 39. 让出高度 + 月历回归「网格」形态 ═════════════════
   两件事：
   ① 1280 高的屏幕上内容只到 1083，底下空一截，可「问一句」却被底行
      171px 的格子切掉了第三行选择器。把面板高度上限从 780 抬到 900，
      多出来的高度全给卡片区，底行从 171 → 294，问一句能完整站住。
   ② 月历现在是「一排圆角药丸 + 几个日期」，看不出是日历。改回真正的
      网格：格子之间 1px 缝隙露出底色当网格线，星期行做成表头，整块
      连成一张表；今天用实心圆，选中日浅蓝底，日期居中等宽。 */

@media (min-width:1280px){
  .brief{min-height:clamp(644px, calc(100vh - 300px), 900px)}
}
@media (min-width:700px){
  .quad{grid-template-rows:minmax(0,86fr) minmax(0,150fr) minmax(0,150fr)}
}

/* 表头：星期行做成一条压深的分隔带 */
.quad .card.q-cal:not(.is-open) .cal-wk{
  display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:1px;
  background:rgba(35,38,52,.055);border-radius:7px 7px 0 0;
  padding:3px 0;margin:0}
.quad .card.q-cal:not(.is-open) .cal-wk span{
  font-size:12px;line-height:14px;font-weight:600;color:var(--ink3);
  letter-spacing:.08em;padding:0;border:0}

/* 日期区：1px 缝隙 + 底色 = 网格线，格子本身方方正正
   （min-height:159 下限与 beta-skin 末条媒体查询保持一致，防止再被清零） */
.quad .card.q-cal:not(.is-open) .cal-grid{
  flex:1 1 auto;min-height:159px;flex-shrink:0;
  display:grid;grid-template-columns:repeat(7,minmax(0,1fr));
  grid-auto-rows:minmax(22px,1fr);
  gap:1px;padding:1px;background:rgba(35,38,52,.1);
  border-radius:0 0 7px 7px;overflow:hidden}
.quad .card.q-cal:not(.is-open) .cd{
  border-radius:0;background:#fbfaf7;
  height:auto;min-height:0;padding:0;
  display:flex;flex-direction:row;align-items:center;justify-content:center;gap:3px;
  box-shadow:none;transition:background .12s}
.quad .card.q-cal:not(.is-open) .cd:hover{background:#fff;box-shadow:none}
.quad .card.q-cal:not(.is-open) .cd.out{background:#f4f2ee}
.quad .card.q-cal:not(.is-open) .cd.out i{color:var(--ink4)}
/* 今天：实心主色圆；选中（非今天）：浅蓝底 + 内描边 */
.quad .card.q-cal:not(.is-open) .cd.today{background:#fff;box-shadow:none}
.quad .card.q-cal:not(.is-open) .cd.today i{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:20px;height:20px;padding:0 4px;border-radius:10px;
  background:var(--blue);color:#fff;font-weight:700}
.quad .card.q-cal:not(.is-open) .cd.sel{background:var(--blue-soft);box-shadow:none}
.quad .card.q-cal:not(.is-open) .cd.sel i{color:var(--blue-d);font-weight:700}
.quad .card.q-cal:not(.is-open) .cd.today.sel i{background:var(--blue-d)}

/* 页面底部收一档，别在最后留一条空带 */
.wrap{padding-bottom:64px}

/* ── 39.1 今天的标记别吃掉数字 ────────────────────────────────
   实心圆在 23px 高的格子里会把「31」压成一坨白点，两个数字根本认不出。
   改成整格浅蓝底 + 日期主色加粗：标记在格子上，不在数字上。
   顺带给日历那一行再多 14px（85 → 96），两排日期从 23 抬到 31。 */
@media (min-width:700px){
  .quad{grid-template-rows:minmax(0,96fr) minmax(0,146fr) minmax(0,144fr)}
}
.quad .card.q-cal:not(.is-open) .cd.today{background:var(--blue-soft)}
.quad .card.q-cal:not(.is-open) .cd.today i{
  display:inline;min-width:0;height:auto;padding:0;border-radius:0;
  background:transparent;color:var(--blue-d);font-weight:800}
.quad .card.q-cal:not(.is-open) .cd.sel{background:rgba(58,81,153,.14)}
.quad .card.q-cal:not(.is-open) .cd.today.sel{background:rgba(58,81,153,.2)}
.quad .card.q-cal:not(.is-open) .cd.today.sel i{background:transparent}
/* 圆点提一档浓度，别在网格里消失 */
.quad .card.q-cal:not(.is-open) .cd .dots .d-ev{background:rgba(58,81,153,.38)}
.quad .card.q-cal:not(.is-open) .cd .dots .d-todo{background:rgba(58,81,153,.62)}

/* ── 39.2 问一句必须完整站住 ──────────────────────────────────
   底行 203 时内容要 207（标题24 + 说明18 + 输入36 + 标签29 + 两行选择器74
   + 内距27）—— 说明那行被 flex 压成了 0 高，最后一行选择器溢出 4px 被切。
   两条一起改：底行再加 12，并把卡里的每一块设成不收缩，宁可卡内滚动也不压字。 */
/* 2026-11-04 日历改整月后行高全部交给内容（见 38 节），下面的 fr 比例
   只会跟 auto 行打架，统一归回 auto —— 问一句卡的内容高度由 40 节的
   flex:0 0 auto 兜底，不会再被压字。 */
@media (min-width:700px){
  .quad{grid-template-rows:auto auto auto}
}
.quad .card.q-ask > *{flex:0 0 auto}
.quad .card.q-ask .ask-tip{margin:2px 0 9px;min-height:17px}
.quad .card.q-ask .ask-ctxl{margin-top:9px;padding-top:8px}
.quad .card.q-ask .uisel .uisel-btn{height:26px}
.quad .card.q-ask .adv-ctx{gap:5px}

/* 差 1px 也是溢出：底行再 7px，选择器外框一并压到 28 */
/* 行高已归 auto（见上），此处只保留选择器尺寸的修正 */
.quad .card.q-ask .adv-ctx > .uisel{height:28px}
.quad .card.q-ask .ask-ctxl{margin-top:7px;padding-top:6px;font-size:12px}

/* ── 39.3 平板档（700~1279 单列）──────────────────────────────
   原来按 648:500 撑是为了给问一句让出底行；行高改 auto 后比例框
   反而会把整月日历裁掉，放开让内容自然撑高。学生格的字回退保留。 */
@media (min-width:700px) and (max-width:1279px){
  .quad .q-kids .kid b{font-size:12px}
  .quad .q-kids .kid em{font-size:12px}
}

/* ═══════════ 40. 问一句卡：输入框顺序 + 展开态填满 ═══════════
   ① 小布局下「问」按钮跑到输入框左边 —— 根因已查明并在源头修掉：
      app.css 的 @media(max-width:768px) 里有裸 `.adv-inp{order:3}`，
      本是给内页提问横栏换行用的，class 同名于是溢到本卡。
      那边已收窄成 `.adv-bar .adv-inp`；这里保留一层防御性归零，
      防止以后有人再往 adv-inp 上写 order。
   ② 大屏展开后内容只占上半截。改成把内容摊开 + 输入框加高 + 试例放大，
      让节奏跟着卡片高度走。 */
.quad .card.q-ask .ask-row{display:flex;flex-direction:row;align-items:stretch}
.quad .card.q-ask .ask-row > .adv-inp{order:0;flex:1 1 auto;min-width:0}
.quad .card.q-ask .ask-row > .ask-go{order:1;flex:0 0 auto}

.quad.card-open > .q-ask.is-open{justify-content:space-between;padding:22px 24px 22px}
.quad.card-open > .q-ask.is-open .card-h{margin-bottom:0}
.quad.card-open > .q-ask.is-open .card-h h2{font-size:22px}
.quad.card-open > .q-ask.is-open .ask-tip{font-size:13px;margin:0}
.quad.card-open > .q-ask.is-open .adv-inp{height:52px;font-size:14.5px;padding:0 16px}
.quad.card-open > .q-ask.is-open .ask-go{height:52px;font-size:14.5px;min-width:64px}
.quad.card-open > .q-ask.is-open .ask-ctxl{font-size:12px;margin-top:0;padding-top:0;border-top:0}
.quad.card-open > .q-ask.is-open .adv-ctx{gap:8px}
.quad.card-open > .q-ask.is-open .uisel .uisel-btn{height:34px;font-size:12px;padding:0 12px}
.quad.card-open > .q-ask.is-open .ask-eg{display:flex;margin-top:0;padding-top:0;border-top:0;gap:9px}
.quad.card-open > .q-ask.is-open .ask-eg span{font-size:12px}
.quad.card-open > .q-ask.is-open .ask-eg button{font-size:12px;padding:8px 15px;border-radius:22px}

/* ── 40.1 问一句展开时不该占半屏 ─────────────────────────────
   space-between 只是把空白摊成三条大缝，比原来还难看。
   根子是：展开态的行高是 1fr，卡片被迫拉满，而这张卡的内容就那么点。
   用 :has() 单独给「问一句展开」这一种情况改成 auto 行 ——
   卡片按内容给高度，其余四张在下面一行平分剩下的空间。 */
@media (min-width:700px){
  .quad.card-open:has(.q-ask.is-open){
    grid-template-rows:auto minmax(0,1fr);
    height:auto;min-height:var(--quad-h,auto)}
  .quad.card-open > .q-ask.is-open{justify-content:flex-start}
}

/* :has() 这条在 Edge 上没吃到，改用 flipCardOpen 打的 .card-open-ask */
@media (min-width:700px){
  .quad.card-open.card-open-ask{
    grid-template-rows:auto minmax(0,1fr);
    height:auto;min-height:var(--quad-h,auto);max-height:var(--quad-h,auto)}
}

/* 展开的「问一句」只占内容高度：靠 align-self 取消拉伸即可，
   不要再去改 grid-template-rows（那会把展开态的网格行数算乱）。 */
@media (min-width:700px){
  .quad.card-open > .q-ask.is-open{align-self:start;height:auto}
  .quad.card-open > .q-ask.is-open .ask-eg{margin-top:14px}
}
