/* ─────────────────────────────────────────────
   工作台 · 应用层样式（在 ui.css 之上）
   只补「页面切换 / 表单 / 编辑 / 弹层 / 空态」，
   视觉规范全部沿用 ui.css：16px 模块间距、19px 卡片内距、--blue 唯一强调色。
   ───────────────────────────────────────────── */

/* 视图切换 */
.view{display:none}
.view.on{display:block;animation:viewIn .42s var(--ease) both}
@keyframes viewIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}

/* 页面标题行（内页统一走这行，比看板版多一个返回位） */
.pg-head{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;
  padding:30px 0 18px;flex-wrap:wrap}
/* 2026-11-09 返工：字号抬到 12px 后，学生页 .hl 481.5 + .hr 612.2 = 1093.7 > 容器 1049，
   撞上第 13 行的 flex-wrap:wrap，整个按钮组掉到标题下面，页头 150 → 210px。
   给 .hl 允许收缩 + 吸收剩余空间，让按钮组留在同一行。 */
.pg-head .hl{flex:1 1 auto;min-width:0}
.pg-head h1{font-size:23px;font-weight:640;letter-spacing:-.03em;margin:0;line-height:1.25}
.pg-head .sub{margin:7px 0 0;font-size:12px;color:var(--ink3)}
.pg-head .hr{display:flex;align-items:center;gap:8px;flex-wrap:wrap}

/* 小号次级按钮 */
.btn.sm{height:33px;font-size:13px;padding:0 15px}
.btn.pale{background:rgba(0,0,0,.045);color:var(--ink2);box-shadow:none}
.btn.pale:hover{background:rgba(0,0,0,.075);color:var(--ink);box-shadow:none}
.btn.danger{background:rgba(255,59,48,.09);color:#C7362C;box-shadow:none}
.btn.danger:hover{background:rgba(255,59,48,.15);box-shadow:none}
.btn[disabled]{opacity:.45;pointer-events:none}

/* 卡片内的通用行（待办全览、材料全览） */
.rows{display:flex;flex-direction:column;margin:2px -8px 0}
.row{display:flex;align-items:center;gap:11px;padding:11px 8px;border-radius:12px;
  cursor:pointer;transition:background .3s var(--ease)}
.row:hover{background:rgba(0,0,0,.026)}
.row:active{transform:scale(.996)}
.row .g{flex:1;min-width:0}
.row .g b{display:block;font-size:13px;font-weight:500;letter-spacing:-.01em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.row .g span{display:block;font-size:12px;color:var(--ink3);margin-top:2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.row .x{flex:none;font-size:12px;color:var(--ink4);font-variant-numeric:tabular-nums}
.row .del{flex:none;width:26px;height:26px;border:0;border-radius:50%;background:transparent;
  color:var(--ink4);cursor:pointer;display:grid;place-items:center;opacity:0;
  transition:opacity .25s,background .25s,color .25s}
.row:hover .del{opacity:1}
.row .del:hover{background:rgba(255,59,48,.1);color:#C7362C}

/* 分组标题（今天 / 本周 / 更早） */
.grp{font-size:12px;color:var(--ink4);letter-spacing:.06em;padding:14px 8px 6px}
.grp:first-child{padding-top:4px}

/* 表单 */
.form{display:flex;flex-direction:column;gap:13px;margin-top:4px}
.fld{display:flex;flex-direction:column;gap:6px;min-width:0}
.fld > label{font-size:12px;color:var(--ink3);letter-spacing:.01em}
.fld > label b{color:#C7362C;font-weight:600;margin-left:2px}
.inp,.sel,.ta{
  width:100%;font:inherit;font-size:var(--fs-sm);color:var(--ink);letter-spacing:-.005em;
  background:var(--field-2);border:1px solid var(--fill-2);border-radius:var(--r-sm);
  padding:var(--sp-2) var(--sp-3);outline:none;
  transition:border-color .3s,box-shadow .3s,background .3s}
/* 单行控件高度统一到 --h-field。
   以前同一行里三个高度：.inp 靠 padding 撑出约 34、.sel 被页面内联写成 33、
   自绘下拉 .uisel-btn 自己写 32 —— 并排时总是差 1~2px，看着像没对齐。 */
.inp,.sel{height:var(--h-field);padding-top:0;padding-bottom:0}

.inp:focus,.sel:focus,.ta:focus{border-color:var(--blue-ring);background:var(--field);
  box-shadow:0 0 0 3.5px var(--brand-100)}

/* 文本域：手机上"里面滚不动、一划整页跟着走"的三个成因，这里一次钉死。
   ① resize 在触摸屏上会把滚动让给父级 —— 只在有鼠标时开；
   ② 缺 overscroll-behavior 时，滚到底会链式带动页面 —— contain 断掉；
   ③ -webkit-overflow-scrolling 让 iOS 内部滚动用原生惯性。 */
.ta{
  min-height:var(--h-ta-min);max-height:var(--h-ta-max);line-height:1.7;
  overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;
  touch-action:pan-y}
@media (hover:hover) and (pointer:fine){
  .ta{resize:vertical}
}
.sel{appearance:none;background-image:var(--chev);
  background-repeat:no-repeat;background-position:right 12px center;padding-right:30px}
.f2{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:13px}
.f3{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr) minmax(0,1fr);gap:13px}
.hintx{font-size:12px;color:var(--ink4);line-height:1.6}

/* 多选片（学生、事件）：玻璃底子，选中渐变填满，对勾从左侧长出 */
.picks{display:flex;flex-wrap:wrap;gap:6px;max-height:168px;overflow:auto;
  -webkit-overflow-scrolling:touch;overscroll-behavior:contain;
  padding:2px 2px 2px 0;margin:0 -2px}
.pk{appearance:none;font:inherit;font-size:12px;color:var(--ink2);cursor:pointer;
  white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis;
  padding:6px 11px;border-radius:980px;border:1px solid rgba(255,255,255,.6);
  background:rgba(255,255,255,.3);
  -webkit-backdrop-filter:blur(10px) saturate(160%);backdrop-filter:blur(10px) saturate(160%);
  box-shadow:0 1px 2px rgba(0,0,0,.045),inset 0 1px 0 rgba(255,255,255,.55);
  transition:all .28s var(--ease);white-space:nowrap}
.pk:hover{border-color:rgba(255,255,255,.85);background:rgba(255,255,255,.5)}
.pk.on{background:var(--sel-grad);border-color:transparent;color:#fff;font-weight:500;
  box-shadow:0 6px 16px -8px rgba(46,160,180,.9)}
.pk::before{content:"✓";display:inline-block;max-width:0;opacity:0;font-size:12px;font-weight:600;
  overflow:hidden;transform:translateX(-5px);vertical-align:1px;
  transition:max-width .36s var(--spring),opacity .2s,transform .32s var(--spring),margin .3s var(--ease)}
.pk.on::before{max-width:16px;opacity:1;transform:none;margin-right:4px}

/* 可删除标签：点叉号缩成圆点消失，后面的标签依次补位（配合 .shrink） */
.pk .x{font-style:normal;display:inline-grid;place-items:center;width:14px;height:14px;
  margin-left:6px;margin-right:-4px;border-radius:50%;background:rgba(0,0,0,.12);
  font-size:12px;line-height:1;cursor:pointer;transition:background .2s,transform .2s}
.pk .x:hover{background:rgba(0,0,0,.28);transform:scale(1.12)}
/* 职务片右侧的范围小字：班级 / 年级组 / 全园 —— 选之前就知道会写成多大口径 */
.pk .dv{font-style:normal;font-size:12px;line-height:1.4;margin-left:6px;padding:1px 5px;
  border-radius:6px;background:rgba(60,45,100,.075);color:var(--ink3);vertical-align:1px}
.pk.on .dv{background:rgba(255,255,255,.32);color:#fff}
/* 多选时第一个职务是主视角，给它一圈亮边 */
.pk.prim{box-shadow:0 0 0 2px rgba(255,255,255,.9),0 3px 10px -3px var(--sel-ring)}
.pk.on .x{background:rgba(255,255,255,.3)}
.pk.on .x:hover{background:rgba(255,255,255,.5)}
.pk.shrink{font-size:0!important;color:transparent!important;pointer-events:none;
  padding-left:0!important;padding-right:0!important;
  transform:scale(.3)!important;opacity:0!important}
.pk.shrink::before{max-width:0!important;opacity:0!important;margin:0!important}
.pk.shrink .x{display:none}

/* 输入联想浮层：磨砂玻璃，随输入实时筛选 */
.sg-pop{position:absolute;top:calc(100% + 6px);left:0;z-index:130;min-width:180px;max-width:290px;
  max-height:212px;overflow:auto;border-radius:14px;padding:6px;
  background:rgba(255,255,255,.88);
  -webkit-backdrop-filter:blur(24px) saturate(180%);backdrop-filter:blur(24px) saturate(180%);
  border:1px solid rgba(255,255,255,.95);box-shadow:0 1px 1px rgba(0,0,0,.03),0 18px 44px -20px rgba(35,38,52,.35);
  animation:sgIn .22s var(--ease) both}
@keyframes sgIn{from{opacity:0;transform:translateY(5px) scale(.98)}to{opacity:1;transform:none}}
.sg-pop button{display:flex;align-items:center;gap:7px;width:100%;border:0;background:transparent;
  font:inherit;font-size:13px;color:var(--ink);padding:7px 9px;border-radius:9px;cursor:pointer;
  text-align:left;transition:background .18s}
.sg-pop button:hover{background:rgba(0,113,227,.1)}
.sg-pop button em{font-style:normal;font-size:12px;color:var(--ink4);margin-left:auto;flex:none}

/* 管家带过来的写作单：一条发丝线提示，不是卡片套卡片。
   作用只有一个 —— 让老师一眼看出「这些不是我自己填的」，并给她一键改回手填的出口。 */
.wintent{display:flex;align-items:center;gap:var(--sp-3);margin:0 0 14px;
  padding:10px 0;border-bottom:1px solid var(--line-soft)}
.wintent .wi-i{flex:none;width:26px;height:26px;border-radius:50%;display:grid;place-items:center;
  background:rgba(0,113,227,.09);color:var(--brand-500)}
.wintent .wi-t{flex:1;min-width:0}
.wintent .wi-t b{display:block;font-size:var(--fs-sm);letter-spacing:-.01em}
.wintent .wi-t em{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  font-style:normal;font-size:var(--fs-xs);color:#6F697C;margin-top:3px;line-height:1.62}
.wintent .btn{flex:none}
@media (max-width:640px){
  .wintent .wi-t em{-webkit-line-clamp:3}
}

/* 管家筛过的筛选条：一条发丝线，不是又一张卡片。
   为什么非要显出来：她点「办」进来看到只剩两条，不说一句就会以为数据丢了。 */
.qhit{display:flex;align-items:center;gap:var(--sp-3);margin:0 0 12px;padding:9px 0;
  border-bottom:1px solid var(--line-soft);font-size:var(--fs-sm);color:var(--ink4)}
.qhit span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.qhit b{color:var(--ink);font-weight:600}
.qhit .btn{flex:none}

/* 管家指到的那一条：滚进视野后亮一下再褪掉（2.6s 后由 JS 摘掉 .hitpulse）。
   只描边不填充 —— 填充会把这条和「选中」混淆，而她这会只是「看这里」。 */
@keyframes hitPulse{
  0%{box-shadow:0 0 0 0 rgba(0,113,227,.34), inset 0 0 0 1px rgba(0,113,227,.42);background:rgba(0,113,227,.075)}
  55%{box-shadow:0 0 0 7px rgba(0,113,227,0), inset 0 0 0 1px rgba(0,113,227,.30);background:rgba(0,113,227,.05)}
  100%{box-shadow:0 0 0 0 rgba(0,113,227,0), inset 0 0 0 1px rgba(0,113,227,0);background:transparent}
}
.hitpulse{animation:hitPulse 2.4s cubic-bezier(.22,.61,.36,1) both;border-radius:var(--r-sm)}
@media (prefers-reduced-motion:reduce){
  /* 不动的人也得知道是哪一条：留一条静态左边线，2.6s 后同样褪掉 */
  .hitpulse{animation:none;box-shadow:inset 2px 0 0 var(--brand-500);background:rgba(0,113,227,.06)}
}

/* 双栏编辑（左选素材 / 右出稿）
   ── 方案 B：把两栏锁进视口，各自独立滚 ──
   以前 .wgrid 只有 align-items:start，高度由内容决定：留栏 2215px、长稿时整页 3634px，
   读全文必须整页滚，一滚左边的设定全走，改一句要滚回顶、改完再滚下来 ——
   「生成 → 读 → 改 → 再生成」这个核心循环被物理打断。
   现在 grid 固定为视口高度，左栏和稿纸各滚各的：左边永远整块可见，右边读全文不用滚页面。
   --w-h 由 fitWrite() 实测写入（页头 + 意图条的实际高度，文案变了也不会错位）；
   脚本没跑到时退回 186px，是当前版式下的实测值。 */
.wgrid{display:grid;grid-template-columns:330px minmax(0,1fr);gap:16px;align-items:stretch;margin-top:0;
  height:var(--w-h,calc(100dvh - 186px));min-height:420px}
.wside{display:flex;flex-direction:column;gap:var(--sp-3);position:relative;top:auto;
  align-self:stretch;max-height:100%;min-height:0;
  overflow-y:auto;overscroll-behavior:contain;scrollbar-gutter:stable;
  /* 底部留一点余气，滚到最后一张卡不会被切在边上 */
  padding:1px 2px 14px 1px}
.ed{min-height:420px;font-size:14.5px;line-height:1.9;letter-spacing:.002em;
  border:0;background:transparent;padding:0;resize:none;width:100%;color:var(--ink);outline:none}
.ed:focus{box-shadow:none;border:0;background:transparent}
/* 稿纸：跟左边一起 sticky，并至少占一屏（减掉页头）。
   原来它按内容只有六百多高，左列五六张卡一千五，右下就空出一大片背景 —— 那是"丑"的来源。
   改成一屏高并跟随滚动后，右边永远有东西，空白变成纸的一部分。
   注意：这条是全局的，材料详情页（#/docs/…）也用 .paperbox 的长文档形态，
   所以写稿页的「锁进视口 + 内滚」只在下面 .wgrid > .paperbox 里覆盖，不动这里。 */
.paperbox{padding:26px 30px 22px;min-height:520px;display:flex;flex-direction:column;
  position:sticky;top:20px;min-height:calc(100vh - 132px)}
/* 写稿页专用：sticky 在定高容器里没有意义，改成 relative，
   把定位上下文交给它自己，内部的 paperbar 才能 sticky 到底。 */
.wgrid > .paperbox{position:relative;top:auto;height:100%;min-height:0;
  overflow-y:auto;overscroll-behavior:contain}
.paperbox .ptitle{font-size:19px;font-weight:640;letter-spacing:-.02em;margin:0 0 4px}
.paperbox .pmeta{font-size:12px;color:var(--ink4);margin:0 0 18px;padding-bottom:14px;
  border-bottom:1px solid var(--line);display:flex;gap:10px;flex-wrap:wrap;align-items:center}
/* 类型就地改：跟 pmeta 的字号对齐的一颗小下拉 */
.paperbox .pmeta .doc-tsel{height:22px;min-height:0;line-height:20px;padding:0 22px 0 7px;
  border-radius:7px;font-size:12px;border:1px solid var(--line);background-color:#fff;color:var(--ink);
  max-width:190px;flex:0 0 auto}
.paperbox .ed{flex:1}
/* 正文编辑框的起始高度：桌面 520，手机 320（以前写在内联 style 上，媒体查询压不动） */
.paperbox .ed-body{min-height:520px}
/* 上传的原图：铺满正文宽、超长自己滚，等比不裁切。
   手机上一屏放不下整张照片是正常的，所以给个封顶高度 + 内部滚动。 */
.doc-att{margin:0 0 14px;border:1px solid var(--line-soft);border-radius:12px;overflow:hidden;background:#fff}
.doc-att img{display:block;width:100%;max-height:460px;object-fit:contain;background:#f4f5f7}
.doc-att .cap{padding:6px 10px;font-size:12px;color:var(--ink4);border-top:1px solid var(--line-soft);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
@media (max-width:640px){
  .doc-att img{max-height:320px}
}
/* 底部两条操作带永远贴住稿纸视口下沿：读长文时光标滚到哪，
   「保存 / 导出 / 改一改」都还在手边，不用再滚到底。 */
.wgrid .paperbar,
.wgrid .polishbar{position:sticky;bottom:0;z-index:4;margin-bottom:-1px;
  background:linear-gradient(to bottom,rgba(255,255,255,0),var(--card,#fff) 14px);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.paperbar{display:flex;align-items:center;gap:8px;margin-top:16px;padding-top:14px;
  border-top:1px solid var(--line);flex-wrap:wrap}
.paperbar .wc{font-size:12px;color:var(--ink4);margin-left:auto;font-variant-numeric:tabular-nums}

/* ───────── 写稿侧栏：统一卡片头 + 可折叠分组 ─────────
   以前六张卡各写各的：有的带计数有的不带，高度从 176 到 732 不等，
   视口 811 只装得下第一张「写什么」。现在统一成
   「序号 + 标题 + 这一项的当前值 + 折角」一行 —— 折起来就是一条索引，
   展开才占地。这是让整个侧栏「看着是一套东西」的关键，
   不是给每张卡单独换个样式。 */
/* 注意 poju-skin.css 在 app.css 之后加载，.card{padding:17px 20px 16px} 会盖掉
   同特异性的 .wacc{padding:0}，所以这里必须带 .wside 前缀压过去。 */
.wacc{padding:0;overflow:hidden}
/* 关键：.wacc 是 .wside（flex column）的子项，一旦 overflow:hidden 就失去
   「min-height:auto」这层自动最小尺寸保护，会被 flex 压缩到几十像素、
   内容全被裁掉（第一版就是这样：写什么卡 732 被压成 167，主题/周次/补充要求
   明明在 DOM 里却一个都看不见）。显式禁止收缩，让它按内容长。 */
.wside > .wacc{padding:0;flex:0 0 auto}
.wacc-h{display:flex;align-items:center;gap:8px;width:100%;
  padding:12px 18px 11px;margin:0;border:0;border-bottom:1px solid var(--hairline);
  background:none;color:inherit;text-align:left;cursor:pointer;appearance:none;
  transition:background .16s ease}
.wacc-h:hover{background:rgba(47,102,144,.035)}
.wacc-h:focus-visible{outline:2px solid var(--blue-ring,#9fb0dd);outline-offset:-2px}
.wacc-ix{flex:none;font-size:12px;letter-spacing:.12em;color:var(--ink4);
  font-variant-numeric:tabular-nums;padding-top:1px}
.wacc-h h2{flex:none;margin:0;font-family:var(--v2-serif,Georgia,serif);font-size:14.5px;
  font-weight:800;letter-spacing:.03em;color:var(--ink)}
.wacc-h .cnt{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;font-size:12px;letter-spacing:.08em;color:var(--ink4);
  text-align:left}
.wacc-cv{flex:none;width:6px;height:6px;margin-left:auto;
  border-right:1.5px solid var(--ink4);border-bottom:1.5px solid var(--ink4);
  transform:rotate(45deg);transition:transform .24s var(--ease,cubic-bezier(.22,.61,.36,1))}
.wacc.is-fold .wacc-cv{transform:rotate(-45deg)}
.wacc.is-fold .wacc-h{border-bottom-color:transparent}
.wacc.is-fold .wacc-h{padding-bottom:12px}
.wacc-body{padding:14px 20px 16px}
.wacc.is-fold .wacc-body{display:none}
/* 「补充事实与要求」：技能事实 + 补充要求这两块加起来 213px，但它们是可选项 ——
   不填也能生成，填了才更准。收成一条 34px 的分隔行，标题上写清已填几项，
   收起来也不至于成黑盒。要填再点开，输入框仍在 DOM 里（生成时照旧读得到）。 */
.wmore{margin-top:14px;border-top:1px solid var(--hairline)}
.wmore-h{display:flex;align-items:center;gap:8px;width:100%;padding:9px 0 8px;
  border:0;background:none;cursor:pointer;text-align:left;font:inherit;color:inherit}
.wmore-h > span:first-child{flex:none;font-size:12px;color:var(--ink2);font-weight:550}
.wmore-h .hintx{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;margin:0;font-size:12px}
.wmore-h .wacc-cv{margin-left:auto}
.wmore.is-fold .wmore-b{display:none}
.wmore.is-fold .wacc-cv{transform:rotate(-45deg)}
.wmore-b{padding-bottom:2px}
/* 折叠态卡片别跟着 .glass 的透明度变化，保持和展开态同一个底面，
   否则一排折叠卡看着像被禁用了 */
.wside > .wacc.is-fold{opacity:1}

/* 「写什么」瘦身：分组 + 类型两排 chips 在 330px 里各折成 2~3 行，
   单这一块就吃掉 200px。改成各自单行横滚（切边就是「还能往右」的提示），
   高度降到 90 左右，一屏能多露出后面两张卡。 */
.wacc[data-wacc="what"] .chips{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;
  scrollbar-width:none;-ms-overflow-style:none;
  /* chips 的负外边距补偿：滚动条位置会吃掉 3px 视觉间距 */
  padding-bottom:2px;margin-bottom:6px}
/* 分组那条原本是 grid:repeat(6,1fr)+max-width:348，在 330 的栏里每列只剩
   44px，「观察与故事」五个字放不下，硬折成两三行。这里统一成单行横滚，
   和其它 chips 一条规矩，也顺手把 200px 的高度省掉。 */
.wacc[data-wacc="what"] .chips.grp{display:flex;flex-wrap:nowrap;max-width:none;
  overflow-x:auto;overflow-y:hidden}
.wacc[data-wacc="what"] .chips::-webkit-scrollbar{display:none}
.wacc[data-wacc="what"] .chip{flex:none}
/* 2026-11-07 老板反馈：电脑端被「挡死」——桌面没有触摸滑动，滚动条又藏了，
   右边的组/类型永远看不见。精确指针（电脑）改回自然换行；
   手机保留单行横滚（触摸滑动顺畅、省高度，切边就是「还能往右」）。 */
@media (hover:hover) and (pointer:fine){
  .wacc[data-wacc="what"] .chips,
  .wacc[data-wacc="what"] .chips.grp{flex-wrap:wrap;overflow-x:visible;overflow-y:visible}
}
.wacc[data-wacc="what"] .chips.grp .chip{font-size:12px;letter-spacing:.04em}
.wacc[data-wacc="what"] .form{margin-top:12px}
/* 折叠头里的小开关（周次/场景）不该吃掉标题宽度 */
.wacc[data-wacc="what"] .fmbar{margin-top:10px}
/* 「正式成文」这一条：330px 的栏里，「开关+正式成文」和 13 字的说明挤在一行，
   说明被切成「按事实写，没填的留〔待」/「定〕」两行 —— 难看且难读。
   让说明独占一行，开关在上，读起来才是一句话。 */
.wacc[data-wacc="what"] .fmbar{row-gap:1px;padding:8px 11px}
.wacc[data-wacc="what"] .fmbar-tx{flex:1 1 100%;font-size:12px;line-height:1.45}

/* 空态 */
.empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;
  padding:44px 20px;text-align:center;color:var(--ink4)}
.empty b{font-size:13px;color:var(--ink2);font-weight:500}
.empty span{font-size:12px;max-width:22em;line-height:1.6}
.empty svg{opacity:.4;margin-bottom:2px}

/* 学生档案（一人一页） */
.stu-head{display:flex;align-items:center;gap:16px;padding:4px 2px 18px;flex-wrap:wrap}
.stu-av{width:62px;height:62px;border-radius:50%;flex:none;display:grid;place-items:center;
  font-size:22px;font-weight:600;color:#3D6A52;
  background:linear-gradient(145deg,#DCEBE1,#BFD9C9);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.8),0 8px 20px -14px rgba(61,106,82,.8)}
.stu-head h2{font-size:21px;font-weight:640;letter-spacing:-.03em;margin:0}
.stu-head .m{font-size:12px;color:var(--ink3);margin-top:5px;display:flex;gap:9px;flex-wrap:wrap}
.stu-head .m i{font-style:normal;color:var(--ink4)}
.stu-stat{display:flex;gap:26px;margin-left:auto;flex-wrap:wrap}
.stu-stat .s b{display:block;font-size:20px;font-weight:620;letter-spacing:-.035em;line-height:1.1;
  font-variant-numeric:tabular-nums}
.stu-stat .s span{display:block;font-size:12px;color:var(--ink4);margin-top:3px}
.tl{display:flex;flex-direction:column;position:relative;padding-left:18px;margin-top:4px}
.tl::before{content:"";position:absolute;left:4px;top:8px;bottom:12px;width:1px;background:var(--line)}
.tli{position:relative;padding:10px 4px 12px}
.tli::before{content:"";position:absolute;left:-18px;top:16px;width:7px;height:7px;border-radius:50%;
  background:#fff;box-shadow:0 0 0 1.5px rgba(0,113,227,.4)}
.tli.b::before{background:var(--blue);box-shadow:0 0 0 1.5px var(--blue)}
.tli .d{font-size:12px;color:var(--ink4);font-variant-numeric:tabular-nums}
.tli p{margin:4px 0 0;font-size:13px;line-height:1.68;letter-spacing:-.006em}
.tli .mt{display:flex;gap:6px;margin-top:6px;flex-wrap:wrap}

/* 材料类记录（写稿产出的观察记录/评语/总结）：整行可点，直接开全文 */
.tli.doci{cursor:pointer;border-radius:9px;padding-left:8px;padding-right:8px;
  transition:background .18s ease}
.tli.doci::before{left:-22px}
.tli.doci:hover{background:rgba(0,113,227,.055)}
.tli.doci:focus-visible{outline:2px solid var(--blue);outline-offset:2px}
.tli.doci .dt{font-size:13px;font-weight:600;margin:5px 0 0;letter-spacing:-.012em}
.tli.doci .dc{font-size:12px;line-height:1.66;color:var(--ink3);margin:3px 0 0}
.tli.doci .mt{align-items:center}
.tli.doci .lkx{font-size:12px;font-weight:550;color:var(--blue);margin-left:auto;white-space:nowrap}

/* 台账表格 */
.lg{width:100%;border-collapse:collapse;font-size:12px}
.lg th{font-size:12px;color:var(--ink4);font-weight:500;letter-spacing:.04em;
  text-align:left;padding:9px 10px;border-bottom:1px solid var(--line);white-space:nowrap}
.lg td{padding:11px 10px;border-bottom:1px solid rgba(0,0,0,.045);vertical-align:top;line-height:1.66}
.lg tr:last-child td{border-bottom:0}
.lg td.k{color:var(--ink2);white-space:nowrap;font-weight:500}
.lg .fill{color:var(--ink4)}

/* 弹层（居中卡片，区别于底部抽屉） */
.mask{position:fixed;inset:0;z-index:80;display:none;align-items:center;justify-content:center;
  padding:24px;background:rgba(20,20,22,.28);backdrop-filter:blur(6px);
  -webkit-backdrop-filter:blur(6px);opacity:0;transition:opacity .32s var(--ease)}
.mask.on{display:flex;opacity:1}
.mbox{width:100%;max-width:520px;max-height:86vh;overflow:auto;border-radius:20px;
  -webkit-overflow-scrolling:touch;overscroll-behavior:contain;
  background:rgba(255,255,255,.94);backdrop-filter:blur(28px) saturate(180%);
  -webkit-backdrop-filter:blur(28px) saturate(180%);
  border:1px solid rgba(255,255,255,.95);box-shadow:0 30px 70px -30px rgba(60,40,110,.4);
  padding:22px 24px 20px;transform:translateY(14px) scale(.985);
  transition:transform .4s var(--spring)}
.mask.on .mbox{transform:none}
.mbox.wide{max-width:660px}
.mbox h3{font-size:16px;font-weight:620;letter-spacing:-.02em;margin:0}
.mbox .mhint{font-size:12px;color:var(--ink3);margin:6px 0 0;line-height:1.6}
.mfoot{display:flex;align-items:center;gap:9px;margin-top:20px}
.mfoot .sp{margin-left:auto}

/* 轻提示 */
.toast{position:fixed;left:50%;bottom:28px;transform:translate(-50%,20px);z-index:120;
  padding:10px 18px;border-radius:980px;font-size:13px;color:#fff;background:rgba(29,29,31,.92);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  box-shadow:0 12px 30px -14px rgba(0,0,0,.6);opacity:0;pointer-events:none;
  transition:opacity .3s,transform .42s var(--spring)}
.toast.on{opacity:1;transform:translate(-50%,0);pointer-events:auto}

/* 设置页的开关行 */
.setrow{display:flex;align-items:center;gap:14px;padding:13px 2px;border-bottom:1px solid rgba(0,0,0,.045)}
.setrow:last-child{border-bottom:0}
.setrow .g{flex:1;min-width:0}
.setrow .g b{display:block;font-size:13px;font-weight:500}
.setrow .g span{display:block;font-size:12px;color:var(--ink3);margin-top:3px;line-height:1.55}

/* 响应式 */
/* 断点从 1180 收到 900：1180~901 之间仍是两列（左 330 + 右弹性）。
   在这个区间改成单列，卡片会宽到 940，内容全挤在左边、右边一片空 —— 更丑。 */
@media(max-width:900px){
  /* 单列：解除上面的视口锁定，回到整页滚动。
     手机上把两栏各锁进半屏，编辑区只剩两百多高，比原来更难用。 */
  /* 2026-11-09 可读性精修附带修：原来写 1fr，而 1fr 的隐式最小值是 auto，
     等于不允许列宽低于内容的 min-content（实测 497.67px），390 视口下整张写作卡
     被 body 的 overflow-x:hidden 切掉右侧 132px，且无法横向滚动回去。
     改成 minmax(0,1fr) 后列宽回到 342px，页内溢出 0，卡内无新增裁切。 */
  .wgrid{grid-template-columns:minmax(0,1fr);height:auto;min-height:0}
  /* 竖排而不是横排：横排时每张卡宽度跟着内容走，末行还常常只剩半张，
     底下一片空 —— 竖排宽度统一、高度也统一，看着才齐。 */
  .wside{position:static;flex-direction:column;align-items:stretch;
    max-height:none;overflow:visible;padding:0}
  .wside > .card{flex:0 0 auto;width:100%}
  /* 单列时稿纸回到正常流，不粘也不强撑一屏 */
  .paperbox{position:static;min-height:420px}
  .wgrid > .paperbox{height:auto;min-height:420px;overflow:visible}
  .wgrid .paperbar,.wgrid .polishbar{position:static;background:none;
    -webkit-backdrop-filter:none;backdrop-filter:none}
}
@media(max-width:860px){
  .f3{grid-template-columns:1fr 1fr}
  .stu-head .stu-stat{margin-left:0;width:100%;gap:20px}
}
@media(max-width:640px){
  .pg-head{padding:76px 0 14px}
  .pg-head h1{font-size:19px}
  .pg-head .hr{width:100%}
  .pg-head .hr .btn{flex:1}
  .f2,.f3{grid-template-columns:1fr}
  .paperbox{padding:20px 18px 16px;min-height:400px}
  .paperbox .ed{min-height:320px}
  .paperbox .ed-body{min-height:320px}
  .mask{padding:12px;align-items:flex-end}
  .mbox{max-width:none;border-radius:20px 20px 14px 14px;padding:20px 18px 16px}
  .stu-av{width:52px;height:52px;font-size:19px}
  .stu-head h2{font-size:18px}
  .lg th,.lg td{padding:8px 6px}
  .ed{min-height:300px}
}

/* ── 学生全览：卡片铺满整行时 16 列，窄屏回落 8 列 ── */
.kids.wide{grid-template-columns:repeat(16,1fr);gap:8px;margin-top:10px}
.kids.wide .kid{padding:12px 2px 11px}
@media(max-width:980px){ .kids.wide{grid-template-columns:repeat(8,1fr);gap:7px} }
@media(max-width:640px){ .kids.wide .kid{padding:9px 1px 8px} }

/* ── 选择片容器：可滚动时给个细滚动条和底部暗示 ── */
.picks{max-height:196px;padding-bottom:3px;scrollbar-width:thin;scrollbar-color:rgba(0,0,0,.16) transparent}
.picks::-webkit-scrollbar{width:6px}
.picks::-webkit-scrollbar-thumb{background:rgba(0,0,0,.14);border-radius:3px}
.picks::-webkit-scrollbar-track{background:transparent}

/* ── 待办行稍微收紧 ── */
.row{padding:10px 8px}
.row .g span{margin-top:1px}

/* ── 台账可编辑格：悬停和聚焦要有反馈，否则不知道能点 ── */
.lg td [contenteditable]{padding:4px 6px;margin:-4px -6px;border-radius:7px;
  transition:background .25s,box-shadow .25s;min-height:24px}
.lg td [contenteditable]:hover{background:rgba(0,113,227,.04)}
.lg td [contenteditable]:focus{background:#fff;box-shadow:0 0 0 2px rgba(0,113,227,.22);
  color:var(--ink)}
.lg td [contenteditable].fill{color:var(--ink4)}
.lg td [contenteditable]:focus.fill{color:var(--ink)}

/* ── 论文空态时别让导出按钮悬在半空 ── */
.paperbar:has(.wc:empty){margin-top:8px}
.picks.tall{max-height:268px}

/* 正文框默认按内容长高：flex:1 会让它被容器卡住，初稿被截断。
   但"空稿"这一种情况例外——那时候撑满整张纸，空白就成了一块可写的区域，
   而不是纸上一块死白。:placeholder-shown 正好只在没内容时命中。 */
.paperbox .ed{flex:0 0 auto}
@media screen and (min-width:1181px){
  .paperbox .ed:placeholder-shown{flex:1 1 auto;min-height:0}
}

/* ───────── 登录（云同步） ───────── */
.auth{position:fixed;inset:0;z-index:900;display:none;align-items:center;justify-content:center;
  padding:22px;background:rgba(251,251,253,.74);
  backdrop-filter:blur(28px) saturate(180%);-webkit-backdrop-filter:blur(28px) saturate(180%)}
.auth.on{display:flex;animation:authIn .45s var(--ease) both}
@keyframes authIn{from{opacity:0}to{opacity:1}}

.auth-card{width:100%;max-width:348px;padding:32px 28px 24px;border-radius:26px;text-align:center;
  background:linear-gradient(180deg,rgba(255,255,255,.94),rgba(255,255,255,.78));
  border:1px solid rgba(255,255,255,.92);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.95),
    0 26px 64px -30px rgba(20,20,30,.3),
    0 2px 8px rgba(20,20,30,.04);
  animation:authCard .55s var(--ease) both}
@keyframes authCard{from{opacity:0;transform:translateY(14px) scale(.985)}to{opacity:1;transform:none}}

.auth-mark{width:46px;height:46px;margin:0 auto 17px;border-radius:14px;display:grid;place-items:center;
  color:var(--blue);background:linear-gradient(180deg,rgba(0,113,227,.15),rgba(0,113,227,.06));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.9)}
.auth-mark svg{width:23px;height:23px}
.auth-card h1{font-size:19.5px;font-weight:640;letter-spacing:-.032em;margin:0;line-height:1.2;color:var(--ink)}
.auth-sub{margin:9px 0 0;font-size:13px;line-height:1.7;color:var(--ink3);letter-spacing:-.005em}

.auth-form{margin-top:15px;display:flex;flex-direction:column;gap:9px}
.auth-form[hidden]{display:none}

/* 登录方式切换 */
.af-tabs{margin:18px auto 0;display:flex;gap:4px;padding:4px;border-radius:11px;
  background:rgba(0,0,0,.05);width:max-content}
.af-tab{appearance:none;border:0;background:transparent;font:inherit;font-size:13px;font-weight:500;
  color:var(--ink3);padding:6px 16px;border-radius:8px;cursor:pointer;letter-spacing:-.005em;
  transition:all .18s}
.af-tab:hover{color:var(--ink)}
.af-tab.on{background:#fff;color:var(--ink);font-weight:560;
  box-shadow:0 1px 3px rgba(0,0,0,.09),0 0 0 .5px rgba(0,0,0,.04)}
.af-link{margin:4px 0 0;font-size:12px;line-height:1.6;color:var(--ink4);
  text-align:center;letter-spacing:-.005em}
.af-in{box-sizing:border-box;width:100%;height:46px;padding:0 15px;border-radius:13px;font:inherit;font-size:14.5px;
  color:var(--ink);background:rgba(255,255,255,.6);border:1px solid rgba(255,255,255,.85);outline:none;
  letter-spacing:.01em;
  transition:background .25s var(--ease),border-color .25s var(--ease),box-shadow .25s var(--ease)}
.af-in::placeholder{color:var(--ink4);letter-spacing:0}
.af-in:focus{background:rgba(255,255,255,.95);border-color:rgba(0,113,227,.4);box-shadow:0 0 0 4px rgba(0,113,227,.09)}

.af-row{position:relative}
.af-row .af-in{padding-right:128px}
/* 验证码按钮嵌在输入框里侧，宽度按文字自适应，不会被挤爆 */
.af-code{position:absolute;right:5px;top:50%;transform:translateY(-50%);
  height:34px;padding:0 13px;border-radius:9px;border:0;cursor:pointer;white-space:nowrap;
  font:inherit;font-size:12px;font-weight:560;letter-spacing:0;color:var(--blue);
  background:rgba(0,113,227,.1);
  transition:background .2s var(--ease),transform .18s var(--ease)}
.af-code:hover{background:rgba(0,113,227,.17)}
.af-code:active{transform:translateY(-50%) scale(.95)}
.af-code:disabled{color:var(--ink4);background:rgba(0,0,0,.05);cursor:default;transform:translateY(-50%)}

/* 未开通页的次要按钮 */
.af-ghost{flex:0 0 88px;height:46px;border-radius:13px;border:0;cursor:pointer;
  font:inherit;font-size:13px;font-weight:560;letter-spacing:-.01em;color:var(--ink3);
  background:rgba(0,0,0,.055);transition:background .2s var(--ease),transform .18s var(--ease)}
.af-ghost:hover{background:rgba(0,0,0,.085)}
.af-ghost:active{transform:scale(.96)}

.af-err{margin:0;min-height:15px;padding-left:3px;text-align:left;font-size:12px;
  color:#D70015;opacity:0;transition:opacity .2s var(--ease)}
.af-err.on{opacity:1}

.af-go{height:46px;border-radius:13px;border:0;cursor:pointer;margin-top:1px;
  font:inherit;font-size:14.5px;font-weight:590;letter-spacing:-.012em;color:#fff;background:var(--blue);
  box-shadow:0 9px 22px -11px rgba(0,113,227,.9);
  transition:filter .2s var(--ease),transform .18s var(--ease),background .2s}
.af-go:hover{filter:brightness(1.07)}
.af-go:active{transform:scale(.985)}
.af-go:disabled{background:rgba(0,0,0,.16);box-shadow:none;cursor:default;transform:none;filter:none}

.af-state{margin:1px 0 0;min-height:15px;font-size:12px;color:var(--blue);letter-spacing:-.005em}
.auth-foot{margin:17px 0 0;font-size:12px;line-height:1.75;color:var(--ink4);letter-spacing:-.003em}
body.locked{overflow:hidden}
/* 登录时把外壳藏掉，只留背景光斑，别让背后半截界面透出来 */
body.locked .side,body.locked .nav,body.locked .main{opacity:0;pointer-events:none}

/* 侧栏的同步状态 */
#syncTip{color:var(--ink4);transition:color .3s var(--ease)}
#syncTip[data-s="未同步"]{color:#C93400}

@media(max-width:640px){
  .auth{padding:16px}
  .auth-card{padding:28px 22px 22px;border-radius:24px;max-width:100%}
  .af-in{font-size:16px}          /* 小于 16px 时 iOS 会自动放大页面 */
  .af-code{font-size:13px;padding:0 12px}
}

/* 未开通面板：和登录卡互斥 */
.auth-card.deny{display:none}
.auth.denied #afLogin{display:none}
.auth.denied .auth-card.deny{display:block}
.auth-mark.warn{color:#C93400;background:linear-gradient(180deg,rgba(255,59,48,.13),rgba(255,59,48,.05))}
.auth-card .dn-t{font-size:18px;font-weight:640;letter-spacing:-.028em;margin:0;line-height:1.35;color:var(--ink)}
.dn-p:empty{display:none}
.dn-p{margin:8px 0 0;font-size:12px;color:var(--ink4);font-variant-numeric:tabular-nums}
.dn-h{margin-top:10px}
.dn-btns{display:flex;gap:8px;margin-top:22px}
.dn-btns .af-go{flex:1;margin-top:0}


/* ───────── 成员管理 ───────── */
.mlist{display:flex;flex-direction:column;margin:8px -8px 0}
.mrow{display:flex;align-items:center;gap:12px;padding:9px 8px;border-radius:12px;
  transition:background .25s var(--ease)}
.mrow:hover{background:rgba(0,0,0,.022)}
.mv{width:32px;height:32px;flex:none;border-radius:11px;display:grid;place-items:center;
  font-size:13px;font-weight:600;color:var(--blue);background:rgba(0,113,227,.1)}
.mg{flex:1;min-width:0}
.mg b{display:flex;align-items:center;gap:6px;flex-wrap:wrap;
  font-size:13px;font-weight:550;letter-spacing:-.012em;line-height:1.4}
.mg em{display:block;font-style:normal;font-size:12px;color:var(--ink4);
  margin-top:3px;font-variant-numeric:tabular-nums;letter-spacing:.01em}
.mtag{font-style:normal;font-size:12px;line-height:1;padding:3px 6px;border-radius:5px;
  font-weight:600;letter-spacing:0;color:var(--blue);background:rgba(0,113,227,.1);white-space:nowrap}
.mtag.self{color:var(--ink);background:rgba(0,0,0,.065)}
.mtag.offT{color:#C93400;background:rgba(255,59,48,.1)}
.mtag.wait{color:var(--ink4);background:rgba(0,0,0,.05)}
.ma{display:flex;gap:7px;flex:none}
.mrow.off .mv{background:rgba(0,0,0,.055);color:var(--ink4)}
.mrow.off .mg b{color:var(--ink3)}
.mload{padding:22px 10px;text-align:center;font-size:12px;color:var(--ink4)}

/* 弹窗里的勾选项 */
.chk{display:flex;align-items:center;gap:9px;margin-top:2px;font-size:13px;
  color:var(--ink3);cursor:pointer;letter-spacing:-.005em;line-height:1.5}
.chk input{width:16px;height:16px;flex:none;accent-color:var(--blue);cursor:pointer;margin:0}

@media(max-width:640px){
  .mrow{gap:10px;padding:9px 4px}
  .ma .btn{padding:0 6px;font-size:12px;min-width:0}
  .mg b{font-size:13px}
}

/* ───────── 使用情况（管理员看子账号） ───────── */
.usg-kpi{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:14px}
/* 这四张走和看板同一套 .kpi 外壳，但这一页是读数用的，卡收紧一档 */
.usg-kpi .kpi{padding:13px 15px;border-radius:14px}
.usg-kpi .kpi .kr{min-height:0;margin:5px 0 0}
.usg-kpi .kpi .v{font-size:22px;margin:0}
@media(max-width:640px){
  .usg-kpi{grid-template-columns:repeat(2,1fr)}
  .usg-kpi .kpi .v{font-size:20px}
}
.ukpi{background:rgba(255,255,255,.72);border:1px solid rgba(255,255,255,.92);border-radius:14px;
  padding:13px 15px;display:flex;flex-direction:column;gap:2px;min-width:0;
  -webkit-backdrop-filter:blur(14px) saturate(160%);backdrop-filter:blur(14px) saturate(160%);
  box-shadow:0 1px 2px rgba(0,0,0,.03),0 14px 32px -26px rgba(0,0,0,.5)}
.ukpi b{font-size:clamp(15px,2.1vw,19px);font-weight:620;letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ukpi span{font-size:12px;color:var(--ink3);letter-spacing:.02em}
.ukpi.live b{color:var(--ok-text)}
.ukpi.spend b{color:#B4651A}
/* 有值的指标给个色：在线绿、花费橙。改的是数值本身，后缀不动。 */
.kpi.live .v{color:var(--ok-text)}
.kpi.spend .v{color:#B4651A}

.usg-tools{display:flex;gap:9px;align-items:center;padding:2px 0 12px;flex-wrap:wrap}
.usg-find{flex:1 1 190px;min-width:120px}
/* 高度跟着旁边的自绘下拉走：桌面 32、手机 38，不然两个控件一高一矮很明显 */
.usg-find .inp{height:32px;width:100%;font-size:13px}
.usg-sel{width:128px;height:34px;font-size:13px;flex:none}
@media(max-width:640px){
  .usg-find .inp{height:38px}
  .usg-sel{height:38px}
}

/* 桌面：表格式 */
.utb{padding:0 18px 6px}
.utr{display:grid;
  grid-template-columns:minmax(0,1.6fr) 82px minmax(84px,.9fr) minmax(92px,1fr) 70px minmax(72px,.8fr);
  gap:10px;align-items:center;padding:11px 0;border-bottom:1px solid var(--line);font-size:12px}
.utr:last-child{border-bottom:0}
.utr.head{padding:9px 0 7px;border-bottom:1px solid var(--line)}
.utr:not(.head){transition:background .3s}
.utr:not(.head):hover{background:rgba(0,0,0,.018)}

.uc-th{border:0;background:transparent;padding:0;font:inherit;font-size:12px;color:var(--ink4);
  letter-spacing:.04em;cursor:pointer;display:inline-flex;align-items:center;gap:3px;
  white-space:nowrap;transition:color .25s;justify-self:start}
.uc-th i{font-style:normal;font-size:12px;color:var(--ink4);transition:opacity .25s}
.uc-th.r{justify-self:end}
.uc-th:hover,.uc-th.on{color:var(--ink2)}
.uc-th.on i{opacity:1}

.uc-name{display:flex;align-items:center;gap:6px;min-width:0}
.uc-name b{font-size:13px;font-weight:600;letter-spacing:-.008em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.uc-name em{font-style:normal;font-size:12px;color:var(--ink4);
  font-variant-numeric:tabular-nums;flex:none}
.uc-st{display:inline-flex;align-items:center;gap:5px;font-size:12px;
  color:var(--ink2);white-space:nowrap}
.udot{width:6px;height:6px;border-radius:50%;flex:none;background:var(--ink4)}
.udot.on{background:var(--ok);box-shadow:0 0 0 3px rgba(52,199,89,.15)}
.udot.away{background:#C4BED0}
.udot.never{background:var(--warn)}
.udot.off{background:#D5CEE0}
.uc-n{font-size:12px;color:var(--ink3);text-align:right;
  font-variant-numeric:tabular-nums;white-space:nowrap}
.uc-n.strong{color:var(--ink);font-weight:560}
.uc-t{font-size:12px;color:var(--ink3);text-align:right;white-space:nowrap;
  font-variant-numeric:tabular-nums}

.utag{font-style:normal;font-size:12px;padding:1px 5px;border-radius:5px;flex:none;
  background:rgba(0,0,0,.05);color:var(--ink3);letter-spacing:.01em}
.utag.adm{background:rgba(0,113,227,.1);color:#0060C0}
.utag.me{background:rgba(52,199,89,.13);color:#1F8A45}

/* 窄屏：卡片式 */
.ucards{display:none;padding:2px 18px 6px}
.ucard{padding:12px 0;border-bottom:1px solid var(--line)}
.ucard:last-child{border-bottom:0}
.uc-h{display:flex;align-items:center;gap:6px;margin-bottom:10px;min-width:0}
.uc-h b{font-size:13px;font-weight:620;letter-spacing:-.012em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.uc-badge{margin-left:auto;flex:none;display:inline-flex;align-items:center;gap:5px;
  font-size:12px;color:var(--ink2)}
.uc-g{display:grid;grid-template-columns:1fr 1fr;gap:9px 14px}
.uc-g>div{display:flex;flex-direction:column;gap:2px;min-width:0}
.uc-g span{font-size:12px;color:var(--ink4);letter-spacing:.02em}
.uc-g b{font-size:13px;font-weight:520;font-variant-numeric:tabular-nums;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.usg-sum{padding:10px 18px 6px;border-top:1px solid var(--line);
  font-size:12px;color:var(--ink4);font-variant-numeric:tabular-nums}
/* 手机上全局规则会把页头按钮拉成整行，这一页只有一个按钮，撑满很难看 */
.pg-head .hr .btn.usg-refresh{flex:0 0 auto;margin-left:auto}

@media(max-width:820px){
  .utb{display:none}
  .ucards{display:block}
  .usg-kpi{grid-template-columns:repeat(2,1fr);gap:9px}
}
@media(max-width:420px){
  .usg-sel{width:112px}
  .ukpi{padding:11px 12px}
  .uc-g{gap:8px 10px}
  .usg-tools{gap:7px}
}

/* 登录遮罩撤掉时，外壳淡入，不要硬闪 */
.side,.nav,.main{transition:opacity .45s var(--ease)}

/* ── 写稿页：类型分组、润色条 ── */
.chip-cap{font-size:12px;color:var(--ink4);letter-spacing:.05em;align-self:center;margin-right:2px}
.btn.xs{height:27px;font-size:12px;padding:0 11px;border-radius:8px}
.polishbar{display:flex;align-items:center;gap:7px;flex-wrap:wrap;
  padding:11px 0 0;margin-top:12px;border-top:1px solid rgba(0,0,0,.06)}
.polishbar .pb-cap{font-size:12px;color:var(--ink4);letter-spacing:.05em;margin-right:2px}
.paperbox .polishbar{margin-bottom:0}

/* ── 台账：复用条 ── */
.lgbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:12px}
.lgbar .sel{width:auto;min-width:130px;height:32px;font-size:13px;padding:0 30px 0 11px}
/* 自绘下拉接管 select 后，宽度规则要跟到外层包裹器上 */
.lgbar .uisel{width:auto;min-width:130px;max-width:200px;flex:0 1 auto}
.lgbar .uisel-btn{min-height:32px;height:32px;font-size:13px;padding:0 28px 0 11px}

/* ── 事件照片 ── */
.phRow{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.ph{position:relative;width:66px;height:66px;border-radius:10px;overflow:hidden;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.07)}
.ph img{width:100%;height:100%;object-fit:cover;display:block}
.ph button{position:absolute;top:2px;right:2px;width:17px;height:17px;border:0;border-radius:50%;
  background:rgba(0,0,0,.5);color:#fff;font-size:12px;line-height:1;cursor:pointer;display:grid;place-items:center}
.phAdd{width:66px;height:66px;border:1px dashed rgba(0,0,0,.18);border-radius:10px;background:transparent;
  color:var(--ink4);font-size:12px;cursor:pointer;transition:border-color .25s,color .25s,background .25s}
.phAdd:hover{border-color:rgba(0,113,227,.45);color:var(--blue);background:rgba(0,113,227,.04)}
.phStrip{display:flex;gap:6px;margin-top:8px;flex-wrap:wrap}
.phStrip img{width:54px;height:54px;object-fit:cover;border-radius:8px;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.06)}
.phStrip img.big{width:74px;height:74px;border-radius:10px}

/* ── 窄屏「全部功能」抽屉 ── */
.more-sheet{position:fixed;inset:0;z-index:110;display:none;align-items:flex-end;
  background:rgba(20,20,22,.28);backdrop-filter:blur(3px)}
.more-sheet.on{display:flex}
.ms-in{width:100%;background:rgba(251,251,253,.98);border-radius:20px 20px 0 0;
  padding:18px 18px calc(20px + env(safe-area-inset-bottom));animation:msUp .34s var(--ease) both;
  box-shadow:0 -12px 40px rgba(0,0,0,.16)}
@keyframes msUp{from{transform:translateY(24px);opacity:.6}to{transform:none;opacity:1}}
.ms-h{font-size:12px;color:var(--ink4);letter-spacing:.06em;margin:0 2px 12px}
.ms-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:9px}
.ms-a{display:flex;align-items:center;justify-content:center;height:47px;border-radius:13px;
  white-space:nowrap;padding:0 4px;box-sizing:border-box;
  font-size:14.5px;color:var(--ink);text-decoration:none;background:rgba(0,0,0,.038);
  letter-spacing:-.01em;transition:background .25s,transform .25s}
.ms-a:active{transform:scale(.97)}
.ms-a.on{background:var(--sel-grad);color:#fff;font-weight:560;
  box-shadow:0 6px 16px -8px rgba(46,160,180,.9)}

/* ── 全局搜索 ── */
.smask{display:none;z-index:115;align-items:flex-start;justify-content:center;padding-top:12vh}
.smask.on{display:flex}
.sbox{width:min(560px,92vw);max-height:72vh;overflow:auto;background:rgba(251,251,253,.99);
  border-radius:18px;padding:16px;box-shadow:0 24px 70px rgba(0,0,0,.24);
  animation:sIn .3s var(--ease) both}
@keyframes sIn{from{opacity:0;transform:translateY(-8px) scale(.99)}to{opacity:1;transform:none}}
.s-top{display:flex;gap:9px;align-items:center}
.s-in{flex:1;height:38px;font-size:14.5px}
.s-res{margin-top:10px}
.s-tip{font-size:12px;color:var(--ink4);margin:18px 4px;text-align:center}
.s-g{font-size:12px;color:var(--ink4);letter-spacing:.05em;margin:12px 4px 6px}
.s-r{display:block;padding:9px 10px;border-radius:11px;text-decoration:none;transition:background .22s}
.s-r:hover{background:rgba(0,0,0,.035)}
.s-r b{display:block;font-size:13px;font-weight:520;color:var(--ink);letter-spacing:-.01em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.s-r span{display:block;font-size:12px;color:var(--ink4);margin-top:2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ── 名单预览 ── */
.impbox{max-height:44vh;overflow:auto;margin-top:12px;border-radius:12px;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.06)}
.improw{display:flex;align-items:center;gap:10px;padding:8px 12px;font-size:13px;
  border-bottom:1px solid rgba(0,0,0,.045)}
.improw:last-child{border-bottom:0}
.improw>span{width:22px;color:var(--ink4);font-size:12px;font-variant-numeric:tabular-nums}
.improw b{flex:1;font-weight:520}
.improw em{font-style:normal;color:var(--ink4);font-size:12px;min-width:62px}

/* ── 撤销按钮（toast 内） ── */
.toast .undo{margin-left:12px;border:0;background:rgba(255,255,255,.2);color:#fff;
  font:inherit;font-size:12px;padding:3px 9px;border-radius:7px;cursor:pointer}
.toast .undo:hover{background:rgba(255,255,255,.32)}

/* 从自填长出输入框时，把原下拉压暗 */
.sel.selfill-off{color:var(--ink4);background-color:rgba(0,0,0,.02)}

/* ── 写稿：文种分组切换 ──
   6 栏底栅格：5 个分组时第一行 3 个（各占 2 栏）、第二行 2 个（各占 3 栏），
   两行都刚好铺满、没有空缺；格宽约 97px 足够放下 5 个汉字，永不断字。 */
/* 文种分组是 6 列均分网格：卡片一旦变宽（单列布局/大屏），
   每颗胶囊就被拉成两百多像素，像一排长条。限个最大宽度，让它保持"胶囊"的样子。 */
.chips.grp{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:6px;max-width:348px}
.chips.grp > .chip.gt{grid-column:span 2}
.chips.grp > .chip.gt:nth-child(4):nth-last-child(2),
.chips.grp > .chip.gt:nth-child(5):nth-last-child(1){grid-column:span 3}
.chip.gt{font-size:12px;padding:0 10px;min-height:32px;color:var(--ink2);background:rgba(0,0,0,.03);
  border-color:transparent;position:relative;display:inline-flex;align-items:center;justify-content:center;
  box-sizing:border-box;min-width:0;white-space:nowrap;letter-spacing:-.1px;overflow:hidden}
.chip.gt.on{background:var(--sel-grad);color:#fff;border-color:transparent;font-weight:520;
  box-shadow:0 2px 8px -5px rgba(46,160,180,.55)}
.chip.gt.hasdot::after{content:'';display:inline-block;width:4px;height:4px;border-radius:50%;
  background:var(--blue);margin-left:4px;vertical-align:2px;flex:none}
.chip.gt.on.hasdot::after{background:#fff}
@media (max-width:340px){
  .chip.gt{font-size:12px;padding:0 4px;letter-spacing:-.2px}
  .chips.grp{gap:5px}
}


/* ── 家长沟通台账 ── */
.crows{display:flex;flex-direction:column}
.crow{display:flex;gap:14px;padding:13px 4px;border-bottom:1px solid var(--line);cursor:pointer;
  transition:background .18s}
.crow:last-child{border-bottom:0}
.crow:hover{background:rgba(0,0,0,.018)}
.cd{flex:0 0 62px;font-size:12px;color:var(--ink2);line-height:1.5}
.cd em{display:block;font-style:normal;color:var(--ink4);font-size:12px}
.cmain{flex:1;min-width:0}
.ct{display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.ct b{font-size:13px;font-weight:560}
.cs{margin:3px 0 0;font-size:13px;color:var(--ink)}
.cc{margin:2px 0 0;font-size:12px;color:var(--ink3);line-height:1.6}
.cf{margin:4px 0 0;font-size:12px;color:var(--warn-text)}

/* ── 批量评语 ── */
/* 写给谁的工具条：搜名字 + 只选还没写的。人一多不靠这个就点不过来 */
.bsel{display:flex;gap:6px;align-items:center;margin-bottom:9px;flex-wrap:wrap}
.bsel .inp{flex:1;min-width:130px;height:32px;font-size:13px;padding:0 11px}
.pk .px{font-style:normal;font-size:12px;font-weight:600;margin-left:4px;letter-spacing:0;color:var(--ink4)}
.pk.on .px{color:var(--ink2)}
.bout{display:flex;flex-direction:column;gap:10px;margin-top:16px;max-height:46vh;overflow:auto}
.bout:empty{display:none}
.bitem{border:1px solid var(--line);border-radius:14px;padding:10px 12px;background:rgba(255,255,255,.55)}
.bh{display:flex;align-items:center;gap:8px;margin-bottom:6px}
.bh b{font-size:13px}
.bst{font-size:12px;color:var(--ink4);margin-left:auto}
.bst.run{color:var(--blue)}
.bst.ok{color:var(--ok-text)}
.bst.bad{color:var(--red-text)}
.bta{min-height:74px;font-size:13px;line-height:1.7}

/* ── 归档 ── */
.arstat{margin:14px 0 0;padding:10px 12px;border-radius:12px;background:rgba(0,0,0,.03);
  font-size:12px;color:var(--ink2)}
.arlist{margin-top:10px;max-height:30vh;overflow:auto}
.arli{display:flex;gap:8px;padding:6px 2px;font-size:12px;border-bottom:1px solid var(--line)}
.arli em{margin-left:auto;font-style:normal;color:var(--ink4);font-size:12px}

/* ── 键盘可达性：统一的焦点环 ── */
a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible,
textarea:focus-visible,[contenteditable]:focus-visible,
[role="button"]:focus-visible,[tabindex]:focus-visible{
  outline:2px solid var(--blue);outline-offset:2px;border-radius:6px}

/* ── 读屏专用：视觉隐藏，但仍进无障碍树 ── */
.sr-only{position:absolute!important;width:1px;height:1px;margin:-1px;padding:0;
  overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

/* 被脚本补成 role=button 的容器（.kid/.tli/.row…）跟着原生按钮一起表现为可点 */
[role="button"]{cursor:pointer}

/* ── 打印：只留内容，去掉外壳 ── */
@media print{
  @page{size:A4;margin:18mm 16mm}
  .side,.nav,.bg,.grain,.more-sheet,.mask,.toast,.side-foot,.foot .more,
  .pg-head .hr,.paperbar,.seg,.bout,.mfoot,button{display:none!important}
  body{background:#fff!important;color:#000!important}
  .main{margin:0!important;padding:0!important}
  .wrap{max-width:none!important;padding:0!important}
  .glass,.card{box-shadow:none!important;border:0!important;background:#fff!important;
    backdrop-filter:none!important;border-radius:0!important;padding:0!important}
  .pg-head{margin-bottom:10mm}
  .lg th,.lg td{border:1px solid #999!important;padding:6px!important;font-size:10pt!important}
  .tl,.rows{break-inside:auto}
  .tli,.crow,.row{break-inside:avoid}
  .paperbox{position:static!important;min-height:0!important}
  .paperbox .ed{flex:0 0 auto!important;height:auto!important;min-height:0!important}
  a{color:#000!important;text-decoration:none!important}
}

/* 手机上把点按区域撑到 40px 以上 */
@media(max-width:640px){
  .chip,.pk,.tag,.btn.sm{min-height:34px}
  .icon-btn{width:38px;height:38px}
  .crow{padding:14px 2px}
  /* 输入框 16px：字号小于 16 时 iOS 一聚焦就会把页面自动放大，很烦 */
  .inp,.sel,.ta{font-size:16px}
  /* 兜底：iOS 只看「被聚焦那个控件」自己的字号，跟 class 无关。
     写稿框 .ed（13.5px）和不带 class 的原生控件都靠这条兜住，
     否则点进去照样整页放大。用 !important 是为了压过元素上的内联字号。 */
  input,textarea,select{font-size:16px!important}
  /* iPhone 底部小白条不压住 toast 和内容 */
  .toast{bottom:calc(28px + env(safe-area-inset-bottom))}
  .wrap{padding-bottom:calc(56px + env(safe-area-inset-bottom))}
  .more-sheet,.mask{padding-bottom:env(safe-area-inset-bottom)}
  /* iOS 会把小字号的 select 自动放大再裁掉一半，统一放开高度 */
  .sel{height:auto!important;min-height:38px;padding-top:6px!important;padding-bottom:6px!important;font-size:16px!important}
  select.sel[style]{width:auto!important;max-width:100%}  /* 只约束原生 select；自绘按钮的宽度由包装层决定，不能被 !important 打窄 */
  /* 双列网格不允许被 date 输入框撑出屏幕 */
  .f2>*,.f3>*{min-width:0}
  input[type=date],input[type=time]{min-width:0;width:100%}
  /* 学期起止两个日期在手机上竖着排，避免第二个被挤出屏幕 */
  .f2.dates{grid-template-columns:1fr}
}

/* ───────── 逐字浮现（今日页标题第二句） ───────── */
.tt h1 em.wv{display:inline}
.tt h1 em.wv i{display:inline-block;font-style:normal;opacity:0;
  animation:charUp .62s var(--ease) both}
  /* 不加 will-change：欢迎语十几个字各提一层，iOS 上合成层爆了反而把动画拖死 */
/* 减动效：直接给终态，别留一堆透明字 */
@media(prefers-reduced-motion:reduce){
  .tt h1 em.wv i{opacity:1!important;transform:none!important;filter:none!important}
  .nav-in,.nav-handle{transition-duration:.01ms!important}
}

/* ───────── KPI 环形进度（学生覆盖那张） ───────── */
.kpi-ring .kr{flex:1 1 auto;display:flex;align-items:center;gap:13px;margin:9px 0 5px}
.mini-ring{position:relative;width:62px;height:62px;flex:none}
.mini-ring .dial{position:absolute;inset:0;border-radius:50%;
  background:conic-gradient(from -90deg,
    var(--blue) 0deg, var(--blue) var(--deg,0deg),
    rgba(0,0,0,.075) var(--deg,0deg), rgba(0,0,0,.075) 360deg);
  -webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 6.5px),#000 calc(100% - 6.5px));
  mask:radial-gradient(farthest-side,transparent calc(100% - 6.5px),#000 calc(100% - 6.5px))}
.mini-ring .rt{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;gap:1px}
.mini-ring .rt b{font-size:20px;font-weight:640;letter-spacing:-.04em;line-height:1;
  font-variant-numeric:tabular-nums}
.mini-ring .rt small{font-size:12px;color:var(--ink3);transform:translateY(1px)}
.kpi-ring .d{margin:0;font-size:12px;line-height:1.6;white-space:normal;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}

/* ───────── 卡片浮动（只桌面、只侧栏两张，手机不动免得晃） ───────── */
@media(min-width:1181px) and (prefers-reduced-motion:no-preference){
  .col-side .card.in{animation:cardFloat 9s ease-in-out 2.4s infinite}
  .col-side .card.in:nth-child(2){animation-duration:11.5s;animation-delay:3.2s}
}

/* 手机上副句仍整句换行（wv 的 span 不能顶掉这个规则） */
@media(max-width:640px){
  .tt h1 em.wv{display:block;margin-top:2px}
}

/* ───────── 设置页：职务多选 ───────── */
.lab-tip{font-size:12px;color:var(--ink4);font-weight:400;margin-left:7px;letter-spacing:0}
#stDuty{max-height:none;gap:7px;margin:1px -2px 0}
#stDuty .pk{padding:7px 13px;font-size:13px}
.pk-add{border-style:dashed;color:var(--ink3);background:transparent}
.pk-add:hover{border-color:rgba(0,113,227,.4);color:var(--blue)}

/* ───────── iOS 日期框：内在尺寸会把 1fr 栅格撑出屏幕 ───────── */
/* 1fr 的最小值是内容宽度，date 输入框在 iOS 上 min-content 很宽，必须压成 minmax(0,1fr) 并剥掉原生外观 */
@media(max-width:640px){
  .f2.dates{grid-template-columns:minmax(0,1fr)}
  input[type=date],input[type=time]{
    -webkit-appearance:none;appearance:none;
    display:block;width:100%;min-width:0;max-width:100%;text-align:left}
}

/* ───────── 写稿页：周次 / 场景可选 ───────── */
.fld > label{display:flex;align-items:center;gap:6px}
.sw.sm{width:30px;height:17px;border-radius:980px}
.sw.sm::after{top:2.5px;left:2.5px;width:12px;height:12px}
.sw.sm.on::after{transform:translateX(13px)}
.sw.sm:active::after{width:15px}
.sw.sm.on:active::after{transform:translateX(10px)}
.fld.fld-off > input,.fld.fld-off > select{display:none}

/* ───────── 自绘下拉：宽度与大屏下的行内排布 ─────────
   按钮继承了 .sel 的 class，会带上 width:100%；在 flex 行里那会独占一整行。
   这里统一改成按内容宽（grid 单元格仍会自己 stretch 填满，因为 width:auto 的 grid item 默认拉伸）。 */
/* 宽度由包装层决定：flex 行里按内容宽、栅格里自动填满，按钮始终 100% 跟随包装层 */
@media(max-width:640px){
  .uisel-btn.sel{min-height:38px}
  .btn.sm{min-height:38px}
}

/* ───────── 工具页（PDF 转 Word / Excel） ───────── */
.t-grid{display:grid;grid-template-columns:1fr;gap:13px}
/* 4 张卡正好 2×2，别用 auto-fit —— 1280 下会排成 3+1，孤零零一张很难看 */
@media(min-width:700px){.t-grid{grid-template-columns:repeat(2,1fr)}}
.t-card{padding:17px 19px 16px;display:flex;flex-direction:column}
.t-h{display:flex;align-items:center;gap:10px}
.t-ico{width:34px;height:34px;border-radius:11px;flex:none;display:grid;place-items:center;
  font-size:14.5px;font-weight:700;color:#fff;letter-spacing:.02em;
  box-shadow:0 6px 14px -9px rgba(35,38,52,.6),inset 0 1px 0 rgba(255,255,255,.35)}
.t-ico.t-word{background:linear-gradient(135deg,#5B7CE8,#3A55B8)}
.t-ico.t-excel{background:var(--sel-grad)}
.t-ico.t-image{background:linear-gradient(135deg,#E8A05B,#C9742F)}
.t-ico.t-photo{background:linear-gradient(135deg,#B07CE8,#7B4BC4)}
.t-tt{min-width:0}
.t-tt b{display:block;font-size:14.5px;font-weight:620;letter-spacing:-.01em}
.t-tt em{display:block;font-style:normal;font-size:12px;color:var(--ink3);margin-top:3px}
.t-drop{margin-top:12px;border:1.5px dashed rgba(60,45,100,.18);border-radius:13px;
  padding:18px 16px;text-align:center;cursor:pointer;
  /* 同一行的卡片高度会被拉齐，让拖放区吃掉多余高度，按钮才不会上下错位 */
  flex:1 1 auto;display:flex;flex-direction:column;align-items:center;justify-content:center;
  background:rgba(255,255,255,.42);
  transition:border-color .25s var(--ease),background .25s var(--ease),transform .3s var(--spring)}
.t-drop:hover,.t-drop:focus-visible{border-color:var(--sel-line);background:rgba(255,255,255,.7);
  transform:translateY(-1px)}
.t-drop.over{border-color:var(--sel-line);background:var(--sel-fill);transform:scale(1.01)}
.t-drop svg{width:22px;height:22px;color:var(--ink3);margin-bottom:7px;transition:color .25s,transform .3s}
.t-drop:hover svg{color:var(--blue-d);transform:translateY(-2px)}
.t-drop b{display:block;font-size:13px;font-weight:560;color:var(--ink)}
.t-drop span{display:block;font-size:12px;color:var(--ink4);margin-top:5px;line-height:1.6}
.t-file{display:flex;align-items:center;gap:8px;margin-top:13px;padding:10px 12px;border-radius:11px;
  background:rgba(255,255,255,.74);border:1px solid var(--line)}
.t-fname{flex:1;min-width:0;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.t-fsize{font-size:12px;color:var(--ink4);flex:none;font-variant-numeric:tabular-nums}
.t-x{border:0;background:rgba(0,0,0,.07);width:20px;height:20px;border-radius:50%;flex:none;
  font-size:12px;line-height:1;color:var(--ink2);cursor:pointer;transition:background .2s}
.t-x:hover{background:rgba(0,0,0,.14)}
.t-foot{display:flex;align-items:center;gap:9px;margin-top:13px;flex-wrap:wrap}
/* 卡片内的选项行：label 固定宽，下拉吃掉剩余宽度（包装层 flex:1，按钮 width:100% 跟随） */
.t-opt{display:flex;align-items:center;gap:9px;margin-top:11px}
.t-opt>label{font-size:12px;color:var(--ink3);flex:none;letter-spacing:.01em}
.t-opt .uisel{flex:1 1 auto;min-width:0}
/* 图片转 PDF 的多文件列表 */
.t-files{margin-top:12px;display:flex;flex-direction:column;gap:6px;max-height:172px;overflow-y:auto;
  overscroll-behavior:contain;padding-right:2px}
.t-files::-webkit-scrollbar{width:5px}
.t-files::-webkit-scrollbar-thumb{background:rgba(60,45,100,.18);border-radius:9px}
.t-fi{display:flex;align-items:center;gap:7px;padding:6px 9px;border-radius:11px;
  background:rgba(255,255,255,.72);border:1px solid var(--line);
  transition:background .18s var(--ease),border-color .18s var(--ease),box-shadow .18s var(--ease)}
.t-fi[draggable="true"]{cursor:grab}
.t-fi.dragging{opacity:.45;cursor:grabbing}
.t-fi.over-row{border-color:var(--sel-line);background:var(--sel-fill);
  box-shadow:0 3px 12px -6px var(--sel-ring)}
/* 六点拖动手柄 */
.t-grip{width:11px;height:18px;flex:none;cursor:grab;opacity:.42;
  background-image:radial-gradient(circle,currentColor 1px,transparent 1.2px);
  background-size:3.5px 4.5px;background-repeat:repeat;color:var(--ink3)}
.t-fi:hover .t-grip{opacity:.75}
/* PDF 文件的占位图标（图片行放缩略图，PDF 行放这个） */
.t-fi-ic{width:30px;height:30px;border-radius:7px;flex:none;display:grid;place-items:center;
  font-size:12px;font-weight:700;letter-spacing:.02em;color:#fff;background:linear-gradient(135deg,#5B7CE8,#3A55B8)}
/* 上下移 */
.t-mv{border:0;background:rgba(0,0,0,.055);width:19px;height:19px;border-radius:6px;flex:none;
  font-size:12px;line-height:1;color:var(--ink2);cursor:pointer;padding:0;
  transition:background .18s,opacity .18s}
.t-mv:hover{background:rgba(0,0,0,.12)}
.t-mv[disabled]{opacity:.25;cursor:default;background:rgba(0,0,0,.04)}
@media(max-width:400px){ .t-fi .t-fsize{display:none} }
.t-fi img{width:30px;height:30px;object-fit:cover;border-radius:7px;flex:none;background:rgba(0,0,0,.05)}
.t-fi-sum{background:var(--sel-fill);border-color:var(--sel-line)}
.t-fi-sum .t-fname{font-size:12px;color:var(--ink3)}
/* PDF 转图片：第一页缩略图 */
.t-thumb{margin-top:11px;display:flex;gap:8px;flex-wrap:wrap}
.t-thumb img{width:62px;border-radius:8px;border:1px solid rgba(60,45,100,.14);
  box-shadow:0 3px 10px -6px rgba(35,38,52,.4);background:#fff}
.t-msg{font-size:12px;color:var(--ink3);min-width:0;flex:1}
.t-msg.ok{color:#1B7A4B}
.t-msg.bad{color:#C7362C}
.t-card.busy .t-go{opacity:.55;pointer-events:none}
.t-note{margin-top:13px;padding:16px 19px}
.t-nh{font-size:12px;font-weight:620;color:var(--ink2)}
.t-ul{margin:9px 0 0;padding-left:17px;font-size:12px;color:var(--ink2);line-height:1.9}
.t-ul b{font-weight:560;color:var(--ink)}
.t-ver{font-size:12px;color:var(--ink4);padding:4px 10px;border-radius:980px;
  background:rgba(0,0,0,.045);font-variant-numeric:tabular-nums;letter-spacing:.02em}
@media(max-width:640px){
  .t-drop{padding:16px 12px}
}

/* 侧栏版本号（非正文档位，允许停在 11px 最小档） */
.side-ver{font-size:11px;color:var(--ink4);text-align:right;padding:5px 4px 0;
  font-variant-numeric:tabular-nums;letter-spacing:.02em}

/* 设置页：更新记录 */

/* 工具页标题旁的小版本号 */
.pg-head h1 .t-ver{margin-left:9px;vertical-align:3px;font-weight:500}

/* ───────── 学生页：批量管理（转出 / 删除） ─────────
   点格子＝勾人，勾中的格子给一圈绿边 + 右上角一个圆点，和「覆盖热力」的琥珀底不打架 */
/* 覆盖看板是 16 列网格，空状态必须横跨整行，否则会被挤成一列竖条 */
.kids>.empty{grid-column:1/-1;justify-self:stretch}
.bulkbar{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.bulkbar>b{font-size:13px;font-weight:600;color:var(--ink)}
.bulkbar>b span{color:var(--blue-d)}
.bulkbar .bfill{flex:1 1 auto;min-width:0}
.kid.pick{position:relative;cursor:pointer;padding-top:14px}
/* 勾选点挂在格子右上角的外沿：格子里只有两三个字，放里面一定压到名字 */
.kid.pick .kchk{position:absolute;top:-4px;right:-3px;width:13px;height:13px;border-radius:50%;
  border:1.5px solid rgba(0,0,0,.16);background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.13);transition:.2s}
.kid.pick:hover .kchk{border-color:var(--sel-line)}
.kid.on{background:var(--sel-fill)!important;box-shadow:inset 0 0 0 2px var(--sel-line)!important}
.kid.on .kchk{border-color:transparent;background:var(--sel-grad);box-shadow:0 2px 6px -1px var(--sel-ring)}
.kid.on .kchk::after{content:'';position:absolute;left:4px;top:2.4px;width:3px;height:5.5px;
  border:solid #fff;border-width:0 1.5px 1.5px 0;transform:rotate(42deg)}

/* 材料库里标示"这份写的是谁" */
.kbind{font-style:normal;font-size:12px;line-height:1.5;color:var(--ink3);background:rgba(0,0,0,.045);
  border-radius:5px;padding:1px 5px;margin-left:6px;white-space:nowrap;vertical-align:1px}

/* ───────── 材料库数字页码条（替代「加载更多」） ─────────
   一行发丝线风格：左边「第 X / Y 页 · 共 Z 份」，右边页码按钮。
   页码按钮沿用 .btn.pale.sm 的骨架，这里只做三件事：
   收紧内边距（页码多时不撑爆一行）、当前页用实线描边高亮、
   省略号占位与文字对齐。不加重底色、不套卡片。 */
.pg-bar{display:flex;align-items:center;justify-content:space-between;gap:12px;
  flex-wrap:wrap;padding:12px 2px 4px}
.pg-info{font-size:12px;color:var(--ink4);font-variant-numeric:tabular-nums}
.pg-btns{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.pg-btns .btn.sm{padding:0 11px;min-width:33px;font-variant-numeric:tabular-nums}
.pg-btns .btn.sm.pg-nav{padding:0 13px}
.pg-btns .btn.on{background:#fff;color:var(--ink);font-weight:600;
  border:1px solid var(--line);box-shadow:none}
.pg-gap{font-size:12px;color:var(--ink4);padding:0 2px;user-select:none}
/* 窄屏：说明文字独占一行，按钮行收紧内边距，尽量整行放下不孤行 */
@media (max-width:640px){
  .pg-bar{gap:8px}
  .pg-info{flex-basis:100%}
  .pg-btns{gap:4px}
  .pg-btns .btn.sm{padding:0 7px;min-width:27px}
  .pg-btns .btn.sm.pg-nav{padding:0 9px}
}

/* ───────── 详情页「← 返回」 ─────────
   一个孩子 / 一份材料的详情没有侧栏入口，进来以后只能靠浏览器后退键；
   标题上面给一颗小按钮，明确写「返回 小二」，比「上一页」更敢点 */
.pg-head .hl .bak{display:inline-flex;align-items:center;gap:4px;appearance:none;border:0;
  background:transparent;color:var(--ink3);font:inherit;font-size:12px;font-weight:500;
  padding:0 6px 0 0;margin:0 0 7px -2px;cursor:pointer;border-radius:6px;line-height:1.4}
.pg-head .hl .bak span{max-width:15em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pg-head .hl .bak:hover{color:var(--blue)}
.pg-head .hl .bak svg{opacity:.75;flex:0 0 auto}
.pg-head .hl .bak:focus-visible{outline:2px solid var(--blue);outline-offset:2px}

/* ───────── 档案附件 ───────── */
.frow .fx{flex:0 0 auto;width:34px;height:34px;border-radius:8px;display:flex;align-items:center;
  justify-content:center;font-size:12px;font-weight:700;letter-spacing:.02em;color:var(--ink3);
  background:rgba(0,0,0,.05);box-shadow:inset 0 0 0 1px rgba(0,0,0,.05);text-transform:uppercase}
.frow .fr{display:flex;gap:6px;flex:0 0 auto}
@media (max-width:560px){
  .frow{flex-wrap:wrap}
  .frow .g{flex:1 1 100%;order:2;margin-top:6px}
  .frow .fr{order:3;width:100%;justify-content:flex-end}
}

/* ───────── 导出弹层 ───────── */
.segs{display:flex;gap:6px;flex-wrap:wrap}
.segs button{appearance:none;border:0;font:inherit;font-size:12px;height:31px;padding:0 13px;
  border-radius:9px;background:rgba(0,0,0,.045);color:var(--ink2);cursor:pointer;transition:.16s;
  white-space:nowrap}
.segs button:hover{background:rgba(0,0,0,.075)}
.segs button.on{background:rgba(0,113,227,.1);color:var(--blue);font-weight:600;
  box-shadow:inset 0 0 0 1px rgba(0,113,227,.3)}
.segs button[disabled]{opacity:.4;pointer-events:none}
.expf{margin:14px 0 0;padding:12px 14px;border-radius:11px;background:rgba(0,113,227,.045);
  box-shadow:inset 0 0 0 1px rgba(0,113,227,.1)}
.expf b{display:block;font-size:12px;font-weight:600;color:var(--ink2);margin-bottom:6px}
.expf span{display:block;font-size:12px;line-height:1.65;color:var(--ink3);padding-left:10px;position:relative}
.expf span::before{content:'·';position:absolute;left:1px;color:var(--ink4)}
.sebar{display:flex;gap:7px;align-items:center;margin-bottom:8px}
.sebar .inp{flex:1 1 auto;height:32px;font-size:13px}
.sebox{max-height:230px;overflow:auto}
.spick{cursor:pointer}
.spick>span{width:22px;font-size:12px;color:var(--blue);font-weight:700}
.spick.on{background:rgba(0,113,227,.05)}
.spick:hover{background:rgba(0,0,0,.035)}
.sefoot{flex:1 1 auto;font-size:12px;color:var(--ink3);align-self:center}
@media (max-width:560px){
  .segs button{height:29px;padding:0 10px;font-size:12px}
  .sebox{max-height:38vh}
}

/* 更多抽屉底部的版本号：手机上核对"是不是拿到新版"用 */
.ms-ver{text-align:center;font-size:12px;color:var(--ink4);padding:10px 0 2px;
  font-variant-numeric:tabular-nums;letter-spacing:.02em}

/* 动效自检的探针动画：只用来测「系统有没有把 CSS 动画关掉」 */
@keyframes __probe{from{opacity:1}to{opacity:.9}}

/* 自检卡片里的心跳方块：纯 rAF 驱动，用来判断"这台机器能不能看见动" */
.mpulse{width:14px;height:14px;border-radius:50%;flex:0 0 auto;
  background:var(--sel-grad);box-shadow:0 0 0 4px var(--brand-100)}

/* ───────── 照片归档（人脸建档） ───────── */
.fkpi{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}
.fkpi .s{display:flex;flex-direction:column;gap:3px;padding:13px 15px;border-radius:12px;
  background:rgba(0,0,0,.028);box-shadow:inset 0 0 0 1px rgba(0,0,0,.045)}
.fkpi .s b{font-size:22px;font-weight:640;letter-spacing:-.03em;font-variant-numeric:tabular-nums}
.fkpi .s span{font-size:12px;color:var(--ink3)}
.fkpi .s.warn b{color:#D98324}
.fnote{margin:2px 0 12px;font-size:12px;line-height:1.7;color:var(--ink3);
  padding:9px 12px;border-radius:10px;background:rgba(217,131,36,.07);
  box-shadow:inset 0 0 0 1px rgba(217,131,36,.16)}
.fgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(232px,1fr));gap:12px}
.fcard{display:flex;flex-direction:column;border-radius:14px;overflow:hidden;
  background:rgba(255,255,255,.6);box-shadow:inset 0 0 0 1px rgba(0,0,0,.06)}
.fimg{position:relative;width:100%;aspect-ratio:4/3;background:#EDE9F2 center/cover no-repeat;
  background-color:rgba(0,0,0,.05)}
.fimg.miss::after{content:'图片不在这台设备上';position:absolute;inset:0;display:flex;
  align-items:center;justify-content:center;font-size:12px;color:var(--ink4)}
.fbox{position:absolute;border:2px solid var(--brand-500);border-radius:6px;
  box-shadow:0 0 0 9999px rgba(0,0,0,.12)}
.fpend{position:absolute;top:7px;right:7px;min-width:20px;height:20px;border-radius:10px;
  background:#D98324;color:#fff;font-size:12px;font-weight:700;font-style:normal;
  display:flex;align-items:center;justify-content:center;padding:0 5px}
.fbody{display:flex;flex-direction:column;gap:7px;padding:11px 12px 12px}
.fbody b{font-size:12px;color:var(--ink2)}
.fwhy{font-size:12px;line-height:1.55;color:#B4701F}
.fquick{display:flex;flex-wrap:wrap;gap:5px}
.fpick .uisel,.fpick .sel{width:100%}
.fbtns{display:flex;gap:6px}
.fbtns .btn{flex:1}
.ftiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(148px,1fr));gap:10px}
.ftile{cursor:pointer;border-radius:12px;overflow:hidden;background:rgba(255,255,255,.55);
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.055);transition:transform .2s,box-shadow .2s}
.ftile:hover{transform:translateY(-2px);box-shadow:0 10px 24px -16px rgba(35,38,52,.5),inset 0 0 0 1px rgba(0,0,0,.06)}
.ftile .fimg{aspect-ratio:1/1}
.ftile-b{display:flex;flex-direction:column;gap:2px;padding:7px 9px 9px}
.ftile-b b{font-size:12px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ftile-b span{font-size:12px;color:var(--ink4)}
/* 学生时间线里的照片条目 */
.tli.pho{cursor:pointer}
.tli .tph{width:100%;max-width:320px;aspect-ratio:4/3;border-radius:10px;margin:6px 0 4px;
  background:#EDE9F2 center/cover no-repeat;background-color:rgba(0,0,0,.05)}
@media (max-width:640px){
  .fkpi{grid-template-columns:repeat(2,1fr)}
  .fgrid{grid-template-columns:1fr}
}

/* ───────── KPI 交互规范（v20261027am）─────────
   三张信息卡（本周事件 / 材料完成 / 待办清掉）是固定块：
   不位移、不倾斜、不发光、不跟手，滚动时也只是跟着页面走，自身不做任何动。
   唯一可交互的是「学生覆盖」：hover 上浮 + 跟手光斑 + 按压倾斜 + 点击涟漪。 */
/* 早先这三张卡是「固定信息块」，所以用 !important 锁死了过渡。
   现在它们各自能跳到事件池 / 材料库 / 待办（.ukpi.is-go），就按可交互处理：
   旧锁已撤，动效交给 motion.css 的 .fx-float / .fx-spec。 */
.ukpi.is-go{cursor:pointer}
.kpi-ring{cursor:pointer}
.kpi-ring .selglow{position:absolute;inset:0;border-radius:inherit;pointer-events:none;opacity:0;
  box-shadow:0 0 0 1.5px rgba(0,122,255,.45),0 0 30px rgba(0,122,255,.35),
             inset 0 0 22px rgba(0,122,255,.12);transition:none}

/* ───────── 学生头像 ─────────
   圆框一律 1:1 + background cover 居中裁，任何尺寸都不会被拉扁。
   姓名摆放：头像在上/在左，名字紧跟其后并允许收缩（min-width:0），
   过长单行省略，不换行、不挤压、不覆盖头像。 */
.stu-av.has,.kav.has{background-size:cover;background-position:center;background-repeat:no-repeat}
.stu-head .stu-av{background-color:rgba(0,113,227,.08);color:var(--blue);font-weight:600}
.stu-head .avbtn{cursor:pointer;position:relative;transition:transform .25s var(--ease),box-shadow .25s var(--ease)}
.stu-head .avbtn:hover{transform:scale(1.04);box-shadow:0 0 0 3px rgba(0,113,227,.16)}
.stu-head .avbtn::after{content:'换';position:absolute;right:-2px;bottom:-2px;width:20px;height:20px;
  border-radius:50%;background:var(--blue);color:#fff;font-size:12px;line-height:20px;text-align:center;
  opacity:0;transition:opacity .2s;box-shadow:0 2px 6px rgba(0,113,227,.45)}
.stu-head .avbtn:hover::after{opacity:1}
/* 信息卡里的名字块：必须能缩，否则长名字会把右侧统计挤出去 */
.stu-nm{min-width:0;flex:1 1 auto}
.stu-nm h2{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* 列表格（覆盖看板）里的迷你头像 */
.kid .kav{width:22px;height:22px;border-radius:50%;flex:none;display:grid;place-items:center;
  font-size:12px;font-weight:600;color:var(--blue);background:rgba(0,113,227,.09);
  box-shadow:inset 0 0 0 1px rgba(0,113,227,.14);margin-bottom:1px}
.kid b{display:block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  text-align:center;padding:0 1px}

/* 设置头像弹层 */
.avwrap{display:flex;justify-content:center;margin:6px 0 14px}
.av-prev{width:168px;height:168px;border-radius:50%;background:#EDE9F2 center/cover no-repeat;
  display:grid;place-items:center;font-size:54px;font-weight:600;color:var(--blue);
  box-shadow:0 0 0 1px rgba(0,0,0,.06),0 18px 40px -24px rgba(35,38,52,.6),inset 0 0 0 6px rgba(255,255,255,.65)}
.avz{display:flex;align-items:center;gap:10px;font-size:12px;color:var(--ink3)}
.avz label{flex:none}
.avz input[type=range]{flex:1 1 auto;accent-color:var(--blue)}
.avtip{font-size:12px;color:var(--ink4)}
.avgrid{display:grid;grid-template-columns:repeat(6,1fr);gap:7px;margin-top:10px}
.avgrid i{aspect-ratio:1/1;border-radius:11px;cursor:pointer;background:#EDE9F2 center/cover no-repeat;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.06);transition:transform .18s var(--ease),box-shadow .18s}
.avgrid i:hover{transform:scale(1.05);box-shadow:0 0 0 2px rgba(0,113,227,.5)}
@media (max-width:640px){
  .av-prev{width:132px;height:132px;font-size:44px}
  .avgrid{grid-template-columns:repeat(4,1fr)}
  .kid .kav{width:20px;height:20px;font-size:12px}
  .stu-nm h2{font-size:18px}
}

/* 头像图贴上来以后把姓氏首字藏掉；取不到图就留着首字，不留空圆 */
.stu-av.loaded,.kav.loaded{color:transparent!important}
.stu-av.noload,.kav.noload{background-image:none!important}

/* 照片卡片右上角的删除 */
.ftile .fimg{position:relative}
/* 删除键：做大到 28px 并加一圈白边，手指容易点中；触屏上常显 */
.fdel{position:absolute;top:5px;left:5px;width:26px;height:26px;border-radius:50%;
  background:rgba(20,16,30,.6);color:#fff;font-style:normal;font-size:16px;line-height:26px;
  text-align:center;cursor:pointer;opacity:.9;transition:opacity .18s,background .18s;
  box-shadow:0 0 0 1.5px rgba(255,255,255,.75);z-index:3;
  -webkit-tap-highlight-color:transparent;
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.ftile:hover .fdel{opacity:1}
/* 默认就一直显示：手机上没有 hover，藏起来就等于没有删除入口 */
.fdel:active{background:rgba(214,61,61,.95)}
.fdel:hover{background:rgba(214,61,61,.92)}
@media (hover:none){
  .fdel{opacity:1;width:28px;height:28px;line-height:28px;font-size:16px}
}
/* 未接识别引擎时的醒目提示条 */
.facewarn{display:flex;gap:9px;align-items:flex-start;margin:0 0 12px;padding:11px 13px;border-radius:12px;
  background:rgba(217,131,36,.1);box-shadow:inset 0 0 0 1px rgba(217,131,36,.28);
  font-size:12px;line-height:1.65;color:#9A5B10}
.facewarn b{font-weight:700}

/* 照片批量删除 */
.fbar{display:flex;align-items:center;gap:8px;margin:8px 0 2px;padding:7px 10px;border-radius:10px;
  background:rgba(214,61,61,.06);box-shadow:inset 0 0 0 1px rgba(214,61,61,.18)}
.fbar span{font-size:12px;color:var(--ink2);margin-right:auto}
.ftile.pick{cursor:pointer}

/* 列表行删除键（事件池 / 沟通记录行右上角）：桌面 hover 显，触屏半显常在 */
.ev,.crow{position:relative}
.rowdel{position:absolute;top:7px;right:8px;width:24px;height:24px;border-radius:50%;
  color:var(--ink4);font-style:normal;font-size:15px;line-height:24px;text-align:center;
  cursor:pointer;opacity:0;z-index:2;transition:opacity .15s,background .15s;
  -webkit-tap-highlight-color:transparent;pointer-events:auto}
.ev:hover .rowdel,.crow:hover .rowdel{opacity:.85}
.rowdel:hover{background:rgba(214,61,61,.12);color:#d63d3d}
@media (hover:none){
  .rowdel{opacity:.5}
}

/* 材料库批量模式：行左边画勾选圈（不塞子元素，五列 grid 不动） */
.tr.pick{position:relative;cursor:pointer;padding-left:32px}
.tr.pick::before{content:'';position:absolute;left:9px;top:50%;transform:translateY(-50%);
  width:15px;height:15px;border-radius:50%;border:1.5px solid var(--ink4);
  transition:border-color .15s,background .15s}
.tr.pick:hover::before{border-color:var(--sel-line,var(--ink2))}
.tr.pick.on::before{border-color:transparent;background:var(--sel-grad,var(--blue));
  box-shadow:0 1px 4px -1px var(--sel-ring,rgba(58,81,153,.5))}
.tr.pick.on::after{content:'';position:absolute;left:13.5px;top:50%;transform:translateY(-58%) rotate(45deg);
  width:3px;height:6.5px;border:solid #fff;border-width:0 1.5px 1.5px 0}
.tr.pick.on{background:rgba(58,81,153,.05)}
.tr.head.pick{padding-left:0}
.ftile.sel{box-shadow:0 0 0 2px var(--blue),0 10px 24px -16px rgba(0,113,227,.6)!important}
.fsel{position:absolute;top:7px;left:7px;width:18px;height:18px;border-radius:50%;
  background:#fff;border:1.5px solid rgba(0,0,0,.22);display:block;z-index:2}
.ftile.sel .fsel{background:var(--blue);border-color:var(--blue)}
.ftile.sel .fsel::after{content:'';position:absolute;left:5px;top:2px;width:4px;height:8px;
  border:solid #fff;border-width:0 1.6px 1.6px 0;transform:rotate(42deg)}

/* 头像用 img 渲染：同步出图，不依赖异步贴背景 */
.stu-av,.kav{position:relative;overflow:hidden}
.avimg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center;
  border-radius:50%;display:block}
.stu-av.loaded,.kav.loaded{color:transparent!important}

/* 入库结果清单：每个失败的孩子 + 具体原因 */
.flist{display:flex;flex-direction:column;gap:6px;margin:4px 0 2px}
.frow{display:flex;gap:10px;align-items:flex-start;padding:9px 11px;border-radius:10px;
  background:rgba(217,131,36,.07);box-shadow:inset 0 0 0 1px rgba(217,131,36,.16)}
.frow b{flex:0 0 auto;font-size:12px;font-weight:650;color:var(--ink)}
.frow span{flex:1 1 auto;font-size:12px;line-height:1.6;color:#9A5B10}
#libInfo b{color:var(--ink);font-weight:650}

/* 人脸引擎共享状态行 */
.fxshare{display:flex;align-items:center;gap:10px;margin:2px 0 10px;padding:10px 12px;border-radius:11px;
  background:var(--sel-fill);box-shadow:inset 0 0 0 1px var(--sel-fill)}
.fxshare .g{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:2px}
.fxshare .g b{font-size:12px;font-weight:650;color:var(--ink)}
.fxshare .g span{font-size:12px;color:var(--ink3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* 成员页的四颗授权小片：一行放不下就自动换行，不要挤成一坨 */
.mperm{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}

/* ───────── 照片归属：已归档卡片 + 撤销条 ───────── */
.fcard.done .fimg{box-shadow:inset 0 0 0 2px var(--sel-line)}
.fok{position:absolute;right:7px;bottom:7px;width:20px;height:20px;border-radius:50%;
  background:var(--brand-500);color:#fff;font-size:12px;font-style:normal;line-height:20px;text-align:center;
  box-shadow:0 2px 8px var(--sel-line)}
.fwhy.ok{color:#2E9E6B}
.fcard.done .fbody b{font-size:13px;font-weight:650;color:var(--ink)}
/* 撤销条：改完归属后一直挂着，点一下还原 */
.fundobar{display:flex;align-items:center;gap:8px;margin:0 0 10px;padding:9px 12px;border-radius:11px;
  background:rgba(0,113,227,.07);box-shadow:inset 0 0 0 1px rgba(0,113,227,.18);
  font-size:12px;color:var(--ink2)}
.fundobar span{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fundobar b{font-weight:650;color:var(--ink)}

/* ───────── 归属体检 / 异常徽标 / 变更记录 ───────── */
.faudit{display:flex;align-items:center;gap:10px;margin:0 0 12px;padding:10px 13px;border-radius:12px;
  background:rgba(217,131,36,.08);box-shadow:inset 0 0 0 1px rgba(217,131,36,.22)}
.faudit.bad{background:rgba(214,61,61,.07);box-shadow:inset 0 0 0 1px rgba(214,61,61,.22)}
.faudit .g{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:2px}
.faudit .g b{font-size:13px;font-weight:650;color:var(--ink)}
.faudit .g span{font-size:12px;line-height:1.5;color:var(--ink3)}
.fbadge{position:absolute;right:5px;top:5px;width:20px;height:20px;border-radius:50%;
  color:#fff;font-size:12px;font-style:normal;font-weight:700;line-height:20px;text-align:center;z-index:4;
  box-shadow:0 0 0 1.5px rgba(255,255,255,.85)}
.fbadge.amber{background:#EF9F27}
.fbadge.red{background:#E24B4A}
.ftile-b span{color:var(--ink4)}
.floglist{max-height:52vh;overflow:auto;display:flex;flex-direction:column;gap:6px}
.floglist .frow{background:rgba(0,0,0,.03);box-shadow:inset 0 0 0 1px rgba(0,0,0,.05)}
.floglist .frow b{font-size:12px;color:var(--ink3);font-variant-numeric:tabular-nums}
.floglist .frow span{font-size:12px;color:var(--ink2)}
#opSel{font-size:13px;padding:6px 8px}
#opSel option{padding:4px 6px}
#opQ{font-size:13px}

/* ═══════════════════════════════════════════════════════════════════
   悬停交互层 v2 · Apple 质感
   ───────────────────────────────────────────────────────────────────
   设计规则（改之前先看这三条）：

   1) 触发条件
      · 悬停反馈只给「点下去真会有反应」的元素。纯信息块（看板上那三张 .ukpi
        统计卡、.frow 失败清单行）保持静止 —— 会动就暗示可点，是误导。
      · 同类名的元素未必同类：.setrow 有的可点有的只是说明行，所以
        列表行一律用 [data-act] 门控，不再用类名一刀切。

   2) 状态叠加（优先级从高到低）
      :active  >  :focus-visible  >  :hover  >  .on / .sel  >  默认
      三层位移/缩放拆成独立变量叠加，互不覆盖：
        transform: translate3d(var(--mgx),var(--mgy),0)   ← 磁吸（JS 写）
                   translateY(var(--lift))                 ← 悬停抬升（CSS）
                   scale(var(--press))                     ← 按压（CSS）
      以前磁吸直接写内联 transform，把 hover 抬升和 active 压缩全压死了。

   3) 参数统一（全站只有这一套）
      悬停进入 .2s / 抬升 .28s / 按下 .14s，缓动 --e-out；
      回弹用 --e-press。位移只有 1px / 2px / 3px 三档，缩放只有
      1.06（图标）与 .965（按压）两档。阴影只有 2 级。
   ═══════════════════════════════════════════════════════════════════ */

:root{
  /* 时长：三档，够用且不啰嗦 */
  --h-fast:.14s;          /* 按下 / 松开 */
  --h-base:.2s;           /* 颜色、底色、描边、透明度 */
  --h-lift:.28s;          /* 位移与阴影 */
  /* 缓动：进入用 expo-out（起步快、收尾软，苹果的手感），回弹单列一条 */
  --e-out:cubic-bezier(.22,1,.36,1);
  --e-press:cubic-bezier(.34,1.32,.64,1);
  /* 位移三档 */
  --lift-1:-1px;
  --lift-2:-2px;
  --lift-3:-3px;
  /* 缩放两档 */
  --zoom:1.06;
  --press-s:.965;
  /* 阴影两级 + 顶部高光（玻璃质感的关键，一律用 inset 1px 白线） */
  --sh-1:0 6px 16px -10px rgba(35,38,52,.5);
  --sh-2:0 1px 1px rgba(0,0,0,.04),0 22px 44px -26px rgba(35,38,52,.5);
  --hi:inset 0 1px 0 rgba(255,255,255,.9);
}

/* ───────── 一、按钮族：抬 1px + 顶部高光 + 阴影加深 ───────── */
.btn,.af-go,.af-ghost,.af-code,.side-new,.todo-add,.pk,.pk-add,.chip{
  transition:transform var(--h-base) var(--e-out),
             box-shadow var(--h-lift) var(--e-out),
             background-color var(--h-base) var(--e-out),
             border-color var(--h-base) var(--e-out),
             color var(--h-base) var(--e-out)}
/* 磁吸 + 抬升 + 按压，三层合成一条 transform（变量互不覆盖） */
.btn{--mgx:0px;--mgy:0px;--lift:0px;
  transform:translate3d(var(--mgx),var(--mgy),0) translateY(var(--lift)) scale(1)}
@media (hover:hover){
  .btn:hover{--lift:var(--lift-1);box-shadow:var(--sh-1),var(--hi)}
  .btn.pri:hover{box-shadow:0 10px 24px -12px rgba(0,0,0,.62),var(--hi)}
  .btn.pale:hover{box-shadow:var(--sh-1)}
  .btn.danger:hover{box-shadow:0 6px 16px -10px rgba(214,61,61,.55)}
}
/* 按下：抬升归零、压缩到 .965。这里把 transform 整条重写一遍，
   是因为 ui.css 里有一条 .btn:active{transform:scale(.965)} 同权重，
   不重写就会把磁吸偏移一起丢掉，按下瞬间按钮会「跳」回原位。 */
.btn:active,.btn.btn:active{transform:translate3d(var(--mgx),var(--mgy),0)
  translateY(0) scale(var(--press-s))}

/* 图标按钮：微放大 + 底片 */
.icon-btn{transition:transform var(--h-base) var(--e-press),
  box-shadow var(--h-lift) var(--e-out),
  background-color var(--h-base) var(--e-out),color var(--h-base) var(--e-out)}
@media (hover:hover){
  .icon-btn:hover{transform:scale(var(--zoom));background:rgba(0,0,0,.06);
    box-shadow:var(--sh-1),var(--hi)}
}
.icon-btn:active{transform:scale(.9)}

/* 侧栏主按钮 / 顶部加号：已有底色变化，这里只统一时长与高光 */
.side-new,.plus{transition:transform var(--h-base) var(--e-press),
  box-shadow var(--h-lift) var(--e-out),background-color var(--h-base) var(--e-out)}
@media (hover:hover){
  .side-new:hover{box-shadow:0 14px 30px -12px rgba(0,0,0,.8),var(--hi)}
  .plus:hover{box-shadow:0 10px 22px -8px rgba(0,113,227,.95),var(--hi)}
}
.side-new:active,.plus:active{transform:scale(.94)}

/* 虚线上传/添加位 */
@media (hover:hover){
  .todo-add:hover{transform:translateY(var(--lift-1));
    box-shadow:0 4px 14px -10px rgba(0,113,227,.6)}
  .phAdd:hover{border-color:rgba(0,113,227,.45);color:var(--blue);
    background:rgba(0,113,227,.035);transform:translateY(var(--lift-1))}
}
.todo-add:active,.phAdd:active{transform:scale(.985)}

/* ───────── 二、图标/文本链接：箭头轻推 + 颜色加深 ───────── */
.more,.card-h .more,.sec-h .more,.pg-head .hl .bak{
  transition:color var(--h-base) var(--e-out),opacity var(--h-base) var(--e-out),
             transform var(--h-base) var(--e-out)}
@media (hover:hover){
  .more:hover,.card-h .more:hover,.sec-h .more:hover{opacity:1;color:var(--blue-d);
    transform:translateX(2px)}
}
.side-nav a,.links a{transition:color var(--h-base) var(--e-out),
  background-color var(--h-base) var(--e-out),transform var(--h-base) var(--e-out)}
@media (hover:hover){
  /* 侧栏每项一条淡底，跟 .side-ind 的滑块不冲突（滑块 z-index 更低） */
  .side-nav a:hover{background:rgba(0,0,0,.038)}
  .side-nav a.on:hover{background:transparent}
}

/* ───────── 三、列表行：底色 + 一圈内描边，不位移 ───────── */
/* 行内常常还套着删除按钮，位移会让两行互相压，所以行只换底色 */
.row[data-act],.crow[data-act],.tli[data-act],.s-r,.doc,.ev,.wk,
.uisel-it,.uarow,.arli[data-act],.utr:not(.head)[data-act]{
  transition:background-color var(--h-base) var(--e-out),
             box-shadow var(--h-base) var(--e-out),
             transform var(--h-base) var(--e-out)}
@media (hover:hover){
  .row[data-act]:hover,.crow[data-act]:hover,.doc:hover,.ev:hover,.wk:hover{
    background:rgba(0,0,0,.032);box-shadow:inset 0 0 0 1px rgba(255,255,255,.55)}
  .tli[data-act]:hover{background:rgba(0,113,227,.05);
    box-shadow:inset 0 0 0 1px rgba(0,113,227,.08)}
  .s-r:hover,.uisel-it:hover{background:rgba(0,113,227,.06)}
  .uarow:hover{background:rgba(0,0,0,.028)}
}

/* 设置页的 .setrow 目前都不是整行可点（可点的入口是行内那颗 .btn / .sw），
   所以整行不给悬停底色 —— 避免「看着能点、点哪都没反应」。
   下面这条只在某行真的挂了 data-act 时才生效，是备用而非现状。 */

/* ───────── 四、卡片与瓦片：抬 2px + 阴影升级 ───────── */
.glass.card,.panel{transition:transform var(--h-lift) var(--e-out),
  box-shadow var(--h-lift) var(--e-out)}
@media (hover:hover){
  .glass.card:hover,.panel:hover{transform:translateY(var(--lift-2));
    box-shadow:var(--sh-2),var(--hi),inset 0 -1px 0 rgba(255,255,255,.18)}
  /* 卡片里正在展开下拉时不许抬，否则弹层会跟着动 */
  .glass.card:has(.uisel.open):hover,.panel:has(.uisel.open):hover{transform:none}
}
@media (hover:none){
  /* 触屏没有悬停，卡片靠按下反馈 */
  .glass.card:active,.panel:active{transform:scale(.994)}
}

/* 照片瓦片：抬 2px + 描边提亮 */
.ftile{transition:transform var(--h-lift) var(--e-out),
  box-shadow var(--h-lift) var(--e-out)}
@media (hover:hover){
  .ftile:hover{transform:translateY(var(--lift-2));
    box-shadow:var(--sh-1),inset 0 0 0 1px rgba(0,113,227,.18)}
}

/* 学生格：30 个格子挨着，幅度必须克制，1.03 就够看出来 */
.kid{transition:transform var(--h-lift) var(--e-press),
  box-shadow var(--h-lift) var(--e-out),background-color var(--h-base) var(--e-out)}
@media (hover:hover){
  .kid[data-act]:hover,.kid.pick:hover{transform:translateY(var(--lift-2)) scale(1.03);
    z-index:3;box-shadow:var(--sh-1),var(--hi)}
}
.kid:active{transform:translateY(0) scale(.97)}

/* ───────── 五、输入控件：悬停先给一点反馈，聚焦才是主角 ───────── */
.inp,.sel,.ta,.af-in,.search,.uisel-btn{
  transition:border-color var(--h-base) var(--e-out),
             box-shadow var(--h-base) var(--e-out),
             background-color var(--h-base) var(--e-out)}
@media (hover:hover){
  .inp:hover,.sel:hover,.ta:hover,.af-in:hover{
    border-color:rgba(0,113,227,.28);background:rgba(255,255,255,.9)}
  .search:hover{border-color:rgba(0,0,0,.1);background:rgba(255,255,255,.82);
    box-shadow:0 2px 10px -8px rgba(35,38,52,.6)}
  .uisel-btn:hover{border-color:rgba(0,0,0,.14);box-shadow:0 2px 8px -6px rgba(35,38,52,.5)}
}
/* 聚焦优先级最高：hover 的浅色一律让位 */
.inp:focus,.sel:focus,.ta:focus,.af-in:focus,.search:focus-within,.uisel.open .uisel-btn{
  border-color:rgba(0,113,227,.5);background:rgba(255,255,255,.97)}

/* ───────── 六、分段控件 / 胶囊 / 标签 ───────── */
.seg button{transition:color var(--h-base) var(--e-out),
  background-color var(--h-base) var(--e-out)}
@media (hover:hover){
  /* 只改字色，不铺底色 —— 底片是给 .ind 滑块用的，铺了会和滑块打架 */
  .seg button:hover{color:var(--ink2)}
  .seg button.on:hover{color:var(--ink)}
}
@media (hover:hover){
  .chip:hover{background:rgba(255,255,255,.8);border-color:rgba(255,255,255,.95);
    box-shadow:var(--sh-1),var(--hi)}
  .pk:hover{background:rgba(0,0,0,.055);color:var(--ink)}
  .pk.on:hover{background:rgba(0,113,227,.13)}
  .pk-add:hover{border-color:rgba(0,113,227,.45);color:var(--blue)}
  .avgrid i:hover,.sg-pop button:hover{box-shadow:var(--sh-1),var(--hi)}
}
.chip:active,.pk:active{transform:scale(.97)}

/* ───────── 七、勾选 / 开关 / 可点缩略图 ───────── */
.tick{transition:border-color var(--h-base) var(--e-out),
  background-color var(--h-base) var(--e-out),
  box-shadow var(--h-lift) var(--e-out)}
@media (hover:hover){
  .todo:hover .tick{border-color:rgba(0,113,227,.55);
    box-shadow:0 0 0 4px rgba(0,113,227,.08)}
  .sw:hover{box-shadow:0 0 0 4px rgba(0,0,0,.045)}
  .sw.on:hover{box-shadow:0 0 0 4px var(--brand-100)}
  .kid.pick:hover .kchk{border-color:var(--sel-line)}
}
.sw{transition:background-color var(--h-base) var(--e-out),
  box-shadow var(--h-lift) var(--e-out)}
.sw::after{transition:transform var(--h-base) var(--e-press),width var(--h-base) var(--e-out)}

/* ───────── 八、删除键：能聚焦就必须看得见 ───────── */
/* 原来 .del / .fdel 只在 hover 才 opacity:1，键盘 Tab 到它时是隐形的 */
@media (hover:hover){
  .row:hover .del,.ftile:hover .fdel{opacity:1}
}
.row .del:focus-visible,.fdel:focus-visible,.fdel:focus{opacity:1}
.del,.fdel{transition:opacity var(--h-fast) var(--e-out),
  background-color var(--h-base) var(--e-out),color var(--h-base) var(--e-out),
  transform var(--h-base) var(--e-press)}
@media (hover:hover){
  .del:hover,.fdel:hover{transform:scale(1.08)}
}

/* ───────── 九、键盘聚焦：与悬停同等的视觉重量 ───────── */
/* 悬停有的抬升，键盘聚焦也要有，否则鼠标和键盘看到的不是一套界面 */
@media (hover:hover){
  .btn:focus-visible,.icon-btn:focus-visible,.ftile:focus-visible,
  .kid[data-act]:focus-visible,.row[data-act]:focus-visible,
  .setrow[data-act]:focus-visible,.tli[data-act]:focus-visible{
    box-shadow:var(--sh-1),var(--hi)}
}
/* 但位移不给聚焦态：Tab 一路走过去，页面一直在抖 */
.btn:focus-visible,.ftile:focus-visible{--lift:0px}

/* ───────── 十、触屏：没有悬停，全靠按下 ───────── */
@media (hover:none){
  /* 触屏上 :hover 会「粘住」——点完不松手就一直保持抬起，看着像卡住。
     用 :not(:active) 排除正在按下的那一颗，按下反馈才不会被这条重置吃掉。 */
  .glass.card:hover:not(:active),.panel:hover:not(:active),.ftile:hover:not(:active),
  .kid[data-act]:hover:not(:active),.kid.pick:hover:not(:active),
  .btn:hover:not(:active){transform:none}
  /* 这些元素本来就只在 hover 时现身，触屏必须常显，否则根本看不见 */
  .row .del,.ftile .fdel{opacity:1}
  /* 按压给即时反馈：缩小 + 底色变深，松手回弹 */
  .row[data-act],.crow[data-act],.tli[data-act],.setrow[data-act],.doc,.ev,.wk{
    transition:background-color var(--h-fast) var(--e-out),transform var(--h-fast) var(--e-out)}
  .row[data-act]:active,.crow[data-act]:active,.tli[data-act]:active,
  .setrow[data-act]:active,.doc:active,.ev:active,.wk:active{
    background:rgba(0,0,0,.055);transform:scale(.99)}
  .kid[data-act]:active,.kid.pick:active{transform:scale(.97)}
  .btn:active,.chip:active,.pk:active,.todo-add:active{transform:scale(.96)}
  .tick{width:20px;height:20px}   /* 手指点得中 */
}

/* ───────── 十一、减少动态效果：只留颜色，不给位移 ───────── */
@media (prefers-reduced-motion:reduce){
  .btn,.icon-btn,.plus,.side-new,.todo-add,.phAdd,.chip,.pk,
  .glass.card,.panel,.ftile,.kid,.row[data-act],.crow[data-act],.tli[data-act],
  .setrow[data-act],.doc,.ev,.wk,.del,.fdel,.more{
    transition-duration:.01ms!important}
  .glass.card:hover,.panel:hover,.ftile:hover,.kid:hover,
  .kid[data-act]:hover,.kid.pick:hover,.btn:hover,.icon-btn:hover,
  .del:hover,.fdel:hover,.todo-add:hover,.phAdd:hover,
  .row[data-act]:active,.crow[data-act]:active,.setrow[data-act]:active{
    transform:none!important}
  /* 磁吸必须一起关掉，否则位移还在 */
  .btn{transform:none!important}
}

/* ───────── 十二、收尾：把剩下几处零散时长并到同一套 token ───────── */
/* .kpi.plain 有更具体的 transition:none，这里不会把它叫醒 */
.kpi{transition:transform var(--h-lift) var(--e-out),
  box-shadow var(--h-lift) var(--e-out)}
.todo{transition:background-color var(--h-base) var(--e-out),
  transform var(--h-fast) var(--e-out)}
.t-body b,.doc b,.wk .wb b{transition:color var(--h-base) var(--e-out)}
.tr{transition:background-color var(--h-base) var(--e-out)}
.kpi-ring .mini-ring .dial{transition:filter var(--h-lift) var(--e-out)}

/* 分段控件的滑块 .ind、导航收放 .nav-in、进度条 .track i 属于「页面级过渡」，
   不是鼠标反馈，保留各自的曲线 —— 悬停统一的是"手一放上去多快有回应"，
   不是把所有动效压成一个速度。 */

/* ───────── 跳到正文（WCAG 2.4.1） ───────── */
/* 平时藏在视口外，一按 Tab 就滑进来；纯键盘用户不必先过 11 个导航项 */
.skip{position:fixed;left:16px;top:16px;z-index:1200;
  height:36px;padding:0 18px;border:0;border-radius:980px;cursor:pointer;
  background:var(--ink);color:#fff;font:inherit;font-size:13px;font-weight:500;
  box-shadow:0 12px 26px -12px rgba(0,0,0,.75);
  transform:translateY(-160%);opacity:0;pointer-events:none;
  transition:transform var(--h-lift) var(--e-out),opacity var(--h-base) var(--e-out)}
.skip:focus{transform:translateY(0);opacity:1;pointer-events:auto}
/* 焦点落在内容容器上，不画环（环留给真正的控件） */
#view:focus,#view:focus-visible{outline:none}
/* 页标题只是「焦点落点」——换页时把焦点交给它，读屏才会念出页名。
   它不是可操作元素，不该画焦点环；否则每次换页标题外面都挂一个蓝框，
   看着像被选中了一段文字。真正可操作的控件仍然保留焦点环。 */
#view h1:focus,#view h1:focus-visible,
#view h2:focus,#view h2:focus-visible,
.fx-sticky h1:focus,.fx-sticky h1:focus-visible{outline:none!important}

/* ───────── 自绘下拉：键盘高亮项 ───────── */
/* 焦点一直留在按钮上（标准 combobox），列表里靠 aria-activedescendant 指位置，
   这个类只负责把「现在指的是哪一项」画出来。 */
.uisel-it.act:not(.on){background:rgba(0,113,227,.12);color:var(--ink)}
.uisel-it.act{outline:none}

/* ───────── 专属相册 ───────── */
/* 排序条：一个下拉 + 一张张数。下拉是 .sel，会被 ui-select 自动换成玻璃样式 */
.alb-bar{display:flex;align-items:center;gap:10px;margin:2px 0 10px;flex-wrap:wrap}
.alb-sel{width:auto;min-width:150px;height:30px;font-size:12px;
  padding-top:0;padding-bottom:0;flex:0 0 auto}
.alb-tip{font-size:12px;color:var(--ink4);font-variant-numeric:tabular-nums}

/* 网格：一格 = 照片 + 下面的备注框，所以列宽比照片墙宽一点 */
.alb-grid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));align-items:start}
.alb-cell{display:flex;flex-direction:column;gap:6px;min-width:0}
.alb-cell .ftile{width:100%}

/* 备注框：平时像一条浅浅的下划线，聚焦才浮起来 */
.fcap{
  width:100%;box-sizing:border-box;font:inherit;font-size:12px;color:var(--ink);
  padding:6px 8px;border-radius:8px;
  border:1px solid transparent;background:rgba(0,0,0,.035);
  outline:none;letter-spacing:-.005em;
  transition:background-color .2s var(--e-out, ease),border-color .2s var(--e-out, ease),
             box-shadow .2s var(--e-out, ease)}
.fcap::placeholder{color:var(--ink4)}
.fcap:hover{background:rgba(0,0,0,.055)}
.fcap:focus{background:#fff;border-color:rgba(0,113,227,.45);
  box-shadow:0 0 0 3px rgba(0,113,227,.1)}
/* 存下来的一瞬间闪一下边框，不用弹 toast 打断 */
.fcap.saved{border-color:rgba(52,199,89,.75);background:rgba(52,199,89,.07)}

/* ───────── 相册折叠（收起态） ─────────
   收起时整张卡只有：标题「专属相册 · N 张」+ 一颗「展开」+ 一行预览。
   预览行本身也是按钮（点整行就开），与其它列表行的悬停规则保持一致：
   换底色 + 一圈内描边，不位移 —— 位移会把下面那张卡挤一下。 */
.alb-peek{
  display:flex;align-items:center;gap:12px;
  padding:9px 10px;margin-top:2px;border-radius:14px;
  cursor:pointer;
  transition:background-color var(--h-base,.2s) var(--e-out,ease),
             box-shadow var(--h-base,.2s) var(--e-out,ease)}
@media (hover:hover){
  .alb-peek:hover{background:rgba(0,0,0,.03);
    box-shadow:inset 0 0 0 1px rgba(255,255,255,.55)}
}
.alb-peek:active{background:rgba(0,0,0,.055)}

/* 三张缩略叠着放：一张一张排会占掉半行，叠起来只用一个缩略的宽度 */
.alb-peek-ims{display:flex;flex:none}
.alb-pk{
  width:42px;height:42px;border-radius:10px;display:block;
  background:#E7E7EF center/cover no-repeat;
  box-shadow:0 0 0 2px #fff,0 2px 8px -4px rgba(35,38,52,.55)}
.alb-pk + .alb-pk{margin-left:-12px}
.alb-pk.miss{background-image:none!important;background:#E7E7EF}

.alb-peek-tx{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
.alb-peek-tx b{font-size:13px;font-weight:600;color:var(--ink);letter-spacing:-.01em}
.alb-peek-tx span{
  font-size:12px;color:var(--ink3);line-height:1.35;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* 箭头：悬停时右推 2px 并与上面 .more 链接同幅度，指向「点开」 */
.alb-chev{
  flex:none;font-style:normal;font-size:19px;line-height:1;
  color:var(--ink4);
  transition:transform var(--h-base,.2s) var(--e-out,ease),
             color var(--h-base,.2s) var(--e-out,ease)}
@media (hover:hover){
  .alb-peek:hover .alb-chev{transform:translateX(2px);color:var(--ink3)}
}

/* 展开：正文一层 260ms 淡入上浮。高度不做动画 ——
   网格高度由图片决定，max-height 猜不准会把最后一行裁掉。 */
.alb-body{animation:albIn .26s cubic-bezier(.22,1,.36,1) both}
@keyframes albIn{
  from{opacity:0;transform:translateY(-4px)}
  to{opacity:1;transform:none}
}

/* 排序条右边两颗：导出靠最右，整理紧随其后。
   只有导出吃 margin-left:auto —— 两颗都 auto 的话空隙会被平分，中间空一大段 */
.alb-bar .alb-export{margin-left:auto}
.alb-bar .alb-edit,.alb-bar .alb-export{flex:none}

/* 窄屏：下拉 + 导出 + 整理 正好一行。
   「共 N 张 · M 条备注」先让位 —— 标题里已经有张数，
   留着它会把「整理」挤到第三行单独杵着，比丢一行小字难看得多。 */
@media (max-width:640px){
  .alb-bar{flex-wrap:nowrap;gap:7px}
  .alb-bar .alb-tip{display:none}
  .alb-bar .uisel{flex:1 1 auto;min-width:0;max-width:none}
  .alb-bar .uisel-btn{min-width:0;padding:0 24px 0 10px}
}

@media (prefers-reduced-motion:reduce){
  .alb-body{animation:none}
  .alb-chev{transition:none}
  .alb-peek:hover .alb-chev{transform:none}
}
/* 触屏没有悬停：按下给一层底色，别让预览行看起来是死的 */
@media (hover:none){
  .alb-peek:active{background:rgba(0,0,0,.06)}
}

/* ───────── 云端照片：大图弹层 ─────────
   跨设备看大图时，图片要从云端签名地址加载（几百毫秒）。
   所以容器先占住高度并给一句「正在取图」，图片到了再换进来 ——
   否则点下去会有一段什么都没有的空白，看着像没点到。 */
.bigpic{
  position:relative;
  min-height:180px;
  margin-top:10px;border-radius:12px;
  background:#EDE9F2 center/contain no-repeat;
  display:flex;align-items:center;justify-content:center;
  overflow:hidden}
.bigpic img{display:block;width:100%;height:auto;border-radius:12px}
.bigpic > span{
  font-size:13px;color:var(--ink3);line-height:1.5;
  padding:32px 22px;text-align:center}
.bigpic.miss{background:rgba(0,0,0,.035)}

/* 「云端副本」角标：只在图片来自云端时出现。
   不是装饰 —— 它解释了「为什么这张看起来比本机那张略小」：
   云端存的是 1280px，本机原图是 1600px。 */
.bigpic .cloudtag{
  position:absolute;right:10px;top:10px;
  font-style:normal;font-size:12px;letter-spacing:.02em;
  color:#0B5FB0;background:rgba(255,255,255,.86);
  padding:3px 8px;border-radius:980px;
  box-shadow:0 2px 8px -4px rgba(0,0,0,.35),inset 0 0 0 1px rgba(0,113,227,.18);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}

/* 相册格里来自云端的图层：不加视觉差异。
   本机的 1600px 和云端的 1280px 在 150px 的格子里看不出区别，
   加个角标只会让照片墙变花；真要区分，去「照片体检」看。 */

/* ═══════════════════════════════════════════════════════════════
   任务拆解 v1（decomp.js）
   结构：交代任务卡 → 拆解表（可勾选）→ 最近拆过的
   视觉沿用卡片语言，只补这一页特有的排布
   ═══════════════════════════════════════════════════════════════ */
.dc-form .cnt{color:var(--ink3)}
.dc-two{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-3)}
.dc-bar{display:flex;align-items:center;gap:var(--sp-2);margin-top:var(--sp-4);flex-wrap:wrap}
.dc-st{font-size:var(--fs-sm);color:var(--ink3)}

.dc-empty{margin-top:var(--sp-4);padding:var(--sp-8) var(--sp-5);text-align:center}
.dc-empty b{display:block;font-size:var(--fs-base);font-weight:520;color:var(--ink)}
.dc-empty p{margin:var(--sp-2) 0 0;font-size:var(--fs-sm);color:var(--ink3);line-height:1.7}
.dc-empty.bad b{color:var(--red-text)}

.dc-res{margin-top:var(--sp-4)}
.dc-acts{margin-left:auto;display:flex;gap:var(--sp-2);flex:none}

.dc-prog{height:4px;border-radius:980px;background:var(--fill-2);overflow:hidden;margin:var(--sp-2) 0 6px}
.dc-prog i{display:block;height:100%;border-radius:980px;
  background:var(--ok);
  transition:width var(--t-hover-in,220ms) var(--c-out,cubic-bezier(.22,1,.36,1))}
.dc-progt{display:flex;justify-content:space-between;gap:var(--sp-3);
  font-size:var(--fs-xs);color:var(--ink4);font-variant-numeric:tabular-nums}

.dc-list{display:flex;flex-direction:column;margin-top:var(--sp-3)}
.dc-row{display:flex;gap:var(--sp-3);padding:var(--sp-3) var(--sp-2);
  border-radius:var(--r-sm);cursor:default;
  transition:background var(--t-hover-out,180ms) var(--c-out,cubic-bezier(.22,1,.36,1))}
.dc-row + .dc-row{border-top:1px solid var(--fill-2)}
.dc-row:hover{background:var(--line-soft)}

/* 勾选：自绘方框，比原生 checkbox 更贴合这套视觉；
   role="checkbox" + aria-checked 已写在按钮上，读屏能念 */
.dc-ck{flex:0 0 auto;width:20px;height:20px;margin-top:2px;padding:0;
  border:1.5px solid var(--check-line);border-radius:var(--r-xs);background:var(--field);
  color:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;
  transition:background .18s var(--ease),border-color .18s var(--ease),transform .12s var(--spring)}
.dc-ck svg{width:12px;height:12px}
.dc-ck:hover{border-color:var(--blue-ring)}
.dc-ck:active{transform:scale(.9)}
.dc-ck:focus-visible{outline:2px solid var(--blue);outline-offset:2px}
.dc-row.done .dc-ck{background:var(--ok);border-color:var(--ok);color:#fff}
.dc-row.done .dc-main b{color:var(--ink4);text-decoration:line-through;text-decoration-thickness:1px}
.dc-row.done .dc-meta,.dc-row.done .dc-ac{color:var(--ink4)}

.dc-main{min-width:0;flex:1}
.dc-main b{display:block;font-size:var(--fs-base);font-weight:520;color:var(--ink);
  line-height:1.55;letter-spacing:-.005em}
.dc-main b i{font-style:normal;display:inline-block;min-width:1.4em;color:var(--ink4);
  font-variant-numeric:tabular-nums;font-weight:400}
.dc-meta{display:flex;gap:var(--sp-2);flex-wrap:wrap;margin-top:var(--sp-1)}
.dc-meta span{font-size:var(--fs-xs);color:var(--ink3);background:var(--fill);
  padding:2px var(--sp-2);border-radius:980px}
.dc-meta .dc-own{color:var(--blue-d);background:var(--brand-50)}
.dc-meta .dc-dep{color:var(--ink4);background:transparent;padding-left:0}
.dc-ac{margin:var(--sp-2) 0 0;font-size:var(--fs-sm);color:var(--ink2);line-height:1.6}
.dc-ac em{font-style:normal;font-size:var(--fs-xs);color:var(--ok-text);background:var(--ok-soft);
  padding:1px var(--sp-2);border-radius:var(--r-xs);margin-right:var(--sp-2)}

.dc-hist{margin-top:var(--sp-4)}
.dc-hist:empty{display:none}

@media (max-width:576px){
  .dc-two{grid-template-columns:1fr}
  .dc-acts{width:100%;margin-left:0;justify-content:flex-end}
  .dc-res .card-h{flex-wrap:wrap}
  .dc-row{gap:var(--sp-3)}
}

/* 首页顶部的「工作参谋」快入口。
   触发时机是手里正拿着一条通知，所以它是输入框而不是按钮：
   贴一段文字 → 回车 → 跳到参谋页自动开跑。 */
.adv-bar{display:block;
  padding:var(--sp-3) var(--sp-4);margin:0 0 var(--sp-4);border-radius:var(--r-md)}
/* 第一行：图标 + 标题 + 输入框 + 按钮。固定一行，输入框吃掉剩余宽度 */
.adv-l1{display:flex;align-items:center;gap:var(--sp-3)}
.adv-ic{flex:0 0 auto;width:30px;height:30px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  color:var(--blue);background:var(--brand-50)}
.adv-tt{flex:0 0 auto;min-width:0}
.adv-tt b{display:block;font-size:var(--fs-sm);font-weight:520;color:var(--ink);letter-spacing:-.01em}
.adv-tt em{display:block;font-style:normal;font-size:var(--fs-xs);color:var(--ink3);margin-top:2px}
.adv-inp{flex:1 1 auto;min-width:0;height:36px;
  background:var(--fill);border-color:transparent}
.adv-inp:hover{background:var(--fill-2)}
.adv-inp:focus{background:var(--field);border-color:var(--blue-ring)}
.adv-go{flex:0 0 auto}

@media (max-width:768px){
  .adv-bar{padding:var(--sp-3)}
  .adv-l1{flex-wrap:wrap;gap:var(--sp-3)}
  .adv-ic{display:none}
  .adv-tt{flex:1 1 100%}
  .adv-inp{flex:1 1 auto;order:3;height:36px;min-width:0;width:auto}
  .adv-go{order:4;flex:0 0 auto}
}

/* 分工表下面「接着办」的两个动作：往下说一遍 / 写份汇报 */
.dc-next{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap;
  margin-top:var(--sp-3);padding-top:var(--sp-3);border-top:1px solid var(--fill-2)}
.dc-next > span{font-size:var(--fs-xs);color:var(--ink4)}

.dc-say,.dc-rep{margin-top:var(--sp-4)}
.dc-pick{display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap;margin:var(--sp-2) 0 0}
.dc-pl{font-size:var(--fs-xs);color:var(--ink3);flex:0 0 auto}
.dc-chips{display:flex;gap:var(--sp-2);flex-wrap:wrap}
.dc-chips .chip{font-size:var(--fs-sm);min-height:30px;padding:0 var(--sp-3)}

/* 生成出来的那段话：等宽不了，按正文读；留白比正文大一点，像一片纸 */
.dc-out{margin-top:var(--sp-3);padding:var(--sp-3) var(--sp-4);border-radius:var(--r-sm);
  font-size:var(--fs-base);line-height:1.85;color:var(--ink);
  white-space:pre-wrap;word-break:break-word;
  background:var(--line-soft);min-height:56px}
.dc-out.ph{color:var(--ink4);font-size:var(--fs-sm);line-height:1.7}
.dc-out.run{color:var(--ink3);font-size:var(--fs-sm)}
.dc-out.bad{color:var(--red-text);font-size:var(--fs-sm);background:var(--red-soft)}
.dc-tip{margin:var(--sp-2) 0 0;font-size:var(--fs-xs);color:var(--ink4);line-height:1.6}

/* 窄屏：这两张卡的副标题太长，会把右上角的「复制」挤出屏幕 */
@media (max-width:576px){
  .dc-say .card-h,.dc-rep .card-h{flex-wrap:wrap;row-gap:var(--sp-2)}
  .dc-say .card-h .cnt,.dc-rep .card-h .cnt{order:3;flex:1 1 100%;margin-left:0}
  .dc-say .card-h .dc-acts,.dc-rep .card-h .dc-acts{margin-left:auto}
}

/* 侧栏按权限隐藏的入口：.side-nav a 的 display:flex 会压过 [hidden]，
   这里显式盖回来，别让没授权的人在白名单里看见一条点不开的项。 */
.side-nav a[hidden]{display:none!important}

/* 话术卡里的「补一句背景」：一行输入，填了会喂进提示词，
   模型据此调整口气（家长焦虑 / 孩子刚入园 / 上次答应过什么） */
.dc-extra{margin-top:var(--sp-3);display:flex;flex-direction:column;gap:var(--sp-2)}
.dc-extra > label{font-size:var(--fs-xs);color:var(--ink3)}
.dc-extra .inp{height:34px;font-size:var(--fs-sm);
  background:var(--fill);border-color:transparent}
.dc-extra .inp:hover{background:var(--fill-2)}
.dc-extra .inp:focus{background:var(--field);border-color:var(--blue-ring)}

/* 「问一句」：自由提问区。放在参谋页最上面，因为大多是临时起意的一句话 */
.ask{margin-bottom:var(--sp-4)}
.ask-ta{line-height:1.7}
.ask-row{display:grid;grid-template-columns:1fr 1fr 1fr;gap:var(--sp-3);margin-top:var(--sp-3)}
.ask-out{margin-bottom:var(--sp-4)}
.ask-type{font-size:var(--fs-xs);color:var(--blue-d);background:var(--brand-50);
  padding:2px 8px;border-radius:980px;flex:0 0 auto}
.ask-ans{line-height:1.9}
.ask-swap{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap;margin-top:var(--sp-3);
  padding-top:var(--sp-3);border-top:1px solid var(--fill-2)}
.ask-swap > span{font-size:var(--fs-xs);color:var(--ink4);flex:0 0 auto}
.ask-swap .chip{font-size:var(--fs-sm);min-height:28px;padding:0 var(--sp-2)}

@media (max-width:768px){
  .ask-row{grid-template-columns:1fr}
}

/* 向下话术：口语版 / 正式版并排。窄屏上下摞 */
.say-two{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:var(--sp-4);margin-top:var(--sp-3);align-items:stretch}
.say-col{min-width:0;display:flex;flex-direction:column}
.say-h{display:flex;align-items:center;gap:var(--sp-2);margin-bottom:var(--sp-2)}
.say-h b{font-size:var(--fs-sm);font-weight:520;color:var(--ink)}
/* 复制按钮贴着标题、不甩到分栏线那边，两栏看着才不像一坨 */
.say-h .btn{margin-left:var(--sp-2)}
.say-h .btn:last-child{margin-left:auto}
.say-col .dc-out{margin-top:0;flex:1 1 auto}
@media (max-width:768px){
  .say-two{grid-template-columns:1fr;gap:var(--sp-3)}
}

/* 待办行上的来源标：这条是从工作参谋的分工派出来的，不是自己随手记的 */
/* 待办行上的来源标（参谋派工 / 提醒 / 循环）。以前只挂在 .t-body b 下，
   待办页那套 .g b 结构吃不到样式，字就成了斜体粘在标题后面 —— 收成通用类。 */
.tref{font-style:normal;font-size:var(--fs-xs);font-weight:400;color:var(--blue-d);
  background:var(--brand-50);padding:1px var(--sp-1);border-radius:var(--r-xs);margin-left:var(--sp-2);
  vertical-align:1px;display:inline-block;line-height:1.5}

/* 传通知：Word / PDF。做成一行按钮，比再摆一个大上传框轻 */
.dc-up{display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap;margin-top:var(--sp-3)}
.dc-up-btn{display:inline-flex;align-items:center;height:32px;padding:0 var(--sp-3);border-radius:var(--r-sm);
  font-size:var(--fs-sm);color:var(--ink2);background:var(--fill);cursor:pointer;
  transition:background .18s var(--ease),color .18s var(--ease)}
.dc-up-btn:hover{background:var(--fill-2);color:var(--ink)}
.dc-up-btn:focus-within{outline:2px solid var(--blue);outline-offset:2px}
.dc-up-st{font-size:var(--fs-xs);color:var(--ink4)}

/* 勾选进待办的行：不再用「完成」的划掉样式，只做轻微标记 */
.dc-row.picked{background:var(--brand-50)}
.dc-row.picked .dc-main b{color:var(--ink)}
.dc-row.picked .dc-ck{background:var(--ok);border-color:var(--ok);color:#fff}

/* 首页快入口下面那排上下文：身份 / 说给谁 / 场合。
   目的只有一个 —— 点进去别再让人选一遍。 */
.adv-ctx{display:flex;gap:var(--sp-2);flex-wrap:wrap;margin-top:var(--sp-3);
  padding-top:var(--sp-3);border-top:1px solid var(--fill-2)}
.adv-sel{width:auto;min-width:132px;height:var(--h-field);font-size:var(--fs-sm);
  background:var(--fill);border-color:transparent;padding:0 28px 0 10px}
.adv-sel:hover{background:var(--fill-2)}
.adv-sel:focus{background:var(--field);border-color:var(--blue-ring)}
@media (max-width:768px){
  .adv-ctx{gap:var(--sp-2)}
  .adv-sel{flex:1 1 calc(50% - 3px);min-width:0}
  .adv-sel:first-child{flex-basis:100%}
}

/* 问一句与任务输入框：白底白边在白卡片上等于没有边界，改成浅灰底 */
.ask-ta,.dc-form .ta{background:var(--fill);border-color:transparent}
.ask-ta:hover,.dc-form .ta:hover{background:var(--fill-2)}
.ask-ta:focus,.dc-form .ta:focus{background:var(--field);border-color:var(--blue-ring)}
.ask-ta{line-height:1.7}

/* 窄屏：卡片头部（标题+说明+操作按钮）必须能换行。
   之前只给"分工表"和两张新卡写了 wrap，答句卡和汇报卡的按钮行仍会顶出屏幕。 */
@media (max-width:576px){
  .dc-res .card-h,.dc-say .card-h,.dc-rep .card-h,.ask-out .card-h,.dc-form .card-h{
    flex-wrap:wrap;row-gap:var(--sp-2)}
  .dc-acts{flex:1 1 100%;width:auto;margin-left:0;justify-content:flex-end}
  .dc-res .card-h .cnt,.dc-say .card-h .cnt,.dc-rep .card-h .cnt{
    flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .ask-swap > span{flex:1 1 100%}
}

/* 窄屏这两张卡上的副标题是装饰，留着会把标题行挤成三行，直接收掉 */
@media (max-width:576px){
  .dc-say .card-h > .cnt,.dc-rep .card-h > .cnt{display:none}
}

/* 本园文风样本：默认收起，省得每次进来都看见一个大空框 */
.dc-style{margin-top:var(--sp-3)}
.dc-style-t{appearance:none;border:0;background:transparent;padding:0;cursor:pointer;
  font-size:var(--fs-sm);color:var(--blue);letter-spacing:-.01em}
.dc-style-t:hover{text-decoration:underline}
.dc-style-t:focus-visible{outline:2px solid var(--blue);outline-offset:3px;border-radius:var(--r-xs)}
.dc-style-b{margin-top:var(--sp-2)}
.dc-style-b .ta{line-height:1.7}

/* 生成结果可编辑：外形仍像一张纸，但点进去就能改。
   以前是只读 div，改一句要先复制到 Word —— 那一步就是"鸡肋"的来源。 */
.dc-edit{display:block;width:100%;box-sizing:border-box;
  max-height:var(--h-ta-max);
  overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;
  touch-action:pan-y;
  font-family:inherit;font-size:var(--fs-base);line-height:1.85;color:var(--ink);
  padding:var(--sp-3) var(--sp-4);border:1px solid transparent;
  border-radius:var(--r-sm);background:var(--fill);
  transition:background var(--t-hover-out,180ms) var(--c-out,cubic-bezier(.22,1,.36,1)),
             border-color .18s var(--ease)}
.dc-edit:hover{background:var(--fill-2)}
.dc-edit:focus{outline:none;background:var(--field);border-color:var(--blue-ring)}
.dc-edit::placeholder{color:var(--ink4)}
@media (hover:hover) and (pointer:fine){
  .dc-edit{resize:vertical}
}
/* 双保险：有些 Android WebView 会把 hover 报成 hover，这里再按指针类型兜一次 */
@media (pointer:coarse){
  .ta,.dc-edit{resize:none}
}

/* 反馈行：「像 / 不太像」。攒几条之后生成的东西会越来越像本人 */
.dc-fb{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap;
  margin-top:var(--sp-4);padding-top:var(--sp-3);border-top:1px solid var(--fill-2)}
.dc-fb-l{font-size:var(--fs-xs);color:var(--ink4)}
.dc-fb-in{display:flex;align-items:center;gap:var(--sp-2);flex:1 1 100%;margin-top:var(--sp-1)}
.dc-fb-in .inp{flex:1 1 auto;height:var(--h-field);font-size:var(--fs-sm);min-width:0;
  background:var(--fill);border-color:transparent}
.dc-fb-in .inp:focus{background:var(--field);border-color:var(--blue-ring)}
@media (max-width:576px){
  .dc-fb-l{flex:1 1 100%}
}

/* 风格库：列表按「身份 → 对象」分组显示，添加区收在最下面。
   设计上刻意做得像一份档案卡，而不像设置里的表单。 */
.sl-list{display:flex;flex-direction:column;gap:var(--sp-2);margin:var(--sp-2) 0 var(--sp-3)}
.sl-item{position:relative;padding:var(--sp-2) var(--sp-3);border-radius:var(--r-sm);
  background:var(--fill);border:1px solid var(--fill-2)}
.sl-tag{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap}
.sl-tag b{font-size:var(--fs-xs);font-weight:520;color:var(--blue-d)}
.sl-tag i{font-style:normal;font-size:var(--fs-xs);color:var(--ink4);
  padding:1px var(--sp-2);border-radius:var(--r-xs);background:var(--fill-2)}
.sl-txt{margin:var(--sp-1) 0 0;font-size:var(--fs-sm);color:var(--ink2);line-height:1.6;
  padding-right:var(--sp-10);word-break:break-word}
.sl-del{position:absolute;top:var(--sp-2);right:var(--sp-2);
  border:0;background:transparent;cursor:pointer;padding:2px var(--sp-1);
  font-size:var(--fs-xs);color:var(--ink4);border-radius:var(--r-xs)}
.sl-del:hover{color:var(--red-text);background:var(--red-soft)}

.sl-add{padding-top:var(--sp-3);border-top:1px solid var(--fill-2)}
.sl-row{display:grid;grid-template-columns:1.4fr 1fr 1fr;gap:var(--sp-2);margin-bottom:var(--sp-2)}
.sl-sel{height:var(--h-field);font-size:var(--fs-sm);padding:0 var(--sp-2);
  border:1px solid transparent;border-radius:var(--r-xs);
  background:var(--fill);color:var(--ink);font-family:inherit;
  -webkit-appearance:none;appearance:none;
  background-image:linear-gradient(45deg,transparent 50%,var(--ink4) 50%),
    linear-gradient(135deg,var(--ink4) 50%,transparent 50%);
  background-position:calc(100% - 14px) 14px,calc(100% - 9px) 14px;
  background-size:5px 5px,5px 5px;background-repeat:no-repeat}
.sl-sel:hover{background-color:var(--fill-2)}
.sl-sel:focus{outline:none;background-color:var(--field);border-color:var(--blue-ring)}
.sl-add .ta{line-height:1.7}

.sl-prof{padding:var(--sp-3);border-radius:var(--r-sm);background:var(--brand-50);
  margin-bottom:var(--sp-3)}
.sl-prof-h{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap}
.sl-prof-h b{font-size:var(--fs-sm);font-weight:520;color:var(--blue-d)}
.sl-prof-h span{font-size:var(--fs-xs);color:var(--ink4);flex:1 1 auto}
.sl-prof p{margin:var(--sp-2) 0 0;font-size:var(--fs-sm);color:var(--ink2);
  line-height:1.75;white-space:pre-wrap}

@media (max-width:576px){
  .sl-row{grid-template-columns:1fr 1fr}
  .sl-row .sl-sel:first-child{grid-column:1 / -1}
}

/* 风格库面板的两处收口：折叠箭头 + 添加区与下方字段留出距离 */
.dc-style-arw{display:inline-block;margin-left:var(--sp-1);font-size:var(--fs-xs);color:var(--ink4)}
.sl-add{margin-bottom:var(--sp-4)}

/* 风格库添加区的小标签：窄屏两个下拉并排时，没有标签分不清哪个是对象 */
.sl-cell{display:flex;flex-direction:column;gap:var(--sp-1);min-width:0}
.sl-lb{font-size:var(--fs-sm);color:var(--ink3)}

/* 「我卡在哪」：一行输入，填了会进方案提示词，让它别绕开真正的难点 */
.dc-stuck{margin-top:var(--sp-3);display:flex;flex-direction:column;gap:var(--sp-1)}
.dc-stuck > label{font-size:var(--fs-xs);color:var(--ink3)}
.dc-stuck .inp{height:var(--h-field);font-size:var(--fs-sm);
  background:var(--fill);border-color:transparent}
.dc-stuck .inp:hover{background:var(--fill-2)}
.dc-stuck .inp:focus{background:var(--field);border-color:var(--blue-ring)}

/* 方案卡：一张纸，能改。行距比话术松一点，因为要读进去判断 */
.dc-plan{margin-bottom:var(--sp-4)}
/* 方案动辄八九百字：超过上限改为框内滚动，不把下面的分工表顶到天边 */
.plan-out{min-height:var(--h-ta-plan);max-height:var(--h-ta-max);line-height:1.85}

/* 窄屏方案卡：副标题是装饰，留着会被挤成「判断 · 取...」 */
@media (max-width:576px){
  .dc-plan .card-h > .cnt{display:none}
}

/* 风格库的「传文件」：用 label 包 file input，外观和旁边的按钮一致 */
.sl-file{position:relative;cursor:pointer;display:inline-flex;align-items:center}
.sl-file:focus-within{outline:2px solid var(--blue-ring);outline-offset:2px}

/* 方案卡底部的「你对这版的想法」：输入框 + 一句解释，语气要像商量不像设置 */
.dc-note{margin-top:var(--sp-3);display:flex;flex-direction:column;gap:var(--sp-1)}
.dc-note > label{font-size:var(--fs-xs);color:var(--ink3)}
.dc-note .inp{height:var(--h-field);font-size:var(--fs-sm);
  background:var(--fill);border-color:transparent}
.dc-note .inp:hover{background:var(--fill-2)}
.dc-note .inp:focus{background:var(--field);border-color:var(--blue-ring)}
.dc-note .hintx{margin:var(--sp-1) 0 0}

/* 最近办过的事：两级列表。
   一级一行（标题 + 日期），点开才露出身份、条数和操作。
   原来八条平铺占掉大半屏，现在一屏能看十几条。 */
.hlist{display:flex;flex-direction:column;margin-top:var(--sp-1)}
.hitem + .hitem{border-top:1px solid var(--line-soft)}
.hrow{display:flex;align-items:center;gap:var(--sp-2);width:100%;
  padding:var(--sp-2) var(--sp-1);border:0;background:transparent;
  text-align:left;cursor:pointer;border-radius:var(--r-xs);
  transition:background var(--t-hover-out,180ms) var(--c-out,cubic-bezier(.22,1,.36,1))}
.hrow:hover{background:var(--line-soft)}
.hrow:focus-visible{outline:2px solid var(--blue-ring);outline-offset:-2px}
/* 三角用 CSS 画，不依赖字体里有没有 ▸，各行宽度才稳 */
.hic{flex:0 0 auto;width:6px;height:6px;margin:0 var(--sp-1);
  border-right:1.5px solid var(--ink4);border-bottom:1.5px solid var(--ink4);
  transform:rotate(-45deg);transition:transform .18s var(--ease)}
.hitem.on .hic{transform:rotate(45deg)}
.ht{flex:1 1 auto;min-width:0;font-size:var(--fs-sm);color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hitem.on .ht{white-space:normal;overflow:visible}
.hd{flex:0 0 auto;font-size:var(--fs-xs);color:var(--ink4);font-variant-numeric:tabular-nums}

.hbody{padding:0 0 var(--sp-2) calc(6px + var(--sp-2) + var(--sp-1));
  animation:hdrop .18s var(--ease) both}
@keyframes hdrop{from{opacity:0;transform:translateY(-3px)}to{opacity:1;transform:none}}
.hm{margin:0;font-size:var(--fs-xs);color:var(--ink3)}
.hacts{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap;margin-top:var(--sp-2)}
.hdel-q{font-size:var(--fs-xs);color:var(--red-text)}
.hdel{color:var(--red-text)}
.hdel:hover{background:var(--red-soft)}
@media (max-width:576px){
  .hrow{padding:var(--sp-2) 0}
  .ht{font-size:var(--fs-base)}
}

/* ───────── 进化页（写作素材 + 对象画像） ─────────
   全部沿用现有 token 与卡片/表格/样本条目三套现成组件，不新造视觉语言；
   新增的只有「放料区」「格式摘要条」「开关行」三块，别的都是复用。 */

/* 放料区：虚线框，拖进来会亮（.over） */
.ln-drop{margin-bottom:var(--sp-4)}
.ln-drop-b{display:flex;flex-direction:column;align-items:center;gap:6px;text-align:center;
  padding:26px 18px;border:1px dashed var(--check-line);border-radius:var(--r-sm);
  background:var(--field);transition:border-color var(--h-base) var(--e-out),background-color var(--h-base) var(--e-out)}
.ln-drop.over .ln-drop-b{border-color:var(--blue);background:var(--blue-ring)}
.ln-drop-ic{width:34px;height:34px;border-radius:50%;display:grid;place-items:center;
  font-size:18px;line-height:1;color:var(--blue-d);background:var(--fill-2);margin-bottom:2px}
.ln-drop-b b{font-size:var(--fs-sm);font-weight:560;color:var(--ink1)}
.ln-drop-b>span{font-size:var(--fs-sm);color:var(--ink4)}
.ln-drop-btns{display:flex;gap:var(--sp-2);flex-wrap:wrap;justify-content:center;margin-top:8px}
.ln-drop-b .hintx{margin:8px 0 0;font-size:var(--fs-sm)}

/* 左右两卡：与材料库/写稿同宽比，窄屏落成一列 */
.ln-two{display:grid;grid-template-columns:minmax(0,1.08fr) minmax(0,1fr);gap:var(--sp-4);align-items:start}
.ln-card{display:flex;flex-direction:column;min-width:0}
.ln-card .sl-list{display:flex;flex-direction:column;gap:6px;margin:0 0 var(--sp-3)}

/* 素材表格：沿用 .tblwrap/.tr 的栅格，只把内边距和末列对齐调一下 */
.ln-tbl{padding:0;margin:0 0 var(--sp-3)}
.ln-row{cursor:pointer;position:relative}
/* .sl-del 本来是给 .sl-item 做右上角绝对定位的；放进表格里会全部叠在卡片右上角，
   这里改回正常流，落在末列 */
.ln-row .sl-del{position:static;justify-self:end;padding:2px 4px}
.ln-row .tm{font-size:12px;color:var(--ink4);white-space:nowrap}
.ln-peek{padding:0 0 10px;border-bottom:1px solid var(--line)}
.ln-peek p{margin:0;font-size:var(--fs-xs);line-height:1.75;color:var(--ink2);
  max-height:132px;overflow-y:auto;overscroll-behavior:contain;white-space:pre-wrap}

/* 「学到了什么」摘要条：把格式学习的结果摆出来，不然用户不知道喂进去有什么变化 */
.ln-learn{display:flex;flex-direction:column;gap:2px;padding:10px 12px;margin:0 0 var(--sp-3);
  border-radius:var(--r-sm);background:var(--ok-soft);border:1px solid var(--line-soft)}
.ln-learn b{font-size:var(--fs-xs);font-weight:560;color:var(--ink1)}
.ln-learn span{font-size:var(--fs-xs);color:var(--ink2);line-height:1.6}

/* 开关行：一行一件事，右边一个开关 */
.ln-sw{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);
  padding:10px 0;border-bottom:1px solid var(--line-soft)}
.ln-sw:last-of-type{border-bottom:0}
.ln-sw .g{display:flex;flex-direction:column;gap:2px;min-width:0}
.ln-sw .g b{font-size:var(--fs-sm);font-weight:520;color:var(--ink1)}
.ln-sw .g span{font-size:var(--fs-sm);color:var(--ink4)}
.ln-sw.dis{opacity:.55}
.ln-tg{flex:none;width:38px;height:22px;border-radius:999px;border:1px solid var(--check-line);
  background:var(--fill-2);position:relative;cursor:pointer;transition:background-color var(--h-base) var(--e-out)}
.ln-tg::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;
  background:var(--field);box-shadow:0 1px 2px rgba(0,0,0,.16);transition:transform var(--h-base) var(--e-out)}
.ln-tg.on{background:var(--sel-grad);border-color:transparent}
.ln-tg.on::after{transform:translateX(16px)}
.ln-tg:disabled{cursor:not-allowed}

/* 未开通：不藏功能，讲清为什么用不了 */
.ln-lock-b{padding:6px 0 2px}
.ln-lock-b b{font-size:var(--fs-sm);font-weight:560;color:var(--ink1)}
.ln-lock-b p{margin:var(--sp-2) 0 0;font-size:var(--fs-xs);line-height:1.75;color:var(--ink2)}

/* 学习日志 */
.ln-logc{margin-top:var(--sp-4)}
.ln-log{padding:4px 0 2px}
.ln-log-r{display:flex;gap:var(--sp-3);padding:5px 0;font-size:var(--fs-xs);color:var(--ink2);
  border-bottom:1px solid var(--line-soft)}
.ln-log-r:last-child{border-bottom:0}
.ln-log-r span{flex:none;color:var(--ink4);font-variant-numeric:tabular-nums}

@media (max-width:900px){
  .ln-two{grid-template-columns:minmax(0,1fr)}
  .ln-drop-b{padding:20px 14px}
  .ln-tbl .tr{grid-template-columns:minmax(0,1fr) 76px 64px 52px 34px;gap:8px}
}

/* 写稿页「这一版按什么写的」那一行：默认空着不占位，生成后才有内容 */
.wbasis{display:flex;flex-wrap:wrap;gap:6px;align-items:center;
  margin:0 0 8px;font-size:var(--fs-xs);color:var(--ink4);line-height:1.6}
.wbasis:empty{display:none}
.wbasis i{font-style:normal;color:var(--blue-d);background:var(--brand-50);
  padding:1px 6px;border-radius:var(--r-xs);white-space:nowrap}

/* 进化页「写作质量」：按文种列平均改动率 */
.ln-q{padding:0}
.ln-q .ln-sw{align-items:flex-start}
.ln-q .v{font:600 var(--fs-sm)/1.4 inherit;color:var(--ink1);font-variant-numeric:tabular-nums;white-space:nowrap}
.ln-q .v em{font-style:normal;font-weight:400;color:var(--ink4);margin-left:4px;font-size:var(--fs-xs)}

/* 自有密钥：内置通道可用时默认收起，避免"看着像必须填" */
.ownd{margin:0}
.ownd>summary{cursor:pointer;font-size:var(--fs-sm);color:var(--blue-d);
  padding:9px 0;list-style:none;user-select:none}
.ownd>summary::-webkit-details-marker{display:none}
.ownd>summary::before{content:"＋ ";font-weight:600}
.ownd[open]>summary::before{content:"－ "}
.ownd>summary:hover{text-decoration:underline}

/* 技能包声明的事实字段：自适应两列，窄屏一列 */
.skfacts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:9px;margin-top:10px}
.skfacts[hidden]{display:none}
@media (max-width:768px){.skfacts{grid-template-columns:minmax(0,1fr)}}

/* 事实区状态条：默认收起时只露这一行，告诉用户记了几项、从哪进去改 */
.sk-sum{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:9px 12px;border-radius:var(--r-sm);background:var(--fill);
  font-size:var(--fs-sm);color:var(--ink3);line-height:1.5}
.sk-sum span{min-width:0}
.sk-sum .more{border:0;background:none;padding:0;flex:none;cursor:pointer;
  font:inherit;color:var(--brand-500)}
.sk-sum .more:hover{text-decoration:underline}

/* 事实区标题行：左边说明，右边「一件件问我」。
   窄屏时按钮换到下一行，避免把标题挤成两行。 */
.sk-hd{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:8px}
.sk-hd label{margin:0}
@media (max-width:576px){
  .sk-hd{flex-wrap:wrap;gap:8px}
  .sk-hd .btn{width:100%;justify-content:center}
}

/* 引导问答的进度点：答过的实心，当前的加长 */
.gd-dots{display:flex;gap:6px;align-items:center}

/* 「这条是我猜的」：轻提示，不抢眼但看得出 */
.gd-guess{margin:7px 0 0;font-size:var(--fs-xs);color:var(--warn);line-height:1.5}

/* 要点确认清单：左标题、右内容、最右「改」 */
.gd-list{border-top:1px solid var(--line-soft)}
.gd-row{display:flex;gap:12px;align-items:baseline;
  padding:11px 0;border-bottom:1px solid var(--line-soft)}
.gd-k{flex:none;width:112px;font-size:var(--fs-sm);color:var(--ink3);line-height:1.5}
.gd-v{flex:1;min-width:0;font-size:var(--fs-base);line-height:1.6;word-break:break-word}
.gd-v.miss{color:var(--ink4)}
.gd-row .more{border:0;background:none;padding:0;flex:none;cursor:pointer;
  font:inherit;font-size:var(--fs-sm);color:var(--brand-500)}
.gd-row .more:hover{text-decoration:underline}
@media (max-width:480px){
  .gd-row{flex-wrap:wrap;gap:4px 10px}
  .gd-k{width:auto}
  .gd-v{flex:1 0 100%;order:3}
}

/* 补问时的等待动画：三个点依次亮 */
.gd-wait{display:flex;gap:6px;margin:18px 0 6px}
.gd-wait i{width:7px;height:7px;border-radius:50%;background:var(--ink4);animation:gdw 1.1s infinite}
.gd-wait i:nth-child(2){animation-delay:.16s}
.gd-wait i:nth-child(3){animation-delay:.32s}
@keyframes gdw{0%,60%,100%{opacity:.25}30%{opacity:1}}
/* 三个按钮 + 进度数字：一律允许换行，窄屏自动折成两行，
   不写死媒体查询——弹窗在侧栏、抽屉里宽度会变，靠内容自己决定更稳。 */
.gq-acts{display:flex;flex-wrap:wrap;gap:9px;align-items:center;margin-top:18px}
.gq-acts .btn{flex:none}
.gd-count{margin-left:auto;font-size:var(--fs-xs);color:var(--ink4);flex:none}
.gd-dot{width:7px;height:7px;border-radius:4px;background:rgba(0,0,0,.12);transition:all .2s}
.gd-dot.done{background:var(--sel-b)}
.gd-dot.on{width:20px;background:var(--sel-grad)}

/* ───────── 「正式成文」开关 ─────────
   放在「写什么」卡头右侧。打开＝必须按事实写；关掉＝允许补足细节、不出现〔待定〕。 */
.fmsw{display:inline-flex;align-items:center;gap:7px;flex:none;margin:0;
  padding:0;border:0;background:none;cursor:pointer;font:inherit;color:var(--ink3);
  -webkit-tap-highlight-color:transparent}
.fmsw span{font-size:12px;font-weight:520;white-space:nowrap;letter-spacing:-.01em}
.fmsw.on{color:var(--ink1)}
.fmsw i.sw{pointer-events:none}

/* 「正式成文」整条：开关 + 一句说明。
   2026-10-29 从页头挪到「写什么」卡里，紧跟文种胶囊 —— 先选写什么，再定用什么模式。
   开着用选中态的绿青色（跟开关同色系），关掉退成灰底，一眼能看出当前是哪一档。 */
.fmbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  margin:12px 0 0;padding:9px 12px;border-radius:var(--r-sm);
  border:1px solid var(--line-soft);background:var(--fill);
  transition:background-color var(--h-base) var(--e-out),border-color var(--h-base) var(--e-out)}
.fmbar.on{background:var(--sel-fill);border-color:var(--sel-line)}
.fmbar-tx{flex:1;min-width:0;font-size:var(--fs-xs);line-height:1.5;color:var(--ink2)}

@media (max-width:520px){
  /* 窄屏：放不下就自然换行，说明落到开关下面一行，左对齐 */
  .fmbar{gap:6px 8px;padding:9px 10px}
}

/* 依据行里的提醒标：宽松模式的稿子不能拿去迎检 */
.wbasis i.warn{color:var(--warn);background:var(--warn-soft)}

/* 分工表下面的缺口提示：不拦结果，只把没落到实处的地方摊出来 */
.dc-lint{margin:2px 0 10px;padding:7px 10px;border-radius:var(--r-sm);
  background:var(--warn-soft);color:var(--warn);font-size:var(--fs-xs);line-height:1.6}

/* 一次给两版：A 在上，B 在下，标出"更松一档"，各自可复制、可切换 */
.say-alt,.ask-alt{margin-top:10px;padding-top:10px;border-top:1px dashed var(--line-soft)}
.say-alt .say-h,.ask-alh{display:flex;align-items:center;gap:8px;margin-bottom:6px}
.say-alt .say-h b,.ask-alh b{font-size:var(--fs-xs);font-weight:560;color:var(--ink3)}
.ask-alh{justify-content:space-between}
.ask-alh b{color:var(--ink3)}
.say-alt .dc-out,.ask-alt .dc-out{width:100%}

/* 收起后的那一行：只留「换回另一版」 */
.say-fold,.ask-fold{display:flex;align-items:center;flex-wrap:wrap;gap:6px;border-top:0;margin-top:8px}

/* ───────── 选中改写 ─────────
   选中正文一段 → 就地浮出小条：左边快捷词，右边自己说。
   手机上不浮，改成贴底一条（浮条会跟系统选中菜单打架）。 */
.selbar{position:fixed;z-index:90;display:none;flex-direction:column;gap:7px;
  padding:8px;background:rgba(255,255,255,.96);backdrop-filter:blur(20px);
  -webkit-backdrop-filter:blur(20px);border:1px solid rgba(0,0,0,.08);
  border-radius:var(--r-md);box-shadow:0 18px 44px -22px rgba(35,38,52,.5)}
.selbar.on{display:flex}
.selbar.fixed{left:12px !important;right:12px;bottom:14px;top:auto !important;width:auto !important}
.sb-row{display:flex;gap:6px;flex-wrap:wrap}
.sb-own{flex-wrap:nowrap}
.sb-b{border:1px solid rgba(0,0,0,.1);background:var(--field);border-radius:var(--r-xs);
  padding:5px 10px;font:inherit;font-size:var(--fs-sm);color:var(--ink);cursor:pointer;line-height:1.4}
.sb-b:hover{border-color:var(--sel-line);color:var(--brand-500)}
.sb-in{flex:1;min-width:0;height:30px;border:1px solid rgba(0,0,0,.1);border-radius:var(--r-xs);
  padding:0 9px;font:inherit;font-size:var(--fs-sm);background:var(--field);color:var(--ink)}
.sb-in:focus{outline:none;border-color:var(--blue-ring)}
.sb-go{flex:none;height:30px;padding:0 13px;border:0;border-radius:var(--r-xs);
  background:var(--sel-grad);color:#fff;font:inherit;font-size:var(--fs-sm);cursor:pointer}

/* 左右对比：手机上上下排 */
.cmp{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin:4px 0 2px}
.cmp-c{background:var(--fill);border-radius:var(--r-sm);padding:10px 12px;
  max-height:38vh;overflow:auto}
.cmp-h{font-size:var(--fs-xs);color:var(--ink3);margin-bottom:6px}
.cmp-t{font-size:var(--fs-base);line-height:1.78;white-space:pre-wrap;word-break:break-word}
.cmp-t del{background:rgba(255,59,48,.12);color:#8E3B36;text-decoration:line-through}
.cmp-t ins{background:rgba(52,199,89,.16);color:#1F6B3A;text-decoration:none}
@media (max-width:680px){.cmp{grid-template-columns:1fr}.cmp-c{max-height:26vh}}

/* 撤销条：替换完给 12 秒，够反悔 */
.undobar{position:fixed;left:50%;bottom:22px;z-index:95;display:none;align-items:center;gap:12px;
  padding:10px 12px;border-radius:var(--r-md);background:#232634;color:#fff;
  font-size:var(--fs-sm);box-shadow:0 14px 34px -14px rgba(0,0,0,.55);
  transform:translate(-50%,12px);transition:opacity .2s,transform .2s}
.undobar.on{display:flex;transform:translate(-50%,0)}
.undobar .ub{border:0;border-radius:var(--r-xs);padding:4px 11px;background:rgba(255,255,255,.16);
  color:#fff;font:inherit;cursor:pointer}
.undobar .ub:hover{background:rgba(255,255,255,.26)}
.undobar .ub-x{border:0;background:none;color:rgba(255,255,255,.55);font-size:17px;
  line-height:1;cursor:pointer;padding:0 2px}

/* 正文和要点打架的提示条：跟撤销条同一套，换成提醒色以示区别 */
.undobar.drift{background:#4A2E0A;max-width:80vw}
.undobar.drift span{line-height:1.5}
/* 和撤销条同时出现时错开高度，别叠在一起 */
.undobar.drift{bottom:78px}
@media (max-width:576px){.undobar.drift{bottom:84px;left:50%;right:auto;max-width:92vw}}

/* ───────── 弹窗尺寸与留白（2026-10-31 调整）─────────
   原来的 520px 弹窗里塞两行按钮 + 四个字段，太挤，填起来手累。
   统一放大一档：宽 600，问答专用 660，问答的要点清单 880（宽版）；
   表单控件在弹窗里单独加高到 44px（页面里的不用动），按钮 38px。
   母句写在 .mbox 里，避免把整站输入框都撑大。 */
.mbox{max-width:600px;padding:26px 30px 24px;max-height:88vh;border-radius:22px}
.mbox.wide{max-width:840px}
.mbox.gq{max-width:660px}
.mbox.gq.wide{max-width:880px}

.mbox > h3{font-size:18px;line-height:1.4}
.mbox .hintx{font-size:13px;line-height:1.72}
.mbox .fld{gap:9px}
.mbox .fld > label{font-size:12px;line-height:1.5}
.mbox .inp,.mbox .sel{height:44px;font-size:14.5px;border-radius:11px;padding:0 14px}
.mbox .ta{font-size:14.5px;padding:11px 14px;border-radius:11px}
.mbox .picks{gap:8px;max-height:216px}
.mbox .picks .chip,.mbox .chip{height:36px;padding:0 15px;font-size:14.5px;border-radius:10px}
.mbox .btn.sm{height:38px;font-size:14.5px;padding:0 19px;border-radius:11px}
.mbox .gq-acts{margin-top:22px;gap:10px}
.mbox .gd-row{padding:14px 0;gap:16px}
.mbox .gd-k{width:152px;font-size:13px}
.mbox .gd-v{font-size:14.5px;line-height:1.72}
.mbox .gd-list{max-height:46vh;overflow:auto;overscroll-behavior:contain}
.mbox .gd-dots{gap:8px}
.mbox .gd-guess{font-size:12px;margin-top:9px}
.mbox .gd-wait{margin:22px 0 6px}
.mbox .cmp{gap:14px}
.mbox .cmp-c{padding:12px 14px;max-height:40vh}

/* 进度点也放大一点，跟更高的控件对齐 */
.gd-dot{width:8px;height:8px;border-radius:5px}
.gd-dot.on{width:24px}

/* 平板：两栏仍保留，宽度让给内容 */
@media (max-width:992px){
  .mbox{max-width:560px}
  .mbox.wide{max-width:760px}
  .mbox.gq{max-width:620px}
}

/* 手机：底部抽屉式，控件再加高，保证一屏填得下 */
@media (max-width:768px){
  .mask{padding:10px}
  .mbox{max-width:none;max-height:92vh;padding:22px 18px 20px;border-radius:20px 20px 14px 14px}
  .mbox > h3{font-size:17px}
  .mbox .inp,.mbox .sel{height:46px;font-size:16px}
  .mbox .btn.sm{height:44px;font-size:14.5px;padding:0 16px}
  .mbox .picks .chip,.mbox .chip{height:38px;font-size:14.5px}
  /* 手机上每行改成两行：第一行「标签 …… 改」，第二行整行放内容 */
  .mbox .gd-row{display:grid;grid-template-columns:1fr auto;gap:5px 10px;
    padding:13px 0;align-items:baseline}
  .mbox .gd-k{width:auto}
  .mbox .gd-row .more{grid-column:2;grid-row:1;justify-self:end}
  .mbox .gd-v{grid-column:1 / -1;grid-row:2}
  /* 手机上不再让清单内部滚动（会出现半行被切），交给整个弹窗滚一次 */
  .mbox .gd-list{max-height:none;overflow:visible}
  .mbox .cmp-c{max-height:30vh}
  .mbox .gq-acts{margin-top:18px}
  .mbox .gq-acts .btn{flex:1 1 auto}
}

/* ───────── 尺寸第二稿（老板反馈"整体还是太小，看着吃力"）─────────
   宽度再放一档，字号整体 +2，控件再加高。问答弹窗 800（宽版 1000），
   保证"一屏一问"不用眯眼。 */
.mbox{max-width:640px;padding:30px 34px 28px}
.mbox.wide{max-width:900px}
.mbox.gq{max-width:800px}
.mbox.gq.wide{max-width:1000px}

.mbox > h3{font-size:21px;line-height:1.38}
.mbox .hintx{font-size:14.5px;line-height:1.75}
.mbox .fld{gap:11px}
.mbox .fld > label{font-size:14.5px}
.mbox .inp,.mbox .sel{height:50px;font-size:16px;padding:0 16px;border-radius:12px}
.mbox .ta{font-size:16px;padding:13px 16px;border-radius:12px}
.mbox .picks{gap:9px}
.mbox .picks .chip,.mbox .chip{height:42px;padding:0 18px;font-size:16px}
.mbox .btn.sm{height:44px;font-size:16px;padding:0 22px}
.mbox .gq-acts{margin-top:26px;gap:12px}
.mbox .gd-row{padding:16px 0;gap:18px}
.mbox .gd-k{width:168px;font-size:13px}
.mbox .gd-v{font-size:16px;line-height:1.75}
.mbox .gd-dots{gap:9px}
.gd-dot{width:9px;height:9px;border-radius:5px}
.gd-dot.on{width:28px}

@media (max-width:1100px){
  .mbox.gq{max-width:700px}
  .mbox.gq.wide{max-width:860px}
}

@media (max-width:768px){
  .mbox{padding:24px 18px 22px;max-height:94vh}
  .mbox > h3{font-size:19px}
  .mbox .inp,.mbox .sel{height:50px;font-size:16px}
  .mbox .btn.sm{height:48px;font-size:16px}
  .mbox .picks .chip,.mbox .chip{height:42px;font-size:16px}
  .mbox .fld > label{font-size:13px}
}

/* 宽度改成「跟着屏幕走」而不是死挡在某个像素：
   原来 1100 断点就把问答弹窗压回 700，1366 的笔记本正好落在这一档里，
   于是怎么调都觉得小。现在按视口百分比兜底，大屏才吃到上限。 */
.mbox{max-width:min(660px,72vw)}
.mbox.wide{max-width:min(920px,88vw)}
.mbox.gq{max-width:min(800px,80vw)}
.mbox.gq.wide{max-width:min(1000px,92vw)}
@media (max-width:1100px){
  .mbox.gq{max-width:min(800px,84vw)}
  .mbox.gq.wide{max-width:min(1000px,94vw)}
}

/* 再放一档：问答弹窗 860（84vw 封顶），标题 22。大屏读着不费眼。 */
.mbox.gq{max-width:min(860px,84vw)}
.mbox > h3{font-size:22px}
/* 手机上不要这层比例限制，仍旧占满可用宽度 */
@media (max-width:768px){.mbox.gq,.mbox.gq.wide,.mbox.wide{max-width:none}}

/* ═══ 个人管家（butler.js）═══════════════════════════════════ */
/* 首页常驻卡 */
.bt-bar{margin-bottom:var(--sp-4)}
.bt-barh{display:flex;align-items:center;gap:var(--sp-3)}
.bt-av{flex:0 0 auto;width:34px;height:34px;border-radius:12px;display:flex;align-items:center;justify-content:center;
  background:linear-gradient(135deg,var(--brand-500),var(--brand-600));color:#fff;
  font-size:var(--fs-sm);font-weight:600;box-shadow:var(--sh-1)}
.bt-bt{flex:1;min-width:0}
.bt-bt b{display:block;font-size:var(--fs-base);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bt-bt em{display:block;font-style:normal;font-size:var(--fs-sm);color:var(--fill-2);color:#6F697C;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* 手机窄屏：两颗按钮吃掉 164px，标题块只剩 60–75px。
   原来副标题没有省略规则，会折成三四行把整条撑高、把输入框顶出屏幕。
   这里让它单行省略；再窄一点干脆不显示副标题（它只是介绍，不是功能）。 */
@media (max-width:430px){
  .bt-barh .btn{height:28px;padding:0 8px;font-size:12px}
  .bt-bt em{display:none}
}
.bt-barh .btn{flex:0 0 auto}

/* 对话区（首页卡与浮球弹层共用） */
.bt-hosted{display:flex;flex-direction:column;min-height:0}
#btHome.bt-hosted{margin-top:var(--sp-3);max-height:320px}
/* 首页卡空态：一行引导 + 「上次聊过 N 条」入口。
   只留条数不留内容 —— 别人看屏幕，看不到上次问了什么。 */
.bt-hint{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3);
  padding:var(--sp-2) 2px var(--sp-2);color:#8A8494;font-size:var(--fs-sm);line-height:1.6}
.bt-hint span{min-width:0}
.bt-past{flex:0 0 auto;display:inline-flex;align-items:center;gap:3px;border:0;background:none;padding:0;
  font-size:var(--fs-xs);color:var(--blue);cursor:pointer;white-space:nowrap;
  border-bottom:1px solid transparent;transition:border-color .18s}
.bt-past:hover{border-bottom-color:currentColor}
.bt-list{flex:1;min-height:0;overflow-y:auto;padding:var(--sp-2) 2px;display:flex;flex-direction:column;gap:var(--sp-2)}
/* 竖着排：气泡一行，行动条另起一行落在下面。
   以前是横排，桌面宽屏勉强并得下，手机上一行放不下，气泡被挤窄、行动条被压扁，
   看着像两个不相干的东西 —— 而它其实是「这句话要办的事」。 */
/* flex-shrink:0：.bt-list 是 flex column，不锁的话消息多了会被逐条压扁，
   长气泡（拖入即读的解读）只剩按钮看得见、文字被压成 0 高。 */
.bt-msg{display:flex;flex-direction:column;align-items:flex-start;max-width:88%;flex-shrink:0}
.bt-msg.u{align-self:flex-end;align-items:flex-end}
.bt-msg.a{align-self:flex-start;align-items:flex-start}
.bt-bub{padding:var(--sp-2) var(--sp-3);border-radius:var(--r-md);font-size:var(--fs-base);line-height:1.65;
  white-space:pre-wrap;word-break:break-word}
.bt-msg.u .bt-bub{background:var(--blue-soft);border:1px solid var(--line-soft);border-bottom-right-radius:var(--r-xs)}
.bt-msg.a .bt-bub{background:var(--fill);border:1px solid var(--line-soft);border-bottom-left-radius:var(--r-xs)}
/* 气泡里的链接：管家偶尔给条网址，得让它看着像链接、点得动，别是一串方括号源码 */
.bt-bub .bt-link{color:var(--blue,#3a5199);text-decoration:underline;text-underline-offset:2px;word-break:break-all}
.bt-bub .bt-link:active{opacity:.7}
/* 句子里那个「被指的东西」本身也是链接：「点这个进小二那一页」——手指找的是「小二」两个字。
   白纸黑字里突然出现一个能点的词，比底下一条按钮更容易被看见。 */
.bt-bub .bt-jump{color:var(--blue,#3a5199);font-weight:600;cursor:pointer;
  text-decoration:underline;text-decoration-style:dotted;text-underline-offset:3px;
  -webkit-tap-highlight-color:transparent;transition:background .14s}
.bt-bub .bt-jump:hover{background:var(--blue-soft);border-radius:3px}
.bt-bub .bt-jump:active{opacity:.65}
.bt-bub .bt-jump:focus-visible{outline:2px solid var(--blue-ring);outline-offset:2px;border-radius:3px}
/* 行动确认条 */
.bt-acts{display:flex;flex-direction:column;gap:var(--sp-1);margin-top:var(--sp-1);align-self:stretch}
.bt-act{display:flex;align-items:center;gap:var(--sp-2);padding:var(--sp-1) var(--sp-2);
  border:1px dashed var(--sel-line);border-radius:var(--r-sm);background:var(--sel-fill);
  font-size:var(--fs-sm);line-height:1.5}
.bt-act.ok{color:var(--ink2);border-style:solid}
/* 没找到那条待办：不给她一个点了会改错对象的按钮，就老实说没找到 */
.bt-act.miss{color:var(--ink2);border-style:dashed}
.bt-act.miss em{color:var(--ink4)}
.bt-act span{flex:1;min-width:0}
.bt-act em{font-style:normal;color:#1f7a4d;font-size:var(--fs-sm);flex:0 0 auto}
.bt-act button{flex:0 0 auto;border:1px solid var(--line-soft);background:var(--field);border-radius:var(--r-xs);
  padding:2px var(--sp-2);font-size:var(--fs-sm);cursor:pointer;color:inherit}
.bt-act button:hover{background:var(--fill-2)}
.bt-act .bt-do{color:var(--brand-600);border-color:var(--blue-ring)}
/* 批量清单 / 写稿摘要：主行下面再摊一行小字。批量要她一眼看清会动到哪几条，
   「3 条」这种数字她没法判断有没有误伤，得把标题列出来才算数。 */
.bt-act .bt-sub{display:block;margin-top:2px;font-size:var(--fs-xs);line-height:1.55;color:var(--ink4)}
.bt-act .bt-sub i{display:block;font-style:normal;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* 删除要按两次：上膛后按钮变红，形状也跟着硬一点，别跟平时的「办」长一样 */
.bt-act .bt-do.arm{color:#b4392f;border-color:#e3b2ac;background:#fdf3f2}
.bt-act .bt-do.arm:hover{background:#fbe9e7}
/* 导航类整行可点：手机屏上一小粒按钮根本不好按，整行按下去才算顺手 */
.bt-act.tap{cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background .16s,border-color .16s}
.bt-act.tap:hover{background:var(--fill-2);border-color:var(--blue-ring)}
.bt-act.tap:active{background:var(--fill-2);border-color:var(--blue-ring);transform:scale(.995)}
/* 首页卡里的行动条：卡片本身只有 320px，气泡、行动条、输入框都得塞下，
   所以字号和按钮一起缩小，副行（批量清单那种）直接收起来，条数够了看主行就行。 */
.bt-acts.mini{gap:4px;margin-top:6px}
.bt-acts.mini .bt-act{padding:3px var(--sp-2);gap:6px;font-size:var(--fs-sm);line-height:1.45}
.bt-acts.mini .bt-act .bt-sub{display:none}
.bt-acts.mini .bt-act button{padding:1px 8px;font-size:var(--fs-xs)}
.bt-acts.mini .bt-act em{font-size:var(--fs-xs)}
/* 「还没生效」这句话必须在她看得见的地方，不能只靠气泡里的「点办就改」——
   模型偶尔会自己说「已经改好了」，两句话一撞，她只会以为事情办完了。 */
.bt-need{font-size:var(--fs-xs);line-height:1.5;color:var(--warn-text)}
.bt-more{font-size:var(--fs-xs);line-height:1.6;color:var(--blue);cursor:pointer;padding:0 2px}
.bt-more:hover{text-decoration:underline}
/* 输入行 */
.bt-inrow{display:flex;gap:var(--sp-2);margin-top:var(--sp-2)}
.bt-inp{flex:1;min-width:0;height:42px;padding:0 var(--sp-3);font-size:var(--fs-base);border-radius:var(--r-sm);
  border:1px solid transparent;background:var(--fill);color:inherit;outline:none}
.bt-inp:focus{background:var(--field);border-color:var(--blue-ring)}
.bt-go{flex:0 0 auto;width:42px;height:42px;border-radius:var(--r-sm);border:0;cursor:pointer;
  background:var(--brand-500);color:#fff;display:flex;align-items:center;justify-content:center;box-shadow:var(--sh-1)}
.bt-go:hover{background:var(--brand-600)}
.bt-go:disabled,.bt-inp:disabled{opacity:.5;cursor:default}
/* 正在输入的三个点 */
.bt-dots{display:inline-flex;gap:4px;align-items:center;padding:2px 0}
.bt-dots i{width:5px;height:5px;border-radius:50%;background:var(--fill-2);animation:btDot 1.1s infinite}
.bt-dots i:nth-child(2){animation-delay:.18s}
.bt-dots i:nth-child(3){animation-delay:.36s}
@keyframes btDot{0%,60%,100%{opacity:.3}30%{opacity:1}}

/* 整页对话（#/butler）——手机形态。
   上一版是右下角浮球 + 全屏遮罩弹层：真机上点开就会「卡住」。
   根因是 遮罩锁定 body 滚动 + 88vh 的固定高度 + 点开就自动聚焦输入框这三样叠在一起，
   键盘一弹，输入框被压在键盘底下、头部被顶出屏幕，整页既滑不动又点不动。
   现在改成独立路由页，滚动、键盘避让全交回浏览器，这一整类事故从根上没有了。 */
/* 整页对话：吃掉 .wrap 给「页面」留的底部呼吸空间（桌面 80px / 手机 56px），
   否则一屏会被顶破，输入条就贴不到屏幕底。由 app.js 在 render() 里按路由加类。 */
#view.is-fullbleed{padding-bottom:0}
/* width:100% 是这一版的关键：原来只写 max-width，.bt-page 作为 flex item 的
   width:auto 等于 fit-content，宽度由内容撑开 —— 有消息时 748、清空后空态
   内容窄就缩到 450，同一页两态差 298px，输入条也跟着缩。
   写死 100% 之后宽度只由 max-width 决定，两态必然同宽。 */
.bt-page{display:flex;flex-direction:column;width:100%;max-width:1080px;margin:0 auto;padding-top:var(--sp-3);
  /* 撑满可视区，让输入条真正贴在屏幕底部。
     手机上 .main 已经有 padding-top:var(--nav-h)（顶栏是 fixed 的），所以只减 nav-h；
     桌面 ≥1180 走侧栏、nav 不占高度，直接满屏。dvh 会跟着键盘/地址栏自动变，这正是我们要的。 */
  min-height:calc(100vh - var(--nav-h,0px));
  min-height:calc(100dvh - var(--nav-h,0px))}
@media (min-width:1180px){
  .bt-page{min-height:100vh;min-height:100dvh;padding-bottom:var(--sp-3)}
}
.bt-ph{display:flex;align-items:center;gap:var(--sp-2);padding:0 0 var(--sp-3);
  border-bottom:1px solid var(--line-soft)}
.bt-pht{flex:1;min-width:0}
.bt-pht b{display:block;font-size:var(--fs-md);letter-spacing:-.02em}
.bt-pht em{display:block;font-style:normal;font-size:var(--fs-sm);color:#6F697C;margin-top:2px}
.bt-spring{flex:1}
.bt-mini{border:1px solid var(--line-soft);background:var(--field-2);border-radius:var(--r-xs);
  padding:4px var(--sp-2);font-size:var(--fs-sm);cursor:pointer;color:inherit}
.bt-mini:hover{background:var(--fill-2)}
/* 「开启新会话」：原来那个 42×27 的灰底「清空」贴在页头最右，几乎融进背景，
   找不到是必然的。现在给它 32px 高、白底细边、一个 ＋ 号，hover 变蓝边蓝字 ——
   它是这个页面上唯一的「重置」动作，就该长得像按钮。 */
.bt-new{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 12px;flex:none;
  border:1px solid var(--line-soft);background:var(--field-2);border-radius:999px;
  font-size:var(--fs-sm);font-weight:550;color:var(--ink2);cursor:pointer;
  transition:background .16s ease,border-color .16s ease,color .16s ease}
.bt-new:hover{background:var(--blue-soft,#eef1f9);border-color:var(--blue-ring,#9fb0dd);
  color:var(--blue,#3a5199)}
.bt-new:active{opacity:.8}
.bt-new:focus-visible{outline:2px solid var(--blue-ring,#9fb0dd);outline-offset:2px}
.bt-new svg{flex:none}
.bt-new[hidden]{display:none}
/* 手机上页头要放头像 + 标题 + 副标题 + 按钮，按钮收窄一点；
   文案不换（写两个 span 切换会让读屏念两遍或漏念一遍）。 */
@media (max-width:640px){
  .bt-new{height:30px;padding:0 10px;font-size:var(--fs-xs,11.5px)}
}
/* 对话主体：内容少时撑满一屏，内容多了让整页跟着长——这样滚动永远由浏览器原生接管 */
.bt-page-body{flex:1;min-height:0;display:flex;flex-direction:column}
.bt-page-body .bt-list{flex:1 1 auto;overflow:visible;padding:var(--sp-4) 0 var(--sp-2);gap:var(--sp-3)}
/* 容器放宽到 1080 后，气泡不能继续按 86% 算 —— 那会拉到 900+，中文一行
   超过 60 字，视线要来回横移。给一个 800px 的像素上限，长文读着才顺。 */
.bt-page-body .bt-msg{max-width:min(84%,800px)}
.bt-page-body .bt-bub{font-size:var(--fs-base);padding:10px var(--sp-3)}
/* 输入条贴在底部：sticky 而不是 fixed，键盘弹起时浏览器会自动把它顶上来 */
.bt-page-body .bt-inrow{position:sticky;bottom:0;margin:0;padding:var(--sp-2);
  padding-bottom:calc(var(--sp-2) + env(safe-area-inset-bottom));
  border:1px solid var(--line-soft);border-radius:var(--r-md);background:var(--card);
  -webkit-backdrop-filter:blur(14px) saturate(160%);backdrop-filter:blur(14px) saturate(160%);
  box-shadow:var(--sh-1)}
.bt-page-body .bt-inp{background:var(--field-2);border-color:var(--line-soft)}
/* 空对话时的开场：三句话 + 三个可以直接点的问题 */
/* 空态顶部对齐对话态：.bt-list 的 padding-top 是 --sp-4，开场原来是 --sp-8，
   两态切换时内容起点差 16px，画面会跳一下。收齐到同一个值。 */
.bt-hello{padding:var(--sp-4) 0 var(--sp-4)}
.bt-hello b{font-size:var(--fs-lg);letter-spacing:-.02em}
.bt-hello p{margin:var(--sp-2) 0 var(--sp-5);font-size:var(--fs-base);color:#6F697C;line-height:1.72}
.bt-chips{display:flex;flex-wrap:wrap;gap:var(--sp-2)}
.bt-chip{border:1px solid var(--line-soft);background:var(--field-2);border-radius:999px;
  padding:var(--sp-2) var(--sp-3);font-size:var(--fs-sm);color:inherit;cursor:pointer;
  transition:background .16s ease,border-color .16s ease}
.bt-chip:hover{background:var(--fill);border-color:var(--blue-ring)}
@media (max-width:640px){
  .bt-page{padding-top:var(--sp-2)}
  .bt-hello{padding-top:var(--sp-4)}
  .bt-page-body .bt-msg{max-width:90%}
  #btHome.bt-hosted{max-height:260px}
}

/* ───────── 环境标识：只有测试版才有 ─────────
   正式版刻意不加任何标记（老板要求），打开即是干净界面。
   测试版由 sync-beta.py 在镜像时注入三处「测试版」标签 + 顶部橙条，
   所以 app 目录里没有 envTag 元素，这里只保留样式供测试版使用。 */
.envTag{
  display:inline-block;font-style:normal;font-size:12px;font-weight:500;
  line-height:1.5;padding:1px 6px;border-radius:99px;letter-spacing:.02em;
  white-space:nowrap;vertical-align:1px;margin-left:6px;border:1px solid;
}
.envTag--beta{color:#8A4B06;background:#FDE9C8;border-color:rgba(138,75,6,.3)}
.side-ver .envTag{margin:0 6px 0 0}
/* 窄屏导航很挤：标签只在桌面侧栏显示，手机上靠顶部橙条辨认，
   不然会把右侧「搜索」「全部功能」挤出屏幕。 */
@media (max-width:640px){
  .nav .envTag{display:none}
}
/* 登录页标题旁的环境标签：手机上登录时也能一眼看出是正式还是测试 */
.auth h1 .envTag{font-size:12px;vertical-align:3px}

/* ───────── 测试版视觉（网址带 ?env=beta 时才有）─────────
   全部由 CSS 生成，不改任何 DOM：正式版没有 html[data-env="beta"]，
   下面这些规则一条都不生效，页面长得跟以前一模一样。
   橙条 fixed 占 30px，所以把导航和侧栏一起下移 30px 让开它。 */
html[data-env="beta"] body::before{
  content:"测试版 · 数据只在本机，随便点，改不坏正式数据";
  position:fixed;left:0;right:0;top:0;height:30px;z-index:99999;
  display:flex;align-items:center;justify-content:center;
  background:#EF9F27;color:#3A2400;font-size:12px;font-weight:500;
  letter-spacing:.02em;box-shadow:inset 0 -1px 0 rgba(0,0,0,.10);
  pointer-events:none;
}
html[data-env="beta"] .nav{top:30px}
html[data-env="beta"] .side{top:30px}

html[data-env="beta"] .side-ver::before,
html[data-env="beta"] #navName::after,
html[data-env="beta"] .auth h1::after{
  content:"测试版";display:inline-block;font-style:normal;
  font-size:12px;font-weight:500;line-height:1.5;padding:1px 6px;
  border-radius:99px;letter-spacing:.02em;white-space:nowrap;vertical-align:1px;
  color:#8A4B06;background:#FDE9C8;border:1px solid rgba(138,75,6,.3);
}
html[data-env="beta"] .side-ver::before{margin:0 6px 0 0}
html[data-env="beta"] #navName::after,
html[data-env="beta"] .auth h1::after{margin-left:6px}
/* 窄屏导航太挤：标签收起来，靠顶部橙条辨认 */
@media (max-width:640px){
  html[data-env="beta"] #navName::after{display:none}
}

/* ───────── 沟通页三层整合：预演 / 记录 / 人物（flag comm-poju）─────────
   破局并入沟通页后的样式。全部用主站令牌，不引第二套配色。 */
.ctabs{display:flex;gap:2px;margin:0 0 var(--sp-4);border-bottom:1px solid var(--line-soft)}
.ctab{appearance:none;border:0;background:none;font:inherit;font-size:14.5px;color:var(--ink3);padding:9px 14px 10px;cursor:pointer;position:relative}
.ctab:hover{color:var(--ink2)}
.ctab.on{color:var(--ink);font-weight:600}
.ctab.on::after{content:'';position:absolute;left:12px;right:12px;bottom:-1px;height:2px;background:var(--brand-500);border-radius:2px}
/* 2026-11-09 返工：字号抬到 14.5px 后，390 宽排不下三颗标签，flex 会把每颗压窄，
   文字竖排成「记/录」，「→ Copilot」在箭头处断行。改成不折行 + 横向滚动，
   不缩字号。active 下划线从 -1px 提到 0 —— overflow 会把它一起裁掉。 */
@media (max-width:640px){
  .ctabs{overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-webkit-overflow-scrolling:touch}
  .ctabs::-webkit-scrollbar{display:none}
  .ctab{flex:0 0 auto;white-space:nowrap}
  .ctab.on::after{bottom:0}
}
.pj-form{display:flex;flex-direction:column;gap:12px}
.pj-loading{color:var(--ink3);font-size:14.5px;line-height:1.8}
.pj-err{color:#C7362C;font-size:13px;line-height:1.7}
.pj-judge{font-size:14.5px;line-height:1.9}
.pj-reply{margin-top:10px;padding:10px 14px;background:var(--brand-50);border-radius:var(--r-sm);font-size:14.5px;line-height:1.8}
.pj-cite{margin-top:10px;font-size:12px;color:var(--ink3)}
.pj-lbl{font-size:12px;color:var(--ink3);letter-spacing:.06em;margin-bottom:8px}
.pj-lbl2{font-size:12px;color:var(--ink3);letter-spacing:.06em;margin:16px 0 8px}
.deep-block{font-size:14.5px}
.reading{padding:10px 0;border-top:1px solid var(--line-soft)}
.reading:first-of-type{border-top:0;padding-top:0}
.r-t{font-size:14.5px;line-height:1.8}
.r-c{margin-top:4px;font-size:13px;color:var(--ink3);line-height:1.8}
.r-c b{color:var(--ink2);font-weight:600}
.two-say{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.say-v{background:var(--fill);border-radius:var(--r-sm);padding:10px 12px;font-size:13px;line-height:1.8}
.say-v b{display:block;font-size:12px;color:var(--ink3);margin-bottom:4px;letter-spacing:.05em}
.chk-list{margin:0;padding-left:18px;font-size:13px;line-height:1.9;color:var(--ink2)}
.tg{display:inline-block;font-size:12px;padding:0 6px;height:17px;line-height:17px;border-radius:4px;vertical-align:1px;margin:0 2px}
.tg-fact{background:var(--ok-soft);color:#1E7C35}
.tg-guess{background:var(--fill-2);color:var(--ink3)}
.pj-hist{display:flex;flex-direction:column}
.pj-hrow{display:flex;align-items:baseline;gap:10px;padding:9px 0;border-top:1px solid var(--line-soft)}
.pj-hrow:first-child{border-top:0;padding-top:0}
.pj-ht{font-size:12px;color:var(--ink3);flex:0 0 auto}
.pj-hrow b{font-size:13px;flex:0 0 auto}
.pj-hrow p{margin:0;font-size:13px;color:var(--ink2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pp-card{border-top:1px solid var(--line-soft);padding:14px 0}
.pp-card:first-child{border-top:0;padding-top:0}
.pp-head{display:flex;align-items:baseline;gap:8px;margin-bottom:8px}
.pp-head b{font-size:16px}
.pp-head span{font-size:12px;color:var(--ink3)}
.pp-dim{font-size:13px;line-height:1.8;margin-top:6px}
.pp-dim b{display:inline-block;font-size:12px;color:var(--ink3);margin-right:8px}
.pp-notes{margin-top:10px}
.pp-notes p{margin:4px 0 0;font-size:13px;color:var(--ink2)}
.pp-notes span{color:var(--ink3);margin-right:8px;font-size:12px}
.pp-note-row{display:flex;gap:8px;margin-top:10px}
.pp-note-row .inp{flex:1}
.pp-up{margin-left:auto}
.pp-fb{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:4px 0 2px 0;padding-left:2px;font-size:12px;color:var(--ink3)}
.pp-fb .inp{flex:1;min-width:120px;height:32px;font-size:13px}
.pp-fb.ok{color:#1E7C35}
.pp-fb .btn{height:32px;padding:0 12px;font-size:13px}
@media (max-width:640px){
  .two-say{grid-template-columns:1fr}
}

/* ── 管家附件：图片 / 文件 / 拖拽（2026-11-06）──────────────────────── */
.bt-att-list{display:none;gap:6px;flex-wrap:wrap;padding:6px 2px 0}
.bt-att-list.on{display:flex}
.bt-att-opt{width:100%;display:flex;align-items:center;gap:6px;font-size:12px;color:var(--ink3,#6b6f7a);cursor:pointer;padding:2px 0}
.bt-att-opt input{width:13px;height:13px;margin:0;accent-color:var(--blue,#3a5199)}
.bt-att{display:inline-flex;align-items:center;gap:6px;max-width:100%;padding:4px 6px;border:1px solid var(--line-soft,#dfe3ec);border-radius:8px;background:var(--field,#fff);font-size:12px;color:var(--ink2,#3c4150)}
.bt-att.err{border-color:#c55}
.bt-att img{width:26px;height:26px;object-fit:cover;border-radius:5px;flex:none}
.bt-att-ic{width:26px;height:26px;border-radius:5px;background:var(--line-soft,#dfe3ec);flex:none}
.bt-att-n{display:flex;flex-direction:column;min-width:0;max-width:150px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.bt-att-n em{font-style:normal;color:var(--ink4,#9aa0ad);font-size:12px}
.bt-att-x{border:0;background:transparent;color:var(--ink4,#9aa0ad);cursor:pointer;font-size:14.5px;line-height:1;padding:2px 3px;flex:none}
.bt-att-btn{width:34px;height:42px;flex:none;border:1px solid var(--line-soft,#dfe3ec);border-radius:var(--r-sm,8px);background:var(--field,#fff);color:var(--ink2,#3c4150);font-size:17px;line-height:1;cursor:pointer}
.bt-att-btn:hover:not(:disabled){border-color:var(--blue,#3a5199);color:var(--blue,#3a5199)}
.bt-att-btn:disabled{opacity:.5;cursor:default}
textarea.bt-inp.bt-ta{height:auto;min-height:52px;padding:10px var(--sp-3,12px);line-height:1.5;resize:none;font-family:inherit}
.bt-drop-on{outline:2px dashed var(--blue,#3a5199);outline-offset:-4px;border-radius:var(--r-sm,8px);position:relative}
.bt-drop-on::after{content:'松手上传 · 图片 / Word / PDF / TXT';position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background:var(--blue,#3a5199);color:#fff;font-size:12px;padding:7px 14px;border-radius:8px;pointer-events:none;z-index:9;white-space:nowrap}
@media (max-width:640px){.bt-att-btn{width:30px;height:38px}}

/* ── Copilot 工作台（2026-11-06）──────────────────────────────────── */
.cp-tabs{display:flex;gap:18px;border-bottom:1px solid var(--line-soft,#e3e6ee);margin:0 0 14px}
.cp-tabs a{padding:8px 2px;font-size:13px;color:var(--ink3,#6b6f7a);text-decoration:none;border-bottom:2px solid transparent}
.cp-tabs a.on{color:var(--blue,#3a5199);border-bottom-color:var(--blue,#3a5199)}
.cp-ctx{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin-bottom:12px}
.cp-ctx label{display:flex;flex-direction:column;gap:4px;font-size:12px;color:var(--ink3,#6b6f7a)}
.cp-ctx input{height:34px;padding:0 10px;border:1px solid var(--line-soft,#dfe3ec);border-radius:8px;background:var(--field,#fff);font-size:12px;color:var(--ink2,#3c4150)}
.cp-steps-nav{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;margin-bottom:14px}
.cp-steps-nav a{display:flex;flex-direction:column;gap:2px;padding:10px 12px;border:1px solid var(--line-soft,#e3e6ee);border-radius:10px;text-decoration:none;background:var(--field,#fff)}
.cp-steps-nav a.on{border-color:var(--blue,#3a5199);background:var(--color-background-info,#eef3fc)}
.cp-steps-nav b{font-size:13px;color:var(--ink2,#3c4150)}
.cp-steps-nav em{font-style:normal;font-size:12px;color:var(--ink4,#9aa0ad)}
.cp-dispatch,.cp-pane{padding:16px 18px;margin-bottom:14px}
.cp-dispatch>b,.cp-pane>b{font-size:14.5px;color:var(--ink2,#3c4150)}
.cp-dispatch p,.cp-pane p{font-size:12px;color:var(--ink3,#6b6f7a);line-height:1.7;margin:6px 0 10px}
.cp-dispatch textarea{width:100%;min-height:64px;padding:10px 12px;border:1px solid var(--line-soft,#dfe3ec);border-radius:10px;background:var(--field,#fff);font-family:inherit;font-size:13px;resize:vertical;color:var(--ink2,#3c4150)}
.cp-dispatch-f{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:10px}
.cp-dispatch-f span{font-size:12px;color:var(--ink4,#9aa0ad)}
.cp-auto{display:flex;align-items:center;gap:6px;margin-top:10px;font-size:12px;color:var(--ink3,#6b6f7a)}
.cp-ask-bar{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:10px;font-size:12px;color:var(--ink3,#6b6f7a)}
.cp-chat{height:420px;display:flex;flex-direction:column}
.cp-chat .bt-list{flex:1;min-height:0}
.cp-task{padding:14px 18px;margin-bottom:14px}
.cp-task-h{display:flex;align-items:center;justify-content:space-between;padding-bottom:10px;border-bottom:1px solid var(--line-soft,#e3e6ee)}
.cp-task-h b{font-size:14.5px}.cp-task-h span{font-size:12px;color:var(--blue,#3a5199)}
.cp-step{display:flex;gap:10px;padding:10px 0;border-bottom:1px solid var(--line-soft,#eef0f5)}
.cp-step>i{width:9px;height:9px;border-radius:50%;background:var(--line-soft,#dfe3ec);margin-top:5px;flex:none}
.cp-step.ok>i{background:#3a5199}.cp-step.busy>i,.cp-step.warn>i{background:#BA7517}
.cp-step b{font-size:13px;color:var(--ink2,#3c4150)}
.cp-step em{font-style:normal;font-size:12px;color:var(--ink4,#9aa0ad);margin-left:8px}
.cp-step p{margin:4px 0 0;font-size:12px;line-height:1.6;color:var(--ink3,#6b6f7a);white-space:pre-wrap}
.cp-confirm{padding:10px 0;display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.cp-confirm>b{width:100%;font-size:12px;color:var(--ink3,#6b6f7a)}
.cp-obs{display:flex;align-items:center;gap:10px;font-size:12px;color:var(--ink3,#6b6f7a)}
.cp-task-f{display:flex;align-items:center;justify-content:space-between;gap:12px;padding-top:10px;font-size:12px;color:var(--ink3,#6b6f7a)}
.cp-out{padding:14px 18px}
.cp-out-row{position:relative;display:grid;grid-template-columns:auto auto 1fr;gap:10px;align-items:center;padding:7px 26px 7px 0;border-bottom:1px solid var(--line-soft,#eef0f5);font-size:12px}
/* 行尾删除键（2026-11-07 老板批）：平时半透明不抢视线，删的时候配合长按确认弹窗 */
.cp-out-del{position:absolute;top:5px;right:0;width:22px;height:22px;border:0;border-radius:50%;background:transparent;color:var(--ink4,#9aa0ad);font-size:14px;line-height:20px;padding:0;cursor:pointer;opacity:.4;transition:opacity var(--h-fast,140ms) ease}
.cp-out-del:hover,.cp-out-del:focus-visible{opacity:1;color:var(--red-text,#C7362C);background:var(--red-soft,rgba(255,59,48,.08))}
.cp-out-del:focus-visible{outline:2px solid var(--red-text,#C7362C);outline-offset:1px}
.cp-out-row span{color:var(--blue,#3a5199)}.cp-out-row em{font-style:normal;color:var(--ink4,#9aa0ad)}
.cp-out-row p{margin:0;color:var(--ink3,#6b6f7a);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cp-people{display:flex;flex-wrap:wrap;gap:8px;margin:10px 0}
.cp-person{padding:8px 12px;border:1px solid var(--line-soft,#dfe3ec);border-radius:9px;background:var(--field,#fff);font-size:12px;cursor:pointer;color:var(--ink2,#3c4150)}
.cp-person em{display:block;font-style:normal;font-size:12px;color:var(--ink4,#9aa0ad);margin-top:2px}
.cp-person-d{margin-top:12px;padding-top:12px;border-top:1px solid var(--line-soft,#e3e6ee)}
.cp-person-d p{font-size:12px;color:var(--ink3,#6b6f7a);margin:6px 0}
.cp-person-d p span{display:inline-block;width:70px;color:var(--ink4,#9aa0ad)}
.cp-lock{color:#a05a20!important}
@media (max-width:640px){
  .cp-ctx,.cp-steps-nav{grid-template-columns:repeat(2,minmax(0,1fr))}
  .cp-chat{height:340px}
  .cp-dispatch-f{flex-direction:column;align-items:stretch}
}
.cp-more{margin-top:4px}
.cp-more summary{font-size:12px;color:var(--blue,#3a5199);cursor:pointer}
.cp-more pre{max-height:220px;overflow:auto;padding:8px 10px;margin:6px 0 0;background:var(--color-background-secondary,#f5f6fa);border-radius:8px;font-size:12px;line-height:1.6;white-space:pre-wrap;word-break:break-all;color:var(--ink3,#6b6f7a)}
/* 档案·人：建档表单、四维确认、记一笔。只用发丝线分层，不叠卡片。 */
.cp-pane-tools{display:flex;align-items:center;gap:10px;margin:10px 0}
.cp-pane-tools span{font-size:12px;color:var(--ink4,#9aa0ad)}
/* 档案页「＋ 新建档」：贴右，只做发丝线按钮，不抢关系图的视线 */
.cp-pane-tools .btn{margin-left:auto;flex:none}
.cp-new-foot{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.cp-new-foot .cp-empty{flex:1;min-width:180px;line-height:1.6}
/* 定时任务卡（2026-11-10 老板批）：说人话建任务 + 列表管理，行样式复用设置页 setrow */
/* ═══ 定时任务管理界面（2026-11-10 照老板给的 WorkBuddy 参照图重做）═══════
   2026-11-10 主题统一：不再自带一套孤立的深色。浅色（默认）全部引用网页现役
   「破局」皮肤变量；深色是同一套设计语言的反相（同一钢靛强调色、同一灰阶层级、
   同一圆角/阴影/发丝线 token），html[data-theme="dark"] 或面板加 .td-dark 即生效。
   本次只改样式：DOM 结构、文案、事件、接口一律不动。 */
:root{
  /* 浅色：配色 / 背景 / 文字 / 边框 / 控件状态，与整页同源 */
  --td-panel:var(--card);
  --td-panel-edge:var(--edge);
  --td-card:var(--field-2);
  --td-card-edge:var(--line-soft);
  --td-ink:var(--ink);
  --td-ink2:var(--ink2);
  --td-ink3:var(--ink3);
  --td-ink4:var(--ink4);
  --td-line:var(--line);
  --td-hair:var(--hairline);
  --td-fill:var(--fill);
  --td-fill-2:var(--fill-2);
  --td-on:var(--blue);
  --td-on-soft:var(--blue-soft);
  --td-on-ring:var(--blue-ring);
  --td-red:var(--red);
  --td-pri:var(--ink);
  --td-pri-ink:#fff;
  --td-shadow:var(--sh-1);
  --td-scheme:light;
}
/* 深色：只覆盖 --td-*，页面其它区块不受影响；取值与浅色一一对应 */
:root[data-theme="dark"],.td-dark,.mbox.td-modal.td-dark{
  --td-panel:rgba(30,35,47,.9);
  --td-panel-edge:rgba(255,255,255,.13);
  --td-card:rgba(45,52,67,.82);
  --td-card-edge:rgba(255,255,255,.09);
  --td-ink:#eef1f6;
  --td-ink2:#c6cddb;
  --td-ink3:#a7b0c0;
  --td-ink4:#8f99ab;
  --td-line:rgba(255,255,255,.15);
  --td-hair:rgba(255,255,255,.09);
  --td-fill:rgba(255,255,255,.055);
  --td-fill-2:rgba(255,255,255,.1);
  --td-on:#7fb4dc;
  --td-on-soft:rgba(127,180,220,.15);
  --td-on-ring:rgba(127,180,220,.5);
  --td-red:#e2938a;
  --td-pri:#7fb4dc;
  --td-pri-ink:#171c26;
  --td-shadow:0 2px 4px rgba(0,0,0,.18),0 24px 48px -28px rgba(0,0,0,.6);
  --td-scheme:dark;
}
.cp-tasks{padding:0;margin:0 0 var(--sp-4);background:none;border:0;box-shadow:none;border-radius:0}
.cp-tasks > .hintx{padding:var(--sp-4);color:var(--ink4)}
.tdp{
  background:var(--td-panel);color:var(--td-ink);
  border:1px solid var(--td-panel-edge);border-radius:var(--r-md);
  box-shadow:var(--td-shadow);
  -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
  padding:var(--sp-3) var(--sp-4) var(--sp-4);
  font-family:inherit;box-sizing:border-box;color-scheme:var(--td-scheme)
}
.tdp *{box-sizing:border-box}
.tdp button{font-family:inherit;cursor:pointer}
.tdp-head{display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap}
.tdp-tabs{display:flex;gap:var(--sp-4)}
.tdp-tabs button{border:0;background:none;color:var(--td-ink3);font-size:var(--fs-base);padding:2px 0 6px;position:relative;font-weight:600}
.tdp-tabs button:hover{color:var(--td-ink2)}
.tdp-tabs button.on{color:var(--td-ink)}
.tdp-tabs button.on::after{content:'';position:absolute;left:0;right:0;bottom:0;height:2px;background:var(--td-on);border-radius:2px}
.tdp-tools{margin-left:auto;display:flex;gap:var(--sp-2);align-items:center}
.tdp-ghost,.tdp-new{border:1px solid var(--td-line);background:var(--td-fill);color:var(--td-ink2);font-size:var(--fs-sm);padding:5px 10px;border-radius:var(--r-sm);white-space:nowrap;transition:background .15s,border-color .15s}
.tdp-ghost:hover{background:var(--td-fill-2);color:var(--td-ink)}
.tdp-ghost.on{color:var(--td-on);border-color:var(--td-on);background:var(--td-on-soft)}
.tdp-new{background:var(--td-pri);color:var(--td-pri-ink);border-color:transparent;font-weight:600}
.tdp-new:hover{filter:brightness(1.12)}
.tdp-new span{opacity:.5;font-size:var(--fs-xs)}
.tdp-filters{display:flex;gap:var(--sp-1);align-items:center;margin:var(--sp-2) 0 var(--sp-3);flex-wrap:wrap}
.tdp-f{border:0;background:none;color:var(--td-ink3);font-size:var(--fs-sm);padding:4px 9px;border-radius:var(--r-xs)}
.tdp-f em{font-style:normal;opacity:.75}
.tdp-f:hover{background:var(--td-fill);color:var(--td-ink2)}
.tdp-f.on{background:var(--td-on-soft);color:var(--td-on);box-shadow:inset 0 0 0 1px var(--td-on-ring)}
.tdp-right{margin-left:auto}
.tdp-bulkbar{display:flex;gap:var(--sp-2);align-items:center;background:var(--td-fill);border:1px solid var(--td-line);border-radius:var(--r-sm);padding:6px 10px;margin-bottom:var(--sp-2);font-size:var(--fs-sm);color:var(--td-ink3)}
.tdp-bulkbar b{color:var(--td-on)}
.tdp-bulkbar button{border:1px solid var(--td-line);background:var(--td-card);color:var(--td-ink2);font-size:var(--fs-sm);padding:3px 9px;border-radius:var(--r-xs)}
.tdp-bulkbar button:hover{border-color:var(--td-on);color:var(--td-on)}
.tdp-bulkbar button:last-child{color:var(--td-red)}
/* 桌面固定 5 列，minmax(0,1fr) 保证每张卡等宽、同高、对齐整齐 */
.tdp-grid{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:var(--sp-2);align-items:stretch}
.tdp-card{background:var(--td-card);border:1px solid var(--td-card-edge);border-radius:var(--r-sm);padding:var(--sp-2) 9px 7px;min-height:92px;display:flex;flex-direction:column;transition:border-color .15s,opacity .15s,box-shadow .15s}
.tdp-card:hover{border-color:var(--td-on-ring);box-shadow:var(--sh-1)}
.tdp-card.off{opacity:.58}
.tdp-card-top{display:flex;align-items:flex-start;gap:6px;min-height:32px}
.tdp-name{flex:1;min-width:0;font-size:var(--fs-sm);font-weight:600;line-height:1.35;color:var(--td-ink);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}
.tdp-ops{display:none;gap:1px;flex:none}
.tdp-card:hover .tdp-ops{display:flex}
.tdp-ops button{border:0;background:none;color:var(--td-ink4);font-size:var(--fs-sm);padding:1px 3px;border-radius:var(--r-xs);line-height:1}
.tdp-ops button:hover{background:var(--td-fill-2);color:var(--td-ink)}
.tdp-ops button.tdp-del:hover{color:var(--td-red)}
.tdp-sw{flex:none;width:28px;height:16px;border-radius:99px;border:0;padding:0;position:relative;background:var(--check-line);transition:background .15s}
.tdp-sw::after{content:'';position:absolute;top:2px;left:2px;width:12px;height:12px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(35,38,52,.25);transition:left .15s}
.tdp-sw.on{background:var(--td-on)}
.tdp-sw.on::after{left:14px}
.tdp-desc{margin:5px 0 7px;font-size:var(--fs-xs);line-height:1.45;color:var(--td-ink2);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;min-height:30px;overflow-wrap:anywhere}
.tdp-foot{margin-top:auto;border-top:1px solid var(--td-hair);padding-top:5px;display:flex;justify-content:space-between;gap:4px;font-size:var(--fs-xs);color:var(--td-ink3)}
.tdp-foot > span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tdp-state{white-space:nowrap;flex:none}
.tdp-state.tdp-dim{opacity:.75}
.tdp-empty{padding:var(--sp-5) var(--sp-2);text-align:center;color:var(--td-ink4);font-size:var(--fs-sm)}
.tdp-chk{flex:none;width:14px;height:14px;margin-top:1px}
.tdp-chk input{width:14px;height:14px;accent-color:var(--td-on);cursor:pointer}
.tdp-runlist{display:flex;flex-direction:column;gap:1px}
.tdp-run{display:grid;grid-template-columns:92px 1fr auto;gap:4px var(--sp-3);align-items:baseline;padding:8px 4px;border-bottom:1px solid var(--td-hair);font-size:var(--fs-sm)}
.tdp-run-at{color:var(--td-ink4);font-variant-numeric:tabular-nums}
.tdp-run b{color:var(--td-ink);font-weight:600}
.tdp-run-ch{color:var(--td-ink3);font-size:var(--fs-xs)}
.tdp-run p{grid-column:2 / -1;margin:2px 0 0;color:var(--td-ink4);font-size:var(--fs-xs);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* 只用设计规范登记的 4 个断点降级，桌面始终 5 列 */
@media (max-width:1180px){.tdp-grid{grid-template-columns:repeat(4,minmax(0,1fr))}}
@media (max-width:992px){.tdp-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:768px){.tdp-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:576px){
  .tdp{padding:var(--sp-3)}
  .tdp-grid{grid-template-columns:1fr}
  .tdp-tools{margin-left:0;width:100%}
  .tdp-run{grid-template-columns:80px 1fr}
  .tdp-run-ch{grid-column:2}
}
/* 新建/编辑弹窗：沿用站内 .mbox 的白雾玻璃，只有控件颜色走 --td-* */
.mbox.td-modal{
  background:var(--td-panel);color:var(--td-ink);color-scheme:var(--td-scheme);
  border:1px solid var(--td-panel-edge);box-shadow:var(--sh-2);
  max-width:780px;padding:var(--sp-4) var(--sp-5);border-radius:var(--r-lg)
}
.mbox.td-modal *{box-sizing:border-box}
.mbox.td-modal h3{display:flex;align-items:center;color:var(--td-ink);font-size:var(--fs-md);font-weight:600;margin:0 0 var(--sp-4)}
.tdm-x{margin-left:auto;border:0;background:none;color:var(--td-ink4);font-size:var(--fs-lg);line-height:1;padding:2px 4px}
.tdm-x:hover{color:var(--td-ink)}
.tdm-name{width:100%;height:38px;background:var(--td-fill);border:1px solid var(--td-line);border-radius:var(--r-sm);
  color:var(--td-ink);font-size:var(--fs-sm);padding:0 12px;outline:none;font-family:inherit}
.tdm-name::placeholder{color:var(--td-ink4)}
.tdm-name:focus{border-color:var(--td-on);box-shadow:0 0 0 3px var(--td-on-soft)}
.tdm-body{margin-top:var(--sp-3);background:var(--td-card);border:1px solid var(--td-line);border-radius:var(--r-sm);padding:0}
.tdm-prompt{display:block;width:100%;min-height:112px;resize:vertical;background:transparent;border:0;
  color:var(--td-ink);font-size:var(--fs-sm);line-height:1.6;padding:14px 14px 6px;outline:none;font-family:inherit}
.tdm-prompt::placeholder{color:var(--td-ink4)}
.tdm-body-bar{display:flex;align-items:center;gap:var(--sp-2);padding:0 12px 10px}
.tdm-plus,.tdm-quick{border:0;background:none;color:var(--td-ink3);font-size:var(--fs-sm);padding:3px 6px;border-radius:var(--r-xs)}
.tdm-plus{font-size:var(--fs-lg);line-height:1}
.tdm-plus:hover,.tdm-quick:hover{background:var(--td-fill-2);color:var(--td-ink)}
.tdm-quick{margin-left:auto}
.tdm-quick span{font-size:var(--fs-xs);opacity:.6}
.tdm-tpls{display:flex;flex-direction:column;gap:1px;padding:0 8px 8px}
.tdm-tpls button{text-align:left;border:0;background:var(--td-fill);color:var(--td-ink3);font-size:var(--fs-sm);padding:7px 10px;border-radius:var(--r-xs)}
.tdm-tpls button:hover{background:var(--td-on-soft);color:var(--td-on)}
.tdm-chips{display:flex;gap:10px;flex-wrap:wrap;border-top:1px solid var(--td-hair);padding:8px 12px}
.tdm-chip{display:inline-flex;align-items:center;gap:5px;font-size:var(--fs-sm);color:var(--td-ink3)}
.tdm-chip > span{font-size:var(--fs-xs);opacity:.6}
.tdm-chip-red{color:var(--td-red)}
.tdm-sel{border:0;background:transparent;color:inherit;font-size:var(--fs-sm);outline:none;font-family:inherit;
  appearance:none;-webkit-appearance:none;padding:2px 0;cursor:pointer}
.tdm-sel option{background:var(--td-card);color:var(--td-ink)}
.tdm-row3{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--sp-2);margin-top:var(--sp-3)}
.tdm-drop{display:flex;align-items:center;gap:5px;min-width:0;background:var(--td-fill);border:1px solid var(--td-line);
  border-radius:var(--r-sm);padding:0 10px;height:38px;font-size:var(--fs-sm);color:var(--td-ink)}
.tdm-drop:focus-within{border-color:var(--td-on);box-shadow:0 0 0 3px var(--td-on-soft)}
.tdm-drop > span{color:var(--td-ink3);flex:none}
.tdm-drop select,.tdm-drop input{flex:1;min-width:0;border:0;background:transparent;color:var(--td-ink);
  font-size:var(--fs-sm);outline:none;font-family:inherit;appearance:none;-webkit-appearance:none;height:100%}
.tdm-drop select option{background:var(--td-card);color:var(--td-ink)}
.tdm-drop i{font-style:normal;font-size:var(--fs-xs);color:var(--td-ink4)}
.tdm-drop input[type=time],.tdm-drop input[type=date]{color-scheme:var(--td-scheme)}
.tdm-extra{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin-top:10px;font-size:var(--fs-sm);color:var(--td-ink3)}
.tdm-extra > span{color:var(--td-ink4)}
.tdm-extra label{display:inline-flex;align-items:center;gap:3px;cursor:pointer}
.tdm-extra input[type=number],.tdm-extra input[type=date]{background:var(--td-fill);border:1px solid var(--td-line);
  border-radius:var(--r-xs);color:var(--td-ink);font-size:var(--fs-sm);padding:5px 8px;font-family:inherit;color-scheme:var(--td-scheme)}
.tdm-wecom{display:flex;align-items:center;gap:10px;margin-top:var(--sp-3);font-size:var(--fs-sm);color:var(--td-ink3)}
.tdm-foot{display:flex;justify-content:flex-end;gap:9px;margin-top:var(--sp-5)}
.tdm-btn{border:1px solid var(--td-line);background:var(--td-fill);color:var(--td-ink2);font-size:var(--fs-sm);
  padding:8px 20px;border-radius:var(--r-sm);font-family:inherit;cursor:pointer}
.tdm-btn:hover{background:var(--td-fill-2);color:var(--td-ink)}
.tdm-btn.pri{background:var(--td-pri);color:var(--td-pri-ink);border-color:transparent}
.tdm-btn.pri:hover{filter:brightness(1.12)}
.tdm-btn.pri:disabled{opacity:.45;cursor:not-allowed;filter:none}
@media (max-width:576px){
  .mbox.td-modal{padding:var(--sp-4)}
  .tdm-row3{grid-template-columns:1fr}
}

.cp-quick{display:flex;gap:8px;margin:10px 0 4px}
.cp-quick input{flex:1;min-width:0;padding:8px 10px;border:1px solid var(--line-soft,#dfe3ec);border-radius:9px;background:var(--field,#fff);font-size:12px;color:var(--ink2,#3c4150)}
.cp-quick input:focus{outline:none;border-color:var(--blue,#3a5199)}
.cp-quick-hint{margin:2px 0 8px;font-size:11px;color:var(--ink4,#9aa0ad)}
.cp-tk-foot{display:flex;gap:8px;margin-top:10px;padding-top:10px;border-top:1px solid var(--line-soft,#eef0f5)}
.cp-tasks .setrow{padding-left:0;padding-right:0}
.cp-new-form label b{color:#c0392b;font-weight:600}
.cp-people-empty{display:flex;flex-direction:column;align-items:center;gap:8px;padding:18px 0 6px}
.cp-people-empty .btn{margin-top:2px}
/* 待确认：草稿区。跟档案区用发丝线隔开，不另起卡片。 */
.cp-wait{margin:14px 0 2px;padding-top:12px;border-top:1px solid var(--line-soft,#e3e6ee)}
.cp-wait>b{font-size:12px;color:var(--ink2,#3c4150)}
.cp-wait>p{font-size:12px;line-height:1.6;color:var(--ink4,#9aa0ad);margin:4px 0 2px}
.cp-wait-card{padding:12px 0 10px;border-bottom:1px solid var(--line-soft,#eef0f5)}
.cp-wait-h{display:flex;align-items:baseline;gap:8px;margin-bottom:2px}
.cp-wait-h b{font-size:13px;color:var(--ink2,#3c4150)}
.cp-wait-h em{font-style:normal;font-size:12px;color:var(--ink4,#9aa0ad)}
.cp-badge{font-style:normal;font-size:12px;padding:1px 6px;border-radius:5px;
  color:#a05a20;border:1px solid #e8c9a8;background:#fdf4ea;margin-left:auto}
.cp-wait-tip{font-size:12px;color:#a05a20;margin:6px 0 0}
.cp-wait-foot{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:10px}
.cp-wait-del{margin-top:6px}
.cp-linkbtn{background:none;border:0;padding:0;font:inherit;font-size:12px;color:var(--ink4,#9aa0ad);
  cursor:pointer;text-decoration:underline;text-underline-offset:2px}
.cp-linkbtn:hover{color:#c0392b}
.cp-dim-ok{font-size:12px;color:var(--blue,#3a5199);padding:2px 0}
.cp-ok-at{font-size:12px;color:var(--blue,#3a5199);margin:4px 0 0}
.cp-new-form{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin:6px 0 14px;padding-top:12px;border-top:1px solid var(--line-soft,#e3e6ee)}
.cp-new-form label{display:flex;flex-direction:column;gap:5px;font-size:12px;color:var(--ink4,#9aa0ad)}
.cp-new-form input,.cp-new-form textarea,.cp-new-form select,.cp-dim-a input,.cp-note input{height:32px;padding:0 9px;border:1px solid var(--line-soft,#dfe3ec);border-radius:8px;background:var(--field,#fff);font-family:inherit;font-size:12px;color:var(--ink2,#3c4150)}
.cp-new-form select{-webkit-appearance:none;appearance:none;cursor:pointer}
.cp-new-form textarea{height:auto;min-height:54px;padding:8px 9px;resize:vertical}
.cp-new-full{grid-column:1 / -1}
.cp-person.on{border-color:var(--blue,#3a5199)}
.cp-person-d>b{font-size:14.5px;color:var(--ink2,#3c4150)}
.cp-person-d>b em{font-style:normal;font-size:12px;font-weight:400;color:var(--ink4,#9aa0ad);margin-left:8px}
.cp-msg{color:#a05a20!important}
.cp-empty{font-size:12px;color:var(--ink4,#9aa0ad)}
.cp-dim{padding:9px 0;border-bottom:1px solid var(--line-soft,#eef0f5)}
.cp-dim>p{margin:0 0 7px;font-size:12px;color:var(--ink3,#6b6f7a);line-height:1.6}
.cp-dim>p span{display:inline-block;width:96px;color:var(--ink4,#9aa0ad)}
.cp-dim-a{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.cp-dim-a input{flex:1;min-width:150px}
.cp-locked{font-size:12px;color:var(--ink4,#9aa0ad)}
.cp-tag{font-style:normal;font-size:12px;padding:1px 5px;border:1px solid currentColor;border-radius:5px;margin-left:6px;white-space:nowrap}
.cp-tag.guess{color:#a05a20}.cp-tag.fact{color:var(--blue,#3a5199)}
.cp-scenes{padding:12px 0 4px}
.cp-scenes>b{display:block;font-size:12px;color:var(--ink3,#6b6f7a);margin-bottom:4px}
.cp-scene{display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:8px 0;border-bottom:1px solid var(--line-soft,#eef0f5);font-size:12px;color:var(--ink3,#6b6f7a)}
.cp-scene>span{font-size:12px;color:var(--ink4,#9aa0ad);min-width:82px}
.cp-scene>p{margin:0;flex:1;min-width:160px;line-height:1.6}
.cp-note{display:flex;gap:8px;align-items:center;margin:12px 0}
.cp-note input{flex:1;min-width:0}
@media (max-width:640px){.cp-new-form{grid-template-columns:1fr}.cp-dim-a input{min-width:120px}}
/* 解惑内嵌：说明压成一行，叠层顶到首屏，上下文带/四步入让到下面 */
.cp-see-hint{font-size:12px;line-height:1.6;color:var(--ink3,#6b6f7a);margin:0 0 10px}
.cp-see-top .deck{margin-top:2px}
/* 关系图：节点只取已建档人物。发丝线分层，一个强调色，不叠卡片。 */
.cp-rel{margin:14px 0;padding-top:12px;border-top:1px solid var(--line-soft,#e3e6ee)}
.cp-rel>b{display:block;font-size:13px;color:var(--ink2,#3c4150)}
.cp-rel>p{margin:4px 0 8px;font-size:12px;color:var(--ink4,#9aa0ad);line-height:1.6}
.cp-rel svg{display:block;width:100%;max-width:640px;height:auto;margin:0 auto}
.cp-rel-list{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}
.cp-rel-list>div{flex:1;min-width:150px;padding:7px 0;border-bottom:1px solid var(--line-soft,#eef0f5)}
.cp-rel-list span{font-size:12px;color:var(--ink2,#3c4150)}
.cp-rel-list em{font-style:normal;font-size:12px;color:var(--blue,#3a5199);margin-left:6px}
.cp-rel-list p{margin:3px 0 0;font-size:12px;color:var(--ink4,#9aa0ad);line-height:1.5}
.cp-person em i{font-style:normal;color:var(--blue,#3a5199)}
/* 拖入即读：解读气泡下的下一步建议（点一个才继续，不自动执行） */
.bt-sugs{display:flex;flex-wrap:wrap;gap:7px;margin-top:9px;padding-top:9px;border-top:1px solid var(--line-soft,#e3e6ee)}
.bt-sug{padding:7px 11px;border:1px solid var(--line-soft,#dfe3ec);border-radius:9px;background:var(--field,#fff);font-size:12px;line-height:1.4;text-align:left;cursor:pointer;color:var(--ink2,#3c4150)}
.bt-sug:hover{border-color:var(--blue,#3a5199)}
.bt-sug b{display:block;font-weight:600;color:var(--blue,#3a5199)}
.bt-sug em{font-style:normal;font-size:12px;color:var(--ink4,#9aa0ad)}
.bt-reading{font-size:12px;color:var(--ink4,#9aa0ad);padding:4px 0}
/* 首页四宫格的管家卡折叠态原本把气泡文字藏起来、只露行动按钮
   （beta-skin.css:53）。拖入即读的「解读」必须让人看见，这条单独放行并限高。 */
.quad .q-butler:not(.is-open) .bt-msg-read .bt-bub{display:block;max-height:96px;overflow:auto;font-size:12px;line-height:1.55}

/* ───────── HoldButton 长按确认（2026-11-07 老板批） ─────────
   全网页删除统一「按住才删」：进度环充满才触发，松手即回退。
   RAF + stroke-dashoffset（只重绘不重排）；鼠标/触摸走 Pointer Events。 */
.hc-mask{position:fixed;inset:0;z-index:9999;display:flex;align-items:center;justify-content:center;
  background:rgba(28,30,40,.44);backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);
  padding:20px;animation:hcIn var(--h-fast,140ms) var(--e-out,ease-out)}
@keyframes hcIn{from{opacity:0}to{opacity:1}}
.hc-card{width:min(340px,92vw);background:var(--card,#fff);border:1px solid var(--line,rgba(0,0,0,.1));
  border-radius:16px;padding:22px 20px 16px;box-shadow:0 18px 50px rgba(20,22,32,.28);text-align:center;
  animation:hcPop var(--h-fast,140ms) var(--e-out,ease-out)}
@keyframes hcPop{from{transform:scale(.94) translateY(6px);opacity:0}to{transform:none;opacity:1}}
.hc-title{display:block;font-size:16px;font-weight:700;color:var(--ink,#232634)}
.hc-desc{margin:8px 0 0;font-size:13px;line-height:1.55;color:var(--ink2,#5a6070);word-break:break-word}
.hc-hold{display:flex;justify-content:center;margin:16px 0 4px}
.hc-tip{margin:2px 0 12px;font-size:12px;color:var(--ink4,#9aa0ad)}
.hc-foot{display:flex;justify-content:center}
.hc-cancel{border:1px solid var(--line,rgba(0,0,0,.14));background:transparent;color:var(--ink2,#5a6070);
  border-radius:9px;padding:7px 24px;font-size:13px;cursor:pointer}
.hc-cancel:hover{background:var(--red-soft,rgba(255,59,48,.08))}
body.hc-lock{overflow:hidden}
/* 方形充能钮（A原型+白勾，老板 2026-11-07 定稿）：靛蓝液面下灌上充，
   文字过半变白保证可读，充满弹跳 + 白勾一笔画出。确认弹窗大号/内嵌小号，尺寸 JS 里给 */
.hold-btn{position:relative;overflow:hidden;border-radius:999px;border:1px solid rgba(58,81,153,.28);
  background:#eceef9;cursor:pointer;padding:0;-webkit-tap-highlight-color:transparent;
  touch-action:none;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none}
.hb-fill{position:absolute;left:0;top:0;bottom:0;width:0%;
  background:linear-gradient(90deg,#41589e,#3a5199)}
.hold-btn .hb-txt{position:relative;z-index:2;width:100%;height:100%;display:flex;align-items:center;
  justify-content:center;font-size:var(--hb-fs,13px);font-weight:600;color:#3a5199;pointer-events:none;
  transition:color .12s ease,opacity .18s ease}
.hold-btn.lit .hb-txt{color:#fff}
.hold-btn.done .hb-txt{opacity:0}
.hb-check{position:absolute;left:50%;top:50%;width:36px;height:36px;margin:-18px 0 0 -18px;z-index:3;
  fill:none;stroke:#fff;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;
  stroke-dasharray:46;stroke-dashoffset:46;pointer-events:none}
.hold-btn.done .hb-check{animation:hbCheck .32s ease-out forwards}
@keyframes hbCheck{to{stroke-dashoffset:0}}
.hold-btn.done{animation:hbBounce .34s cubic-bezier(.34,1.56,.64,1)}
@keyframes hbBounce{0%{transform:scale(1.05,.9)}55%{transform:scale(.96,1.05)}100%{transform:scale(1)}}
.hold-btn.shake{animation:hbShake .3s ease}
@keyframes hbShake{0%,100%{transform:translateX(0)}25%{transform:translateX(-5px)}55%{transform:translateX(4px)}80%{transform:translateX(-2px)}}
.hold-btn:focus-visible{outline:2px solid #3a5199;outline-offset:3px}
@media (prefers-reduced-motion: reduce){
  .hc-mask,.hc-card,.hold-btn.done,.hold-btn.done .hb-check,.hold-btn.shake{animation:none}
}

/* ═══════════════════════════════════════════════════════════════════════
   日夜模式（2026-11-10 老板要的手动切换）
   ─ 开关只在「今天」页右上角，切的是 <html data-theme>，整站一起换；
   ─ 浅色一行没动：下面每一条都挂在 [data-theme="dark"] 下；
   ─ 深色沿用定时任务面板已定的同一套深钢靛 + 浅字 + 钢靛强调色，
     不另起一套配色；只覆盖颜色与阴影，尺寸、间距、布局、内容全部不动。
   ═══════════════════════════════════════════════════════════════════════ */
:root[data-theme="dark"]{
  color-scheme:dark;
  --ink:#eef1f6;
  --ink2:#c6cddb;
  --ink3:#a7b0c0;
  --ink4:#8f99ab;
  --line:rgba(255,255,255,.15);
  --hairline:rgba(255,255,255,.09);
  --line-soft:rgba(255,255,255,.055);
  --fill:rgba(255,255,255,.05);
  --fill-2:rgba(255,255,255,.09);
  --check-line:rgba(255,255,255,.22);
  --blue:#7fb4dc;
  --blue-d:#a8cdea;
  --blue-soft:rgba(127,180,220,.14);
  --blue-ring:rgba(127,180,220,.45);
  --brand-500:#7fb4dc;
  --brand-600:#a8cdea;
  --brand-50:rgba(127,180,220,.12);
  --brand-100:rgba(127,180,220,.2);
  --accent-line:rgba(127,180,220,.5);
  --sel-a:#7fb4dc;
  --sel-b:#7fb4dc;
  --sel-grad:linear-gradient(135deg,#7fb4dc,#7fb4dc);
  --sel-ring:rgba(127,180,220,.45);
  --sel-line:rgba(127,180,220,.5);
  --sel-fill:rgba(127,180,220,.14);
  --ok:#67c48f;
  --ok-text:#8ad7aa;
  --ok-soft:rgba(103,196,143,.14);
  --warn:#e0a95c;
  --warn-text:#e9bb7e;
  --warn-soft:rgba(224,169,92,.14);
  --red:#e2938a;
  --red-text:#e2938a;
  --red-soft:rgba(226,147,138,.14);
  --card:rgba(30,35,47,.72);
  --glass:rgba(30,35,47,.72);
  --field:#242b39;
  --field-2:rgba(45,52,67,.85);
  --edge:rgba(255,255,255,.12);
  --sh-1:0 1px 2px rgba(0,0,0,.18),0 20px 44px -32px rgba(0,0,0,.75);
  --sh-2:0 2px 4px rgba(0,0,0,.22),0 28px 56px -32px rgba(0,0,0,.8);
  --sh-3:0 6px 16px -10px rgba(0,0,0,.8);
  --blur:blur(44px) saturate(140%);
}
html[data-theme="dark"]{background:#171c26}
html[data-theme="dark"] body{background:transparent;color:var(--ink)}
html[data-theme="dark"] body::after{opacity:.12}
html[data-theme="dark"] ::selection{background:rgba(127,180,220,.3);color:#fff}
/* 白色实底的控件：深色下换成同一块玻璃，避免「白底 + 浅字」读不出来 */
html[data-theme="dark"] .glass,
html[data-theme="dark"] .sg-pop,
html[data-theme="dark"] .mbox,
html[data-theme="dark"] .auth,
html[data-theme="dark"] .auth-card,
html[data-theme="dark"] .af-in,
html[data-theme="dark"] .search,
html[data-theme="dark"] .inp,
html[data-theme="dark"] .ta,
html[data-theme="dark"] .t-drop,
html[data-theme="dark"] .bitem,
html[data-theme="dark"] .ftile,
html[data-theme="dark"] .ukpi,
html[data-theme="dark"] .btn.ghost,
html[data-theme="dark"] .btn.pale,
html[data-theme="dark"] .links a.on,
html[data-theme="dark"] .af-tab.on,
html[data-theme="dark"] .nav-handle,
html[data-theme="dark"] .nav-in,
html[data-theme="dark"] .side,
html[data-theme="dark"] .more-sheet .ms-in,
html[data-theme="dark"] .td-theme{
  background:var(--card);
  border-color:var(--line);
  color:var(--ink);
  box-shadow:var(--sh-1);
}
html[data-theme="dark"] .btn.pri,
html[data-theme="dark"] .btn.pri:hover,
html[data-theme="dark"] .pk.on,
html[data-theme="dark"] .chip.on{
  background:#7fb4dc;color:#171c26;
}
html[data-theme="dark"] .btn.pri:hover{background:#a8cdea}
html[data-theme="dark"] input:not([type=checkbox]):not([type=radio]):not([type=range]),
html[data-theme="dark"] textarea,
html[data-theme="dark"] select{
  background:var(--field);color:var(--ink);border-color:var(--line);color-scheme:dark;
}
html[data-theme="dark"] input::placeholder,
html[data-theme="dark"] textarea::placeholder{color:var(--ink4)}
/* 今天页右上角的开关：发丝线 + 玻璃药丸，不抢刊头 */
.td-theme{position:absolute;right:0;top:0;display:inline-flex;align-items:center;gap:6px;
  height:30px;padding:0 12px;border-radius:999px;
  border:1px solid var(--line);background:var(--card);color:var(--ink2);
  font-family:var(--v2-sans,inherit);font-size:var(--fs-sm);letter-spacing:.02em;
  cursor:pointer;white-space:nowrap;
  -webkit-backdrop-filter:var(--blur);backdrop-filter:var(--blur);
  box-shadow:var(--sh-1);
  transition:color .18s var(--ease-q),border-color .18s var(--ease-q),background .18s var(--ease-q)}
.td-theme:hover{color:var(--ink);border-color:var(--sel-line);background:var(--field-2)}
.td-theme:focus-visible{outline:2px solid var(--blue-ring);outline-offset:2px}
.td-theme .td-theme-ico{font-size:14px;line-height:1}
@media (max-width:576px){
  .td-theme{top:-2px;height:28px;padding:0 9px}
}
/* 深色下的未选中态与 hover：别把浅色实底抖出来（玻璃上会像贴了块白纸） */
html[data-theme="dark"] .chip:not(.on),
html[data-theme="dark"] .pk:not(.on),
html[data-theme="dark"] .btn.ghost:hover,
html[data-theme="dark"] .chip:hover,
html[data-theme="dark"] .search:hover,
html[data-theme="dark"] .search:focus-within,
html[data-theme="dark"] .t-drop:hover,
html[data-theme="dark"] .t-drop:focus-visible,
html[data-theme="dark"] .af-in:focus,
html[data-theme="dark"] .af-tab.on,
html[data-theme="dark"] .links a.on{
  background:var(--fill-2);
  border-color:var(--line);
  color:var(--ink);
}
