  /* ── 深色(默认)· Claude Code 暖炭灰 + 赤陶橙 ────────────────────────── */
  :root{
    --bg:#181716; --bg2:#1c1b19; --panel:#252320; --panel2:#302f2c; --card:#2b2a27;
    --line:#3a3934; --line2:#4a4941;
    --text:#ecebe3; --dim:#a5a094; --dim2:#716d61;
    --accent:#d97757; --accent2:#c8613f;
    --user1:#d97757; --user2:#c25f3c; --on-user:#fff;
    --ok:#5aa469; --err:#d1674a; --radius:16px;
    --bar-bg:rgba(28,27,25,.72);
    --login-bg:radial-gradient(120% 90% at 50% -10%,#252320 0%,#1c1b19 60%);
    --code-bg:#22211e; --code-fg:#d4d0c4; --code-inline:rgba(180,170,150,.15);
    --scroll:#3a3934; --scroll-h:#4a4941;
    --bubble-shadow:0 1px 2px rgba(0,0,0,.24);
    --shadow:0 10px 34px rgba(0,0,0,.45);
    --focus-ring:rgba(217,119,87,.2);
    --glow1:rgba(217,119,87,.4); --glow2:rgba(194,95,60,.4);
    /* 语义状态色:成功/错误/警告的 前景·边框·底色 三件套 */
    --ok-fg:#8dc9a8; --ok-line:#3d6b52; --ok-bg:#1f2c25;
    --err-fg:#e5aaaa; --err-line:#6b3d3d; --err-bg:#2c1f1f;
    --warn:#e8a84c;
    --danger:#e05050; --danger2:#c03030;   /* 停止按钮:比 --err 更红更醒目 */
    --on-accent:#fff;                      /* 强调色/彩色底上的前景文字 */
    /* 代码差异色:沿用 GitHub 标准值,饱和度刻意高于 --ok/--err,不并入语义色 */
    --diff-add:#3fb950; --diff-del:#f85149;
    /* 项目标签分类色:互相区分用,不做合并 */
    --tag-sun:#df977b; --tag-copper:#d4a474; --tag-leaf:#87ad80; --tag-ink:#a8b5d4;
    --tag-olive:#a5b87d; --tag-gold:#d4b051;
    /* 遮罩与叠加:半透明黑/白,深浅主题通用 */
    --ov-1:rgba(0,0,0,.12); --ov-2:rgba(0,0,0,.32); --ov-3:rgba(0,0,0,.5); --ov-4:rgba(0,0,0,.88);
    --wh-1:rgba(255,255,255,.14); --wh-2:rgba(255,255,255,.28); --wh-3:rgba(255,255,255,.85);
    --sbw:9px;   /* 滚动条宽度,和下面 ::-webkit-scrollbar 保持一致 */
  }
  /* ── 尺寸设计令牌(与主题无关,不随深浅色变化)─────────────────────────
     写新样式时一律用这些变量,不要再手写字号/圆角/间距/过渡时长。
     字号下限 12px:再小在移动端读不清,已统一上调。 */
  :root{
    /* 字号阶梯 */
    --fs-sm:12px; --fs-md:13px; --fs-base:14px; --fs-lg:15px; --fs-xl:16px;
    /* 间距阶梯 */
    --sp-1:4px; --sp-2:6px; --sp-3:8px; --sp-4:12px; --sp-5:16px;
    /* 圆角阶梯(50% 圆形与 0 直角不在此列,按需直写) */
    --r-sm:6px; --r-md:9px; --r-lg:12px; --r-xl:16px; --r-pill:999px;
    /* 过渡时长:交互反馈用 fast,位移/展开用 base */
    --t-fast:.15s; --t-base:.22s;
  }
  /* ── 浅色:系统偏好浅色且用户未手动固定时 · Claude Code 暖米色 ────────── */
  @media(prefers-color-scheme:light){
    :root:not([data-theme]){
      --bg:#ffffff; --bg2:#ffffff; --panel:#f7f7f7; --panel2:#eeeeee; --card:#ffffff;
      --line:#e5e5e5; --line2:#d8d8d8;
      --text:#29261f; --dim:#6d6757; --dim2:#9a9482;
      --accent:#bd5d3a; --accent2:#a84e2f;
      --user1:#d97757; --user2:#c25f3c; --on-user:#fff;
      --bar-bg:rgba(255,255,255,.8);
      --login-bg:radial-gradient(120% 90% at 50% -10%,#f5f5f5 0%,#ffffff 60%);
      --code-bg:#f5f5f5; --code-fg:#3a362c; --code-inline:rgba(0,0,0,.06);
      --scroll:#d8d8d8; --scroll-h:#c4c4c4;
      --bubble-shadow:0 1px 2px rgba(0,0,0,.05);
      --shadow:0 10px 34px rgba(0,0,0,.08);
      --focus-ring:rgba(189,93,58,.16);
      --glow1:rgba(217,119,87,.3); --glow2:rgba(189,93,58,.28);
      --ok-fg:#347a58; --ok-line:#8dc9a8; --ok-bg:#eef9f2;
      --err-fg:#ad4e4e; --err-line:#e5aaaa; --err-bg:#fff2f2;
      --warn:#c98a2e;
      --danger:#d94040; --danger2:#b82828;
      --on-accent:#fff;
      --diff-add:#1a7f37; --diff-del:#cf222e;
      --tag-sun:#c2765a; --tag-copper:#a87d4f; --tag-leaf:#5f8a58; --tag-ink:#6b7ba8;
      --tag-olive:#7d9155; --tag-gold:#a8862c;
    }
  }
  /* ── 手动固定浅色 ────────────────────────────────────────────────────── */
  :root[data-theme="light"]{
    --bg:#ffffff; --bg2:#ffffff; --panel:#f7f7f7; --panel2:#eeeeee; --card:#ffffff;
    --line:#e5e5e5; --line2:#d8d8d8;
    --text:#29261f; --dim:#6d6757; --dim2:#9a9482;
    --accent:#bd5d3a; --accent2:#a84e2f;
    --user1:#d97757; --user2:#c25f3c; --on-user:#fff;
    --bar-bg:rgba(255,255,255,.8);
    --login-bg:radial-gradient(120% 90% at 50% -10%,#f5f5f5 0%,#ffffff 60%);
    --code-bg:#f5f5f5; --code-fg:#3a362c; --code-inline:rgba(0,0,0,.06);
    --scroll:#d8d8d8; --scroll-h:#c4c4c4;
    --bubble-shadow:0 1px 2px rgba(0,0,0,.05);
    --shadow:0 10px 34px rgba(0,0,0,.08);
    --focus-ring:rgba(189,93,58,.16);
    --glow1:rgba(217,119,87,.3); --glow2:rgba(189,93,58,.28);
    --ok-fg:#347a58; --ok-line:#8dc9a8; --ok-bg:#eef9f2;
    --err-fg:#ad4e4e; --err-line:#e5aaaa; --err-bg:#fff2f2;
    --warn:#c98a2e;
    --danger:#d94040; --danger2:#b82828;
    --on-accent:#fff;
    --diff-add:#1a7f37; --diff-del:#cf222e;
    --tag-sun:#c2765a; --tag-copper:#a87d4f; --tag-leaf:#5f8a58; --tag-ink:#6b7ba8;
    --tag-olive:#7d9155; --tag-gold:#a8862c;
  }
  /* data-theme="dark" 用根默认值即可,无需重复 */

  *{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
  html,body{margin:0;height:100%;background:var(--bg2);color:var(--text);
    font:15px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"PingFang SC","Microsoft YaHei",sans-serif;
    overscroll-behavior:none;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
    -webkit-text-size-adjust:100%;text-size-adjust:100%;
    transition:background-color .3s ease,color .3s ease}
  button{font:inherit;cursor:pointer;border:none;background:none;color:inherit}
  a{color:var(--accent)}

  /* 美化滚动条 */
  ::-webkit-scrollbar{width:var(--sbw);height:9px}
  ::-webkit-scrollbar-thumb{background:var(--scroll);border-radius:var(--r-md);border:2px solid transparent;background-clip:padding-box}
  ::-webkit-scrollbar-thumb:hover{background:var(--scroll-h);background-clip:padding-box}
  ::-webkit-scrollbar-track{background:transparent}

  /* 登录 */
  #login{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;
    background:var(--login-bg);z-index:50;padding:24px}
  #login .card{width:100%;max-width:340px;text-align:center;animation:pop .4s ease}
  #login .logo{width:68px;height:68px;margin:0 auto 16px;color:var(--text);
    display:flex;align-items:center;justify-content:center}
  #login .logo .voco-mascot{--s:2.4}
  #login h1{font-size:30px;margin:0 0 6px;letter-spacing:1px;font-weight:600;
    font-family:Optima,"Times New Roman","Songti SC",serif}
  #login p{color:var(--dim);margin:0 0 26px;font-size:var(--fs-base)}
  #login input{width:100%;padding:var(--sp-5) var(--sp-5);border-radius:var(--r-xl);border:1px solid var(--line2);
    background:var(--card);color:var(--text);font-size:var(--fs-xl);margin-bottom:12px;transition:border-color var(--t-base),box-shadow var(--t-base)}
  #login input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--focus-ring)}
  #login button{width:100%;padding:var(--sp-5);border-radius:var(--r-xl);
    background:linear-gradient(135deg,var(--user1),var(--user2));color:var(--on-accent);font-weight:600;font-size:var(--fs-xl);
    transition:transform var(--t-fast),box-shadow var(--t-base);box-shadow:0 4px 16px var(--glow2)}
  #login button:active{transform:scale(.97)}
  #login .err{color:var(--err);font-size:var(--fs-md);height:18px;margin-top:10px}

  /* 布局 */
  #app{display:flex;overflow:hidden;
    position:fixed;top:var(--app-top,0);left:0;right:0;bottom:0;height:var(--app-h,auto)}
  #sidebar{width:280px;flex-shrink:0;background:var(--bg2);
    border:1px solid var(--line);border-radius:var(--r-xl);
    margin:8px 0 8px 8px;
    box-shadow:0 2px 12px rgba(0,0,0,.08);
    display:flex;flex-direction:column;overflow:hidden;
    transition:transform var(--t-base) cubic-bezier(.4,0,.2,1),width var(--t-base) cubic-bezier(.4,0,.2,1),margin var(--t-base) cubic-bezier(.4,0,.2,1),box-shadow var(--t-base);z-index:30}
  #sidebar .shead{padding:var(--sp-4) var(--sp-5) var(--sp-2);padding-top:calc(12px + env(safe-area-inset-top));display:flex;align-items:center;gap:8px}
  #sidebar .shead .brand{flex:1;font-family:Optima,"Times New Roman","Songti SC",serif;
    font-size:20px;font-weight:700;color:var(--text);cursor:pointer;
    transition:color var(--t-fast)}
  #sidebar .shead .brand:hover{color:var(--accent)}
  .syncstate{flex:none;max-width:76px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
    padding:2px var(--sp-2);border:1px solid var(--line);border-radius:var(--r-pill);font-size:var(--fs-sm);line-height:14px;color:var(--muted)}
  .syncstate.syncing,.syncstate.cached{background:var(--panel)}
  .syncstate.online{color:var(--ok-fg);border-color:var(--ok-line);background:var(--ok-bg)}
  .syncstate.offline{color:var(--err-fg);border-color:var(--err-line);background:var(--err-bg)}
  /* 列表行统一规范:所有可点行(＋新对话 / 分组头 / 会话)共用同一内边距 + 圆角,
     hover 的灰底矩形尺寸与圆角完全一致 */
  /* #convList 是固定外框(Tab 栏 + 列表),只有 #convBody 滚动 */
  #convList{flex:1;display:flex;flex-direction:column;overflow:hidden;padding:2px 0 0}
  #sideTabs{flex-shrink:0;padding:0 var(--sp-3)}   /* 与 #convBody 的左右 8px 内边距对齐 */
  #convBody{flex:1;overflow-y:auto;padding:0 var(--sp-3) var(--sp-3)}
  /* 侧边栏顶部固定区:新对话 + 主会话 + 语音通话三入口,不随会话列表滚动(#convList 内),
     列表很长时 flex-shrink:0 保证不被压缩挤出 */
  #convTop{flex-shrink:0;padding:2px var(--sp-3) 0}
  #convTopRows{display:flex;flex-direction:column}
  /* 侧边栏骨架屏:数据到位前的占位行,复用聊天区 skelshine 动画;
     真实行渲染时整个容器被 innerHTML 清空替换,无跳动 */
  .conv.skelrow{pointer-events:none}
  .conv.skelrow .sbar{flex:1;height:16px;border-radius:var(--r-md);background:var(--panel2)}
  .conv.skelrow .sbar.w45{flex:0 0 45%}
  .skelconv{height:34px;border-radius:var(--r-sm);background:var(--panel2);margin-bottom:4px}
  .projgrp,.conv{padding:var(--sp-2) var(--sp-4);border-radius:var(--r-sm);display:flex;align-items:center;
    cursor:pointer;transition:background var(--t-fast),color var(--t-fast)}
  .conv.active{background:var(--panel2)}
  /* :hover 只在真有 hover 能力的设备生效——触屏上元素自身样式随 :hover 变化,
     会撞上 iOS 经典坑:第一下点击只用来"结算" hover 态,第二下才真正触发 click */
  @media(hover:hover){ .projgrp:hover,.conv:hover{background:var(--panel2)} }
  /* ＋新对话:与主会话行同构(.conv 行样式 + edit 图标),margin 对齐 #convList 内边距 */
  #newBtn{margin:0 0 1px}
  #newBtn:active{transform:scale(.98)}
  /* 语音任务:固定分组,行样式复用 .conv/.cvbody,状态点颜色跟任务状态走 */
  /* 侧边栏收起按钮(仅桌面显示)*/
  #collapseBtn{display:none;width:26px;height:26px;border-radius:var(--r-sm);flex-shrink:0;
    align-items:center;justify-content:center;color:var(--dim);
    transition:background var(--t-fast),color var(--t-fast),transform var(--t-fast)}
  #collapseBtn:hover{background:var(--panel2);color:var(--text)}
  #collapseBtn:active{transform:scale(.9)}
  #collapseBtn .ic{width:16px;height:16px}
  /* touch-action:pan-y——纵向滚动交给浏览器原生处理,横向不让浏览器插手,
     全交给 bindSwipe() 的 JS 手势;否则原生纵向抖动会触发 #convList 的 scroll
     监听把刚滑出来的菜单强制收起(表现为"菜单停不住、点不到按钮") */
  .conv{margin-bottom:1px;gap:8px;color:var(--dim);position:relative;overflow:hidden;touch-action:pan-y}
  /* 新对话、主会话、工作台属于同一固定入口组，使用普通行间距。 */
  #convTopRows .conv{margin-bottom:1px}
  .conv.active{color:var(--text)}
  @media(hover:hover){ .conv:hover{color:var(--text)} }
  /* 左滑露出归档/删除(cvact 默认平移到行外,靠 overflow:hidden 裁掉;
     滑动时 cvbody 与 cvact 反向同步平移,互换着露出/藏起) */
  .conv .cvbody{display:flex;align-items:center;gap:8px;width:100%;transition:transform var(--t-base) ease}
  .conv.swiping .cvbody{transition:none}
  .conv.swiped .cvbody{transform:translateX(-108px)}
  .conv .cvact{position:absolute;top:0;right:0;bottom:0;width:108px;display:flex;
    transform:translateX(100%);transition:transform var(--t-base) ease}
  .conv.swiping .cvact{transition:none}
  .conv.swiped .cvact{transform:translateX(0)}
  .conv .cvact button{flex:1;border:none;display:flex;align-items:center;justify-content:center;color:var(--on-accent);cursor:pointer}
  .conv .cvact button .ic{width:16px;height:16px}
  .conv .cvact .cvarch{background:var(--dim2)}
  .conv .cvact .cvpin{background:var(--accent)}
  .conv .cvact .cvdel{background:var(--err);border-radius:0 7px 7px 0}   /* 贴行右边缘,配行本身的圆角,避免被 overflow 裁出直角缺口 */
  .conv .ct{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--fs-base)}
  .conv .livedot{flex-shrink:0;width:7px;height:7px;border-radius:50%;background:var(--accent);animation:livepulse 1.2s infinite}   /* AI 正在回复:闪烁圆点 */
  @keyframes livepulse{0%,100%{opacity:.25;transform:scale(.8)}50%{opacity:1;transform:scale(1)}}
  .conv .ctime{flex-shrink:0;color:var(--dim2);font-size:var(--fs-sm);font-variant-numeric:tabular-nums;transition:opacity var(--t-fast)}  /* 会话时刻:名称右侧 */
  /* 任务行「停止」键(只出现在后台任务还在跑时):常显红方块,紧贴 ⋯ 左侧,触屏也能直接点 */
  .conv .cvstop{position:absolute;right:30px;top:50%;transform:translateY(-50%);width:20px;height:20px;
    display:flex;align-items:center;justify-content:center;padding:0;border:none;background:none;
    color:var(--err);cursor:pointer;border-radius:var(--r-sm);transition:background var(--t-fast)}
  .conv .cvstop .ic{width:13px;height:13px}
  .conv .cvstop:hover{background:var(--card)}
  /* 「⋯」更多键绝对定位:不占布局宽度,hover 时浮现 */
  .conv .more{position:absolute;right:8px;top:50%;transform:translateY(-50%);opacity:0;pointer-events:none;
    font-size:var(--fs-xl);line-height:1;color:var(--dim2);padding:2px var(--sp-2);border-radius:var(--r-sm);transition:opacity var(--t-fast),color var(--t-fast),background var(--t-fast)}
  .conv .more:hover,.conv .more.on{color:var(--text);background:var(--card);opacity:1}
  /* 桌面 hover:显示 ⋯、隐藏时间;触屏彻底不挂 .conv:hover(即便只改子元素样式,
     iOS 也会判定该元素"随 hover 变化"而要求点两下),改用左滑弹归档/删除 */
  @media(hover:hover){ .conv:hover .ctime{opacity:0} .conv:hover .more{opacity:.6;pointer-events:auto} }
  @media(hover:none){ .conv .more{opacity:0;pointer-events:none} }
  /* 会话「更多」浮层菜单(挂在 body 上,避开侧栏 overflow 裁剪) */
  .convmenu{position:fixed;z-index:40;min-width:130px;
    background:var(--card);border:1px solid var(--line2);border-radius:var(--r-lg);padding:var(--sp-2);
    box-shadow:var(--shadow);animation:pop .14s ease}
  .convmenu .cmitem{display:flex;align-items:center;gap:8px;width:100%;text-align:left;
    padding:var(--sp-3) var(--sp-4);border-radius:var(--r-md);font-size:var(--fs-md);color:var(--text);transition:background var(--t-fast)}
  .convmenu .cmitem:hover{background:var(--panel2)}
  .convmenu .cmitem.danger{color:var(--err)}
  .convmenu .cmitem.danger:hover{background:rgba(209,103,74,.12)}
  /* 侧栏底部会话筛选下拉(挂在状态栏「设置」左侧,弹层朝上开) */
  #convFilterBox{position:relative}
  #convFilterPop{position:absolute;bottom:calc(100% + 4px);right:0;min-width:120px;z-index:40;
    background:var(--card);border:1px solid var(--line2);border-radius:var(--r-lg);padding:var(--sp-2);
    box-shadow:var(--shadow);animation:pop .14s ease}
  #convFilterPop[hidden]{display:none}
  #convFilterPop .fmi{display:flex;align-items:center;gap:8px;width:100%;text-align:left;
    padding:var(--sp-3) var(--sp-4);border-radius:var(--r-md);font-size:var(--fs-md);color:var(--text);transition:background var(--t-fast)}
  #convFilterPop .fmi:hover{background:var(--panel2)}
  #convFilterPop .fmi.on{color:var(--accent);font-weight:600}
  .sfoot{padding:var(--sp-3) var(--sp-4) var(--sp-3) var(--sp-5);border-top:1px solid var(--line);font-size:var(--fs-md);color:var(--text);display:flex;align-items:center;gap:9px}
  .sfoot .savatar{width:26px;height:26px;border-radius:50%;flex-shrink:0;
    background:linear-gradient(135deg,var(--accent),var(--user2));
    display:flex;align-items:center;justify-content:center;
    color:var(--on-accent);font-size:var(--fs-sm);font-weight:700;letter-spacing:0}
  .sfoot .sfoottxt{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500}
  /* 出错气泡:红色左边框 */
  .bubble.err{border-left:3px solid var(--err);padding-left:var(--sp-4)}
  /* 完成未读灰点:工作结束后保留,打开会话后消失。间距靠 .cvbody 的 gap:8px 统一,
     不额外加 margin——否则和 .livedot 的间距对不齐。 */
  .conv .reviewdot{flex-shrink:0;width:7px;height:7px;border-radius:50%;background:var(--dim2);animation:dotpop .18s ease}
  @keyframes dotpop{0%{transform:scale(.4);opacity:0}100%{transform:scale(1);opacity:1}}
  /* 跨会话审批/确认弹窗:半透明背景 + 居中紧凑卡片(不做成占满全屏的大块) */
  #choiceModal{position:fixed;inset:0;z-index:100;display:flex;align-items:center;justify-content:center;background:var(--ov-3);padding:18px}
  #choiceModal[hidden]{display:none}
  #choiceModal .cmbox{width:min(360px,100%);max-height:80vh;display:flex;flex-direction:column;background:var(--panel);border:1px solid var(--line2);border-radius:var(--r-xl);overflow:hidden;box-shadow:var(--shadow)}
  #choiceModal .cmhead{padding:var(--sp-5) 18px var(--sp-4);border-bottom:1px solid var(--line)}
  #choiceModal .cmbadge{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-sm);font-weight:600;color:var(--accent);text-transform:uppercase;letter-spacing:.04em;margin-bottom:7px}
  #choiceModal .cmdot{width:6px;height:6px;border-radius:50%;background:var(--accent);animation:livepulse 1.2s infinite}
  #choiceModal .cmtitle{font-size:var(--fs-lg);font-weight:700;color:var(--text);line-height:1.3}
  #choiceModal .cmbody{padding:var(--sp-5) 18px 18px;overflow-y:auto}
  #choiceModal .cmprompt{font-size:var(--fs-md);line-height:1.55;color:var(--text);margin-bottom:14px;word-break:break-word}
  #choiceModal .cmprompt p{margin:0 0 .6em}
  #choiceModal .cmprompt p:last-child{margin-bottom:0}
  #choiceModal .cmopts{display:flex;flex-direction:column;gap:8px}
  #choiceModal .cmopts button{width:100%;text-align:left;padding:var(--sp-4) var(--sp-4);border-radius:var(--r-md);border:1px solid var(--line2);background:var(--panel2);color:var(--text);font-size:var(--fs-md);cursor:pointer;transition:background var(--t-fast),border-color var(--t-fast);position:relative}
  #choiceModal .cmopts button:hover{background:var(--card);border-color:var(--accent)}
  #choiceModal .cmopts button.selected{background:color-mix(in srgb,var(--accent) 15%,transparent);border-color:var(--accent);color:var(--accent);font-weight:600}
  #choiceModal .cmopts button.dimmed{opacity:.45}
  #choiceModal .cmopts button:disabled{pointer-events:none}
  @media(max-width:480px){ #choiceModal .cmbox{width:100%;max-height:70vh} }
  /* 设置入口:状态栏最右一个齿轮图标 */
  .sfoicon{width:30px;height:30px;border-radius:var(--r-md);flex-shrink:0;display:flex;align-items:center;justify-content:center;
    color:var(--dim);transition:background var(--t-fast),color var(--t-fast)}
  .sfoicon:hover{background:var(--panel2);color:var(--text)}
  .sfoicon:active{transform:scale(.9)}
  .sfoicon .ic{width:17px;height:17px;vertical-align:0}

  /* 项目分组(手风琴;行的内边距/圆角走上面的统一规范) */
  .projgrp{gap:6px;margin-top:2px;color:var(--dim);font-size:var(--fs-md);font-weight:600;user-select:none}
  .projgrp:hover{color:var(--text)}
  .projgrp .pgcaret{margin-right:auto;color:var(--dim2)}  /* chevron 紧跟名称(间距走 projgrp 的 gap:6px),auto 外边距把按钮推到最右 */
  .projgrp .pgname{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dim2)}
  .projgrp .pgadd,.projgrp .pgmore{flex-shrink:0;opacity:0;background:none;border:none;cursor:pointer;
    color:var(--dim2);font-size:var(--fs-md);padding:1px var(--sp-2);border-radius:var(--r-sm);line-height:1}
  .projgrp:hover .pgadd,.projgrp:hover .pgmore{opacity:.6}
  .projgrp .pgadd:hover{opacity:1;color:var(--text);background:var(--card)}
  .projgrp .pgmore:hover,.projgrp .pgmore.on{opacity:1;color:var(--text);background:var(--card)}
  .projgrp.projadd{color:var(--dim2);font-weight:600;margin-top:4px}   /* 黑灰、无分割线、与分组同款行 */
  /* 「定时」Tab 两类任务的手风琴标题:VOCOCO 可管理任务 + 本机只读任务。 */
  .crongrp{cursor:pointer;margin-top:8px}
  .crongrp:first-child{margin-top:2px}
  .crongrp .pgcaret{margin-right:0;flex-shrink:0}
  .crongrp:focus-visible{outline:1px solid var(--accent);outline-offset:-1px}
  /* 项目拖拽排序:可拖起手型,拖起半透明,悬停目标高亮上边框示意插入位置 */
  .projgrp[draggable="true"]{cursor:grab}
  .projgrp.dragging,.conv.dragging{opacity:.4}
  .projgrp.dragover,.conv.dragover{box-shadow:inset 0 2px 0 var(--accent)}
  .conv.ingroup{margin-left:12px}   /* 分组下的会话缩进,体现层级 */
  /* 「展开更多」:分组超过 5 条时的第 6 行,颜色比普通会话行淡一档 */
  .conv.convmore{color:var(--dim2);font-size:var(--fs-md)}
  @media(hover:hover){ .conv.convmore:hover{color:var(--dim)} }

  /* 侧栏第二层 Tab(项目/置顶/最近),位于语音对话行下方、各分组内容上方——分段控件样式:
     整条淡底(panel)托着,选中项浮起一块更亮的 card 色块,不需要额外分割线 */
  .sidetabs{display:flex;gap:2px;margin:2px 2px 10px;padding:var(--sp-1);border-radius:var(--r-md);background:var(--panel)}
  .sidetab{flex:1;text-align:center;padding:var(--sp-2) var(--sp-1);border-radius:var(--r-md);font-size:var(--fs-md);
    color:var(--dim);cursor:pointer;user-select:none;transition:background var(--t-fast),color var(--t-fast)}
  @media(hover:hover){ .sidetab:hover{color:var(--text)} }
  .sidetab.active{background:var(--card);color:var(--text);font-weight:600}
  .tabempty{padding:var(--sp-5) var(--sp-4);color:var(--dim2);font-size:var(--fs-md);text-align:center}

  /* 新建项目弹窗(服务端目录浏览器) */
  #projModal{position:fixed;inset:0;z-index:60;display:flex;align-items:center;justify-content:center;background:var(--ov-3)}
  #projModal[hidden]{display:none}   /* id+attr 优先级压过上面的 display:flex,hidden 才真生效 */
  #projModal .pmbox{width:min(560px,92vw);max-height:82vh;display:flex;flex-direction:column;
    background:var(--panel);border:1px solid var(--line2);border-radius:var(--r-xl);overflow:hidden}
  #projModal .pmhead{padding:var(--sp-5) 18px;font-size:var(--fs-lg);font-weight:700;border-bottom:1px solid var(--line)}
  #projModal .pmpathrow{display:flex;gap:8px;padding:var(--sp-4) var(--sp-5)}
  #pmPath{flex:1;min-width:0;background:var(--panel2);border:1px solid var(--line2);border-radius:var(--r-md);
    color:var(--text);padding:var(--sp-3) var(--sp-4);font-size:var(--fs-md)}
  #projModal .pmgo{background:var(--panel2);border:1px solid var(--line2);border-radius:var(--r-md);color:var(--text);padding:0 var(--sp-5);cursor:pointer}
  #pmList{flex:1;overflow-y:auto;padding:var(--sp-1) var(--sp-4);min-height:120px}
  .pmrow{padding:var(--sp-3) var(--sp-4);border-radius:var(--r-md);cursor:pointer;font-size:var(--fs-md);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .pmrow:hover{background:var(--panel2)}
  .pmrow.pmup{color:var(--dim2)}
  #projModal .pmfoot{display:flex;gap:10px;justify-content:flex-end;padding:var(--sp-4) var(--sp-5);border-top:1px solid var(--line)}
  #projModal .pmfoot button{padding:var(--sp-3) var(--sp-5);border-radius:var(--r-md);cursor:pointer;font-size:var(--fs-md);border:1px solid var(--line2);background:var(--panel2);color:var(--text)}
  #projModal .pmfoot .pmok{background:var(--accent);border-color:var(--accent);color:var(--on-accent);font-weight:600}

  /* 会话搜索弹窗(⌘F / 侧栏放大镜):顶部搜索框 + 结果列表,标题命中排前正文其次 */
  #searchModal{position:fixed;inset:0;z-index:60;display:flex;align-items:flex-start;justify-content:center;
    background:var(--ov-3);padding-top:min(14vh,120px)}
  #searchModal[hidden]{display:none}
  #searchModal .smbox{width:min(560px,92vw);max-height:min(62vh,520px);display:flex;flex-direction:column;
    background:var(--panel);border:1px solid var(--line2);border-radius:var(--r-xl);overflow:hidden}
  #searchModal .smhead{display:flex;align-items:center;gap:9px;padding:var(--sp-4) var(--sp-5);border-bottom:1px solid var(--line)}
  #searchModal .smhead .ic{width:17px;height:17px;color:var(--dim2);flex-shrink:0}
  #smInput{flex:1;min-width:0;background:none;border:none;outline:none;color:var(--text);font-size:var(--fs-lg)}
  #smList{flex:1;overflow-y:auto;padding:var(--sp-2) var(--sp-3)}
  .smrow{padding:var(--sp-3) var(--sp-4);border-radius:var(--r-md);cursor:pointer}
  .smrow:hover,.smrow.sel{background:var(--panel2)}
  .smrow .smtitle{display:flex;align-items:center;gap:7px;font-size:var(--fs-md);min-width:0}
  .smrow .smtitle .t{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .smrow .smtime{color:var(--dim2);font-size:var(--fs-sm);flex-shrink:0}
  .smrow .smtag{flex-shrink:0;font-size:var(--fs-sm);color:var(--dim2);border:1px solid var(--line2);border-radius:var(--r-sm);padding:1px var(--sp-2)}
  .smrow .smsnip{margin-top:2px;font-size:var(--fs-sm);color:var(--dim2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .smrow b{color:var(--accent);font-weight:600}
  .smempty{padding:22px 0;text-align:center;color:var(--dim2);font-size:var(--fs-md)}

  /* 定时任务详情/编辑弹窗:抄新建项目弹窗同一套壳(pmbox/pmhead/pmfoot);只做「新建一条」
     或「编辑一条」,不兼列表——列表交给侧栏「定时任务」分组,启用/删除挪到该任务的
     「⋯」菜单(见 openConvMenu 里的 isCron 分支),不再放在这个弹窗里 */
  #cronModal{position:fixed;inset:0;z-index:60;display:flex;align-items:center;justify-content:center;background:var(--ov-3)}
  #cronModal[hidden]{display:none}
  #cronModal .pmbox{width:min(640px,92vw);max-height:85vh;display:flex;flex-direction:column;
    background:var(--panel);border:1px solid var(--line2);border-radius:var(--r-xl);overflow:hidden}
  #cronModal .pmhead{padding:var(--sp-5) 22px;font-size:var(--fs-xl);font-weight:700;border-bottom:1px solid var(--line)}
  #cronForm{padding:20px 22px;display:flex;flex-direction:column;gap:6px;overflow-y:auto;flex:1;min-height:0}
  #cronForm .cflabel{font-size:var(--fs-sm);font-weight:600;color:var(--dim);margin-top:6px}
  #cronForm .cflabel:first-child{margin-top:0}
  #cronForm input,#cronForm textarea,#cronForm select{background:var(--panel2);border:1px solid var(--line2);border-radius:var(--r-md);
    color:var(--text);padding:var(--sp-3) var(--sp-4);font-size:var(--fs-md);font-family:inherit;flex-shrink:0}
  #cronForm textarea{resize:none;min-height:38px;max-height:200px;overflow-y:auto;field-sizing:content}
  #cfScriptFields{display:flex;flex-direction:column;gap:6px;flex-shrink:0}
  #cronForm .cfrow{display:flex;gap:8px}
  #cronForm .cfrow select{flex:1;min-width:0}
  #cronForm .cfrow input{flex:1;min-width:0}
  #cronModal .pmfoot{display:flex;gap:10px;justify-content:flex-end;padding:var(--sp-5) 22px;border-top:1px solid var(--line);flex-shrink:0}
  #cronModal .pmfoot button{padding:var(--sp-3) 18px;border-radius:var(--r-md);cursor:pointer;font-size:var(--fs-md);border:1px solid var(--line2);background:var(--panel2);color:var(--text)}
  #cronModal .pmfoot .pmok{background:var(--accent);border-color:var(--accent);color:var(--on-accent);font-weight:600}

  /* 「定时」Tab 里的「本机系统任务」区块(launchd/crontab,只读,见 buildSystemTaskRow):
     区块小标题复用 .cmbadge 同款"小字大写"视觉语言;行本身复用 .conv/.cvbody/.ct/.ctime,
     只加一个状态徽标 */
  .systaskhdr{padding:var(--sp-4) var(--sp-4) var(--sp-1);color:var(--dim2);font-size:var(--fs-sm);font-weight:600;
    text-transform:uppercase;letter-spacing:.04em}
  .conv .stbadge{flex-shrink:0;font-size:var(--fs-sm);font-weight:600;padding:1px var(--sp-2);border-radius:var(--r-sm);
    border:1px solid var(--line2);color:var(--dim2)}
  .conv .stbadge.sterr{color:var(--err);border-color:var(--err)}
  .conv .stbadge.stok{color:var(--ok);border-color:var(--ok)}

  /* 本机系统任务详情弹窗(只读):抄 pmbox 壳,内容区域(脚本/日志)更大更能滚动 */
  #sysTaskModal{position:fixed;inset:0;z-index:60;display:flex;align-items:center;justify-content:center;background:var(--ov-3)}
  #sysTaskModal[hidden]{display:none}
  #sysTaskModal .pmbox{width:min(640px,94vw);max-height:82vh;display:flex;flex-direction:column;
    background:var(--panel);border:1px solid var(--line2);border-radius:var(--r-xl);overflow:hidden}
  #sysTaskModal .pmhead{display:flex;justify-content:space-between;align-items:center;gap:10px;
    padding:var(--sp-5) 18px;font-size:var(--fs-lg);font-weight:700;border-bottom:1px solid var(--line)}
  #stClose{background:none;border:none;color:var(--dim2);cursor:pointer;font-size:var(--fs-base);padding:var(--sp-1) var(--sp-2);border-radius:var(--r-sm)}
  #stClose:hover{background:var(--panel2);color:var(--text)}
  #stBody{flex:1;overflow-y:auto;padding:var(--sp-5) 18px}
  .stmeta{color:var(--dim);font-size:var(--fs-sm);line-height:1.6}
  .stseclabel{color:var(--dim2);font-size:var(--fs-sm);font-weight:600;text-transform:uppercase;letter-spacing:.03em;margin-top:12px}
  .stpre{background:var(--panel2);border:1px solid var(--line2);border-radius:var(--r-md);padding:var(--sp-4) var(--sp-4);
    font-size:var(--fs-sm);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;white-space:pre-wrap;
    word-break:break-all;color:var(--text);max-height:220px;overflow-y:auto;margin:4px 0 0}
  .stlogpath{color:var(--dim2);font-size:var(--fs-sm);margin-top:8px;word-break:break-all}
  .stlogempty{color:var(--dim2);font-size:var(--fs-sm);margin-top:4px}

  /* 删除/归档确认弹窗(worktree 有未提交改动时):同抄 pmbox 壳,合并成一组共用样式。
     删除场景主操作「归档保留」高亮、「仍然删除」危险红(删会连 worktree 内容一起丢);
     归档场景「确定归档」高亮、放弃走普通按钮 */
  #delModal,#archModal{position:fixed;inset:0;z-index:60;display:flex;align-items:center;justify-content:center;background:var(--ov-3)}
  #delModal[hidden],#archModal[hidden]{display:none}
  #delModal .pmbox,#archModal .pmbox{width:min(440px,92vw);display:flex;flex-direction:column;
    background:var(--panel);border:1px solid var(--line2);border-radius:var(--r-xl);overflow:hidden}
  #delModal .pmhead,#archModal .pmhead{padding:var(--sp-5) 18px;font-size:var(--fs-lg);font-weight:700;border-bottom:1px solid var(--line)}
  #delModal .pmbody,#archModal .pmbody{padding:var(--sp-5) 18px;font-size:var(--fs-md);color:var(--dim);line-height:1.6}
  #delModal .pmfoot,#archModal .pmfoot{display:flex;gap:10px;justify-content:flex-end;padding:var(--sp-4) var(--sp-5);border-top:1px solid var(--line)}
  #delModal .pmfoot button,#archModal .pmfoot button{padding:var(--sp-3) var(--sp-5);border-radius:var(--r-md);cursor:pointer;font-size:var(--fs-md);border:1px solid var(--line2);background:var(--panel2);color:var(--text)}
  #delModal .pmfoot .pmok,#archModal .pmfoot .pmok{background:var(--accent);border-color:var(--accent);color:var(--on-accent);font-weight:600}
  #delModal .pmfoot .pmwarn{background:transparent;border-color:var(--err);color:var(--err);font-weight:600}

  /* 设置弹窗 */
  #setModal{position:fixed;inset:0;z-index:60;display:flex;align-items:center;justify-content:center;background:var(--ov-3)}
  #setModal[hidden]{display:none}
  .setbox{width:min(820px,94vw);height:min(660px,88vh);display:flex;flex-direction:column;
    background:var(--panel);border:1px solid var(--line2);border-radius:var(--r-xl);overflow:hidden}
  .sethead{display:flex;align-items:center;padding:var(--sp-5) 18px;border-bottom:1px solid var(--line)}
  .sethead .settitle{flex:1;font-size:var(--fs-xl);font-weight:700}
  .setclose{width:32px;height:32px;border-radius:var(--r-md);color:var(--dim);font-size:var(--fs-xl);
    display:flex;align-items:center;justify-content:center;transition:background var(--t-fast),color var(--t-fast)}
  .setclose:hover{background:var(--panel2);color:var(--text)}
  .setbody{flex:1;display:flex;min-height:0}
  .settabs{flex-shrink:0;width:132px;padding:var(--sp-4) var(--sp-4);border-right:1px solid var(--line);
    display:flex;flex-direction:column;gap:3px;overflow-y:auto}
  .settab{text-align:left;padding:var(--sp-3) var(--sp-4);border-radius:var(--r-md);font-size:var(--fs-base);color:var(--dim);
    transition:background var(--t-fast),color var(--t-fast)}
  .settab:hover{background:var(--panel2);color:var(--text)}
  .settab.active{background:var(--panel2);color:var(--text);font-weight:600}
  .setpane{flex:1;overflow-y:auto;padding:18px 20px;min-width:0}

  /* 分区标题 + 说明 */
  .setpane h3{margin:0 0 4px;font-size:var(--fs-base);font-weight:700;display:flex;align-items:center;gap:7px}
  .setpane h3 .ic{width:16px;height:16px;color:var(--accent)}
  .setpane .shint{margin:0 0 14px;font-size:var(--fs-sm);color:var(--dim);line-height:1.55}
  .setpane .sechd{margin:20px 0 8px;font-size:var(--fs-sm);font-weight:700;color:var(--dim2);
    text-transform:uppercase;letter-spacing:.5px}

  /* 开关(switch) */
  .sw{position:relative;display:inline-block;width:38px;height:22px;flex-shrink:0}
  .sw input{opacity:0;width:0;height:0;position:absolute}
  .sw .track{position:absolute;inset:0;background:var(--line2);border-radius:22px;transition:background var(--t-base);cursor:pointer}
  .sw .track::before{content:"";position:absolute;left:3px;top:3px;width:16px;height:16px;
    background:#fff;border-radius:50%;transition:transform var(--t-base);box-shadow:0 1px 3px rgba(0,0,0,.3)}
  .sw input:checked + .track{background:var(--accent)}
  .sw input:checked + .track::before{transform:translateX(16px)}

  /* 行:一条设置项(左内容 + 右开关) */
  .srow{display:flex;align-items:center;gap:12px;padding:var(--sp-4) 0;border-bottom:1px solid var(--line)}
  .srow:last-child{border-bottom:none}
  .srow .sinfo{flex:1;min-width:0}
  .srow .sname{font-size:var(--fs-base);font-weight:600;color:var(--text);word-break:break-word}
  .srow .sdesc{font-size:var(--fs-sm);color:var(--dim);margin-top:2px;line-height:1.5;
    display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .srow .sacts{display:flex;align-items:center;gap:12px;flex-shrink:0}
  .srow .miniact{font-size:var(--fs-sm);color:var(--dim);padding:var(--sp-1) var(--sp-2);border-radius:var(--r-sm);transition:background var(--t-fast),color var(--t-fast);white-space:nowrap}
  .srow .miniact:hover{background:var(--panel2);color:var(--text)}
  .srow .miniact.on{color:var(--accent)}
  .srow .miniact.danger:hover{color:var(--err);background:rgba(209,103,74,.12)}
  .srow.off .sname{color:var(--dim)}

  /* 技能作用范围:通用会话 / 明确选择的 Git 编程项目 */
  .skScope{display:flex;gap:4px;margin:12px 0 8px;padding:var(--sp-1);background:var(--panel2);border-radius:var(--r-md);width:max-content}
  .skScope button{padding:var(--sp-2) var(--sp-3);border-radius:var(--r-sm);color:var(--dim);font-size:var(--fs-sm);transition:background var(--t-fast),color var(--t-fast)}
  .skScope button.active{background:var(--panel);color:var(--text);box-shadow:0 1px 2px rgba(0,0,0,.12)}

  /* 技能搜索框 + 计数 */
  .skbar{display:flex;align-items:center;gap:8px;margin-bottom:6px}
  .sksearch{flex:1;display:flex;align-items:center;gap:7px;background:var(--panel2);
    border:1px solid var(--line2);border-radius:var(--r-md);padding:var(--sp-2) var(--sp-4)}
  .sksearch .ic{width:15px;height:15px;color:var(--dim2)}
  .sksearch input{flex:1;min-width:0;background:none;border:none;outline:none;color:var(--text);font-size:var(--fs-md)}

  /* 通用按钮 */
  .btn{padding:var(--sp-3) var(--sp-5);border-radius:var(--r-md);font-size:var(--fs-md);border:1px solid var(--line2);
    background:var(--panel2);color:var(--text);cursor:pointer;transition:background var(--t-fast),border-color var(--t-fast)}
  .btn:hover{background:var(--card)}
  .btn.primary{background:var(--accent);border-color:var(--accent);color:var(--on-accent);font-weight:600}
  .btn.primary:hover{background:var(--accent2)}
  .btn.ghost{background:none;border-color:var(--line2)}
  .btn.sm{padding:var(--sp-2) var(--sp-4);font-size:var(--fs-sm)}
  .setrowbtns{display:flex;gap:9px;flex-wrap:wrap;margin-top:16px}

  /* 数据面板(设置 → 数据):总览 + 会话明细 */
  .stbar{display:flex;align-items:center;gap:var(--sp-3);margin-bottom:var(--sp-4);flex-wrap:wrap}
  .stx{display:flex;gap:var(--sp-1);padding:var(--sp-1);background:var(--panel2);border-radius:var(--r-md)}
  .stx button{padding:var(--sp-2) var(--sp-4);border-radius:var(--r-sm);color:var(--dim);font-size:var(--fs-sm);
    transition:background var(--t-fast),color var(--t-fast)}
  .stx button.active{background:var(--panel);color:var(--text);box-shadow:0 1px 2px rgba(0,0,0,.12)}
  .stkpi{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--sp-3);margin-bottom:var(--sp-5)}
  .stkpi .k{background:var(--bg2);border:1px solid var(--line);border-radius:var(--r-lg);padding:var(--sp-4)}
  .stkpi .k .n{font-size:20px;font-weight:700;letter-spacing:-.3px;font-variant-numeric:tabular-nums}
  .stkpi .k .l{font-size:var(--fs-sm);color:var(--dim)}
  .stkpi .k .d{font-size:var(--fs-sm);color:var(--dim2);margin-top:2px}
  .stsec{margin-bottom:var(--sp-5)}
  /* 日历:一格一天,按时间顺序连续排列、满宽自动换行。
     不用 GitHub 那种"一列一周"的排法——那种要固定 53 列才好看,而这里历史只有几十天时
     会空出大半张图;auto-fill 让列数跟着面板宽度走,几十天是两行,一年就是八行,始终填满。 */
  .stcal{display:grid;grid-template-columns:repeat(auto-fill,minmax(13px,1fr));gap:2px}
  .stcal .cel{aspect-ratio:1;border-radius:2px;background:var(--panel2)}
  .stcal .cel.mstart{box-shadow:inset 0 0 0 1px var(--line2)}  /* 每月 1 号描边,当刻度用 */
  .stlg{display:flex;align-items:center;gap:var(--sp-2);color:var(--dim2);font-size:var(--fs-sm);margin-top:var(--sp-2)}
  .stlg .cel{width:11px;height:11px;border-radius:2px;background:var(--panel2)}
  .sttab{width:100%;border-collapse:collapse;font-size:var(--fs-sm)}
  .sttab th{text-align:left;color:var(--dim2);font-weight:600;border-bottom:1px solid var(--line);padding:var(--sp-2) var(--sp-1)}
  .sttab td{padding:var(--sp-2) var(--sp-1);border-bottom:1px solid var(--line);font-variant-numeric:tabular-nums}
  .sttab .r{text-align:right}
  .stdot{display:inline-block;width:7px;height:7px;border-radius:50%;margin-right:var(--sp-2)}
  .ststack{display:flex;height:18px;border-radius:var(--r-sm);overflow:hidden;margin-bottom:var(--sp-3)}
  .stbars{display:flex;align-items:flex-end;gap:2px;height:88px}
  .stbars i{flex:1;background:linear-gradient(180deg,var(--accent),var(--accent2));border-radius:2px 2px 0 0;min-height:2px}
  .sttip-target{cursor:default}
  .sttip{position:fixed;z-index:90;max-width:calc(100vw - var(--sp-5));padding:var(--sp-2) var(--sp-3);
    border:1px solid var(--line2);border-radius:var(--r-md);background:var(--card);color:var(--text);
    box-shadow:var(--shadow);font-size:var(--fs-sm);line-height:1.5;white-space:pre-line;pointer-events:none}
  .sttip[hidden]{display:none}
  .stmini{height:6px;background:var(--panel2);border-radius:var(--r-pill);overflow:hidden}
  .stmini i{display:block;height:100%;background:var(--accent);border-radius:var(--r-pill)}
  .stgrid2{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-5)}
  .stchips{display:flex;flex-wrap:wrap;gap:var(--sp-2);margin-top:var(--sp-3)}
  .stchip{background:var(--panel2);border:1px solid var(--line);border-radius:var(--r-pill);
    padding:1px var(--sp-3);font-size:var(--fs-sm);color:var(--dim)}
  .stchip.bad{color:var(--err-fg);border-color:var(--err-line);background:var(--err-bg)}
  .stchip.good{color:var(--ok-fg);border-color:var(--ok-line);background:var(--ok-bg)}
  .stsrch{display:flex;align-items:center;gap:var(--sp-2);background:var(--panel2);border:1px solid var(--line2);
    border-radius:var(--r-md);padding:var(--sp-2) var(--sp-4);margin-bottom:var(--sp-3)}
  .stsrch .ic{width:15px;height:15px;color:var(--dim2)}
  .stsrch input{flex:1;min-width:0;background:none;border:none;outline:none;color:var(--text);font-size:var(--fs-md)}
  .strow{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-3) var(--sp-2);
    border-bottom:1px solid var(--line);cursor:pointer;transition:background var(--t-fast)}
  .strow:hover{background:var(--panel2)}
  .strow .t{flex:1;min-width:0}
  .strow .t .nm{font-size:var(--fs-md);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .strow .t .mt{font-size:var(--fs-sm);color:var(--dim2);margin-top:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .strow .num{text-align:right;font-size:var(--fs-sm);font-variant-numeric:tabular-nums;flex-shrink:0;min-width:52px}
  .strow .num b{display:block;font-size:var(--fs-md);font-weight:600}
  .strow .num span{color:var(--dim2)}
  .stdet{background:var(--bg2);border:1px solid var(--line);border-radius:var(--r-lg);padding:var(--sp-5)}
  .stdet h4{margin:0 0 var(--sp-1);font-size:var(--fs-base)}
  .stdet .kv{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--sp-3);margin:var(--sp-4) 0}
  .stdet .kv span{display:block;font-size:var(--fs-sm);color:var(--dim2)}
  .stdet .kv b{font-size:var(--fs-lg);font-variant-numeric:tabular-nums}
  @media(max-width:640px){
    .stkpi{grid-template-columns:repeat(2,1fr)}
    .stgrid2{grid-template-columns:1fr}
    .stdet .kv{grid-template-columns:repeat(2,1fr)}
  }

  /* 外部 MCP 添加表单 */
  .mcpform{background:var(--bg2);border:1px solid var(--line);border-radius:var(--r-lg);padding:var(--sp-5);margin-top:8px}
  .mcpform .fld{margin-bottom:10px}
  .mcpform .fld:last-child{margin-bottom:0}
  .mcpform label{display:block;font-size:var(--fs-sm);color:var(--dim);margin-bottom:4px}
  .mcpform input,.mcpform textarea,.mcpform select{width:100%;background:var(--panel2);
    border:1px solid var(--line2);border-radius:var(--r-md);color:var(--text);padding:var(--sp-3) var(--sp-4);font-size:var(--fs-md);
    font-family:inherit}
  .mcpform textarea{resize:vertical;min-height:52px;font-family:ui-monospace,Menlo,monospace;font-size:var(--fs-sm)}
  .mcpform input:focus,.mcpform textarea:focus,.mcpform select:focus{outline:none;border-color:var(--accent)}
  .mcperr{color:var(--err);font-size:var(--fs-sm);margin-top:8px;min-height:16px}
  .mctag{display:inline-block;font-size:var(--fs-sm);color:var(--dim2);border:1px solid var(--line2);
    border-radius:var(--r-sm);padding:1px var(--sp-2);margin-left:8px;font-family:ui-monospace,Menlo,monospace}
  .mctag.cur{color:var(--accent);border-color:var(--accent);font-family:inherit;font-weight:600}

  /* 文件列表 + 编辑器(记忆 / 人设) */
  .frow{display:flex;align-items:center;gap:10px;padding:var(--sp-4) 0;border-bottom:1px solid var(--line);cursor:pointer;transition:opacity var(--t-fast)}
  .frow:hover .fname{color:var(--accent)}
  .frow .ic{width:16px;height:16px;color:var(--dim);flex-shrink:0}
  .frow .fname{flex:1;font-size:var(--fs-md);color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace,Menlo,monospace}
  .frow .fmiss{font-size:var(--fs-sm);color:var(--dim2)}
  .frow .fchev{color:var(--dim2);font-size:var(--fs-lg)}
  .feditor{display:flex;flex-direction:column;height:100%}
  .feditor .fetop{display:flex;align-items:center;gap:10px;margin-bottom:10px}
  .feditor .feback{font-size:var(--fs-md);color:var(--dim);padding:var(--sp-2) var(--sp-3);border-radius:var(--r-md);transition:background var(--t-fast),color var(--t-fast)}
  .feditor .feback:hover{background:var(--panel2);color:var(--text)}
  .feditor .fepath{flex:1;font-size:var(--fs-md);font-weight:600;font-family:ui-monospace,Menlo,monospace;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .feditor textarea{flex:1;width:100%;background:var(--code-bg);color:var(--code-fg);
    border:1px solid var(--line2);border-radius:var(--r-lg);padding:var(--sp-5);font-size:var(--fs-md);line-height:1.6;
    font-family:ui-monospace,Menlo,monospace;resize:none;outline:none}
  .feditor textarea:focus{border-color:var(--accent)}
  .fesave{display:flex;align-items:center;gap:10px;margin-top:12px}
  .fesave .festat{font-size:var(--fs-sm);color:var(--dim);flex:1}
  .fesave .festat.ok{color:var(--ok)}
  .setempty{text-align:center;color:var(--dim2);font-size:var(--fs-md);padding:30px var(--sp-4)}
  .setload{text-align:center;color:var(--dim2);font-size:var(--fs-md);padding:24px}

  /* 外观:主题分段选择器 */
  .theme-seg{display:flex;border:1px solid var(--line2);border-radius:var(--r-md);overflow:hidden;width:fit-content;margin-top:4px}
  .theme-seg .tsopt{padding:var(--sp-3) 20px;font-size:var(--fs-md);color:var(--dim);transition:background var(--t-fast),color var(--t-fast);border-right:1px solid var(--line2)}
  .theme-seg .tsopt:last-child{border-right:none}
  .theme-seg .tsopt:not(.active):hover{background:var(--panel2);color:var(--text)}
  .theme-seg .tsopt.active{background:var(--accent);color:var(--on-accent);font-weight:600;cursor:default}

  @media(max-width:640px){
    .setbox{width:100vw;height:100%;max-height:100%;border-radius:0;border:none}
    .sethead{padding-top:calc(14px + env(safe-area-inset-top))}
    .setbody{flex-direction:column}
    .settabs{width:auto;flex-direction:row;border-right:none;border-bottom:1px solid var(--line);
      padding:var(--sp-3) var(--sp-4);gap:6px;overflow-x:auto}
    .settab{white-space:nowrap;flex-shrink:0}
    .setpane{padding:var(--sp-5)}
  }

  /* 主区 */
  main{flex:1;display:flex;flex-direction:column;min-width:0;position:relative;background:var(--bg2);overflow:hidden}
  /* #chatMain 和 #callView 都是 main 标签,上面这条 main{display:flex} 是作者样式,
     会盖掉浏览器默认的 [hidden]{display:none}(UA 样式在层叠里天然让位于作者样式,
     跟选择器优先级无关)——两边互斥显隐都得补一条这样的覆盖,不然 openCallView()
     切 hidden 属性没用,#app 的 flex 布局会把两个 main 各分一半宽度摆成左右分屏。 */
  #chatMain[hidden]{display:none}
  header.bar{padding:var(--sp-4) 32px;
    padding-top:calc(11px + env(safe-area-inset-top));
    background:var(--bar-bg);backdrop-filter:blur(14px);
    -webkit-backdrop-filter:blur(14px);position:absolute;top:0;left:0;right:0;z-index:10;
    transition:transform .35s cubic-bezier(.4,0,.2,1)}
  header.bar .barwrap{max-width:820px;margin:0 auto;display:flex;align-items:center;gap:8px}
  .icon{width:38px;height:38px;border-radius:var(--r-lg);display:flex;align-items:center;justify-content:center;
    font-size:19px;color:var(--dim);flex-shrink:0;transition:background var(--t-fast),color var(--t-fast)}
  .icon:hover{background:var(--panel2);color:var(--text)}
  .icon:active{transform:scale(.92)}
  header.bar .title{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:center;line-height:1.25}
  header.bar .title #convTitle{font-size:var(--fs-lg);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  header.bar .title .tsub{display:flex;align-items:center;gap:8px;min-width:0}
  #projBox{position:relative;flex-shrink:1;min-width:0}
  #gitBox{position:relative;flex-shrink:0}
  .tgit{font-size:var(--fs-sm);color:var(--dim);font-weight:500;font-variant-numeric:tabular-nums;
    background:var(--panel2);border-radius:var(--r-sm);padding:1.5px var(--sp-2);max-width:190px;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:background var(--t-fast),color var(--t-fast)}
  .tgit:hover{color:var(--text)}
  .tgit.dirty{color:var(--accent)}
  .tgit .gahb{color:var(--accent);font-weight:700}   /* 标题栏未合并提交标记 ↑N */
  .tgit[hidden]{display:none}
  .tgit.tproj{max-width:140px}
  /* 项目路径弹层:点项目名 pill 弹出完整路径 */
  #projPop{position:absolute;top:calc(100% + 8px);left:0;z-index:20;width:288px;
    background:var(--card);border:1px solid var(--line2);border-radius:var(--r-lg);padding:var(--sp-4) var(--sp-4);
    box-shadow:var(--shadow);animation:pop .18s ease}
  #projPop[hidden]{display:none}
  #projPop .ppath{font-size:var(--fs-sm);color:var(--text);word-break:break-all;font-family:ui-monospace,Menlo,monospace}
  /* Git 状态弹层 */
  #gitPop{position:absolute;top:calc(100% + 8px);left:0;width:288px;z-index:20;
    background:var(--card);border:1px solid var(--line2);border-radius:var(--r-xl);padding:var(--sp-5);
    box-shadow:var(--shadow);animation:pop .18s ease}
  #gitPop[hidden]{display:none}
  #gitPop .gph{display:flex;justify-content:space-between;align-items:baseline;gap:8px;margin-bottom:4px}
  #gitPop .gbr{font-size:var(--fs-md);font-weight:600;color:var(--accent);display:inline-flex;align-items:center;gap:6px}
  #gitPop .gah{font-size:var(--fs-sm);color:var(--dim);font-variant-numeric:tabular-nums}
  #gitPop .gsub{font-size:var(--fs-sm);color:var(--dim2);word-break:break-all;margin-bottom:var(--sp-2);
    font-family:ui-monospace,Menlo,monospace}
  #gitPop .gsum{font-size:var(--fs-sm);color:var(--dim);padding-bottom:var(--sp-2);
    border-bottom:1px solid var(--line);margin-bottom:var(--sp-2)}
  #gitPop .gclean{font-size:var(--fs-sm);color:var(--dim);padding:2px 0 var(--sp-1)}
  #gitPop .gfiles{max-height:220px;overflow:auto}
  #gitPop .ggrp{font-size:var(--fs-sm);color:var(--dim2);font-weight:600;padding:var(--sp-2) 0 2px}
  #gitPop .gf{display:flex;gap:8px;align-items:baseline;font-size:var(--fs-sm);padding:2px 0}
  #gitPop .gf .gx{flex-shrink:0;width:20px;color:var(--accent);font-family:ui-monospace,Menlo,monospace}
  #gitPop .gf .gp{color:var(--text);word-break:break-all}
  #gitPop .gmore{font-size:var(--fs-sm);color:var(--dim);padding-top:var(--sp-2)}
  #gitPop .gempty{font-size:var(--fs-sm);color:var(--dim)}
  .gdot{display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--ok-fg);flex-shrink:0}
  .gdot-warn{background:var(--warn)}
  .gdot-err{background:var(--err-fg)}
  #ctxBox{position:relative;flex-shrink:0;display:flex;align-items:center;gap:6px}
  /* 标题栏图标操作统一为正方形：定时任务与普通会话共用，避免 hover 灰底横向膨胀。 */
  .hmore{width:28px;height:28px;padding:0;border-radius:var(--r-md);font-size:18px;line-height:1;color:var(--dim2);
    cursor:pointer;transition:background var(--t-fast),color var(--t-fast);flex-shrink:0;display:flex;align-items:center;justify-content:center}
  .hmore:hover,.hmore.on{color:var(--text);background:var(--panel2)}
  .hmore[hidden]{display:none}
  .hmore .ic{width:16px;height:16px}
  /* 定时任务启停开关:标题栏右侧直出,不藏进「⋯」 */
  .hswitch{width:34px;height:20px;border-radius:var(--r-md);background:var(--line2);position:relative;
    cursor:pointer;flex-shrink:0;transition:background var(--t-fast)}
  .hswitch.on{background:var(--accent)}
  .hswitch::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;
    border-radius:50%;background:#fff;transition:transform var(--t-fast)}
  .hswitch.on::after{transform:translateX(14px)}
  .hswitch[hidden]{display:none}
  #barMeta{display:flex;align-items:center;gap:7px;font-size:var(--fs-sm);color:var(--dim);
    font-weight:500;font-variant-numeric:tabular-nums;padding:var(--sp-2) var(--sp-3);border-radius:var(--r-md);transition:background var(--t-fast)}
  #barMeta:hover{background:var(--panel2)}
  #barMeta[hidden]{display:none}
  #barMeta .ctxring{width:20px;height:20px;flex-shrink:0}
  #barMeta .ctxring .track{fill:none;stroke:var(--panel2);stroke-width:2.5}
  #barMeta .ctxring .fill{fill:none;stroke:var(--accent);stroke-width:2.5;stroke-linecap:round;
    transform:rotate(-90deg);transform-origin:center;transition:stroke-dashoffset .45s ease,stroke .3s}
  #barMeta.warn .ctxring .fill{stroke:var(--err)}
  #barMeta.warn #ctxPct{color:var(--err)}
  /* 上下文明细弹层(默认收起,点进度条展开)*/
  #ctxPop{position:absolute;top:calc(100% + 8px);right:0;width:248px;z-index:20;
    background:var(--card);border:1px solid var(--line2);border-radius:var(--r-xl);padding:var(--sp-5);
    box-shadow:var(--shadow);animation:pop .18s ease;font-variant-numeric:tabular-nums}
  #ctxPop[hidden]{display:none}
  #ctxPop .ph{display:flex;justify-content:space-between;align-items:baseline;gap:8px;margin-bottom:9px}
  #ctxPop .ph .t{font-size:var(--fs-sm);color:var(--dim)}
  #ctxPop .ph .m{font-size:var(--fs-md);font-weight:600}
  #ctxPop .ph .m b{color:var(--accent)}
  #ctxPop.warn .ph .m b{color:var(--err)}
  #ctxPop .pbar{height:6px;border-radius:var(--r-sm);background:var(--panel2);overflow:hidden;margin-bottom:11px}
  #ctxPop .pbar i{display:block;height:100%;border-radius:var(--r-sm);background:linear-gradient(90deg,var(--accent),var(--user2))}
  #ctxPop.warn .pbar i{background:var(--err)}
  #ctxPop .pr{display:flex;justify-content:space-between;align-items:center;gap:10px;font-size:var(--fs-sm);padding:4.5px 0;color:var(--text)}
  #ctxPop .pr .k{color:var(--dim)}
  #ctxPop .pr .v .pp{color:var(--dim2);margin-left:5px}
  #ctxPop .pr.sub .k{padding-left:var(--sp-4);color:var(--dim2);font-size:var(--fs-sm)}
  #ctxPop .pr.sep{border-top:1px solid var(--line);margin-top:4px;padding-top:var(--sp-3)}
  #ctxPop .pr .mdl{font-size:var(--fs-sm);color:var(--dim);font-family:ui-monospace,Menlo,monospace}
  /* 上下文明细弹层里的会话 ID */
  #ctxPop .convid{display:flex;align-items:center;gap:8px;font-size:var(--fs-sm);padding:var(--sp-1) 0 var(--sp-3);border-bottom:1px solid var(--line);margin-bottom:8px}
  #ctxPop .convid .k{color:var(--dim);flex-shrink:0}
  #ctxPop .convid .idv{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace,Menlo,monospace;color:var(--text)}
  #ctxPop .convid .cpy{width:24px;height:24px;border-radius:var(--r-sm);display:flex;align-items:center;justify-content:center;color:var(--dim2);transition:background var(--t-fast),color var(--t-fast);flex-shrink:0}
  #ctxPop .convid .cpy:hover{background:var(--panel2);color:var(--text)}
  /* 会话文档弹层:只列文档，不把工具卡里大量代码文件塞进来 */
  #convDocsPop{position:absolute;top:calc(100% + 8px);right:0;width:min(360px,calc(100vw - 24px));z-index:20;
    background:var(--card);border:1px solid var(--line2);border-radius:var(--r-xl);box-shadow:var(--shadow);animation:pop .18s ease;overflow:hidden}
  #convDocsPop[hidden]{display:none}
  #convDocsPop .cdhead{padding:var(--sp-4) var(--sp-4) var(--sp-3);font-size:var(--fs-sm);font-weight:600;color:var(--text);display:flex;justify-content:space-between}
  #convDocsPop .cdhead span{font-weight:500;color:var(--dim)}
  #convDocsPop .cdlist{max-height:340px;overflow:auto;padding:0 var(--sp-2) var(--sp-2)}
  #convDocsPop .cdrow{width:100%;display:flex;align-items:flex-start;gap:8px;padding:var(--sp-3) var(--sp-2);border-radius:var(--r-md);text-align:left;color:var(--text);cursor:pointer}
  #convDocsPop .cdrow:hover{background:var(--panel2)}
  #convDocsPop .cdicon{color:var(--accent);padding-top:2px;flex-shrink:0}
  #convDocsPop .cdicon .ic{width:16px;height:16px}
  #convDocsPop .cdmain{min-width:0;flex:1;display:flex;flex-direction:column;gap:2px}
  #convDocsPop .cdname{font-size:var(--fs-sm);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  #convDocsPop .cdpath{font-size:var(--fs-sm);color:var(--dim2);font-family:ui-monospace,Menlo,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  #convDocsPop .cdactions{display:flex;gap:3px;flex-wrap:wrap;justify-content:flex-end;padding-top:1px}
  #convDocsPop .cdactions i{font-style:normal;font-size:var(--fs-sm);color:var(--dim);background:var(--panel2);border-radius:var(--r-sm);padding:2px var(--sp-1);white-space:nowrap}
  #convDocsPop .cdempty{padding:var(--sp-5) var(--sp-4);color:var(--dim);font-size:var(--fs-sm)}
  #hamb{display:none;width:42px;height:42px;font-size:21px;border-radius:var(--r-lg)}
  #hamb .ic{width:19px;height:19px}

  #messages{flex:1;overflow-y:auto;scrollbar-gutter:stable;padding:18px 32px var(--sp-3);
    /* JS 实测到就用精确顶栏高;没测到(或时机太早)时兜底也要含顶部安全区,
       否则刘海机上第一条消息会被不透明顶栏盖住看不见。max 取两者较大者,双保险。 */
    padding-top:calc(18px + max(var(--header-h, 0px), 62px + env(safe-area-inset-top)));
    padding-bottom:calc(8px + var(--composer-h, 104px));
    -webkit-overflow-scrolling:touch;position:relative;
    transition:padding .35s cubic-bezier(.4,0,.2,1)}
  #scrollDownBtn{position:fixed;bottom:calc(16px + var(--composer-h, 104px));right:24px;z-index:50;
    width:40px;height:40px;border-radius:50%;background:var(--bg2);border:1px solid var(--line);
    color:var(--dim);font-size:18px;display:flex;align-items:center;justify-content:center;
    cursor:pointer;box-shadow:0 2px 10px rgba(0,0,0,.2);transition:opacity var(--t-base),transform var(--t-base);
    opacity:0;transform:translateY(8px);pointer-events:none}
  #scrollDownBtn.show{opacity:1;transform:translateY(0);pointer-events:auto}
  #scrollDownBtn:hover{background:var(--hover);color:var(--text)}
  .wrap{max-width:820px;margin:0 auto}
  .row{display:flex;margin:10px 0;animation:pop .32s cubic-bezier(.2,.7,.3,1)}
  .row.me{justify-content:flex-end}
  .row.ai{display:block;margin:0}
  .row.sys{justify-content:center}
  .row.sys .sysnote{font-size:var(--fs-sm);color:var(--dim2);background:var(--card);
    border:1px solid var(--line);border-radius:var(--r-pill);padding:var(--sp-2) var(--sp-5);max-width:90%;text-align:center}
  .bubble{max-width:86%;padding:var(--sp-4) var(--sp-5);border-radius:var(--radius);white-space:normal;word-wrap:break-word;
    overflow-wrap:anywhere;box-shadow:var(--bubble-shadow)}
  .row.me .bubble{background:linear-gradient(135deg,var(--user1),var(--user2));color:var(--on-user);border-bottom-right-radius:6px;white-space:pre-wrap}
  .row.ai .bubble{background:transparent;border-radius:var(--radius);max-width:100%;margin:4px 0 10px;display:block;box-shadow:none;padding:0}
  .bubble.pending{color:var(--dim)}
  .status{font-size:var(--fs-sm);color:var(--dim);margin:0;display:flex;flex-wrap:wrap;gap:4px 12px}
  .status .chip{display:inline-flex;align-items:center}
  .status .chip.live{color:var(--accent)}
  .status .statusstop{margin-left:auto;flex-shrink:0;width:24px;height:24px;border-radius:50%;
    background:var(--err);color:var(--on-accent);font-size:var(--fs-sm);line-height:1;display:inline-flex;
    align-items:center;justify-content:center;cursor:pointer;border:none}
  .status .statusstop:hover{filter:brightness(1.1)}
  .status .statusstop:active{transform:scale(.9)}
  .status .statusstop .sq{width:9px;height:9px;border-radius:2px;background:#fff}
  .dots{display:inline-flex;gap:3px;margin-left:5px;align-items:center}
  .dots i{width:4px;height:4px;border-radius:50%;background:currentColor;opacity:.28;animation:blink 1.2s infinite}
  .dots i:nth-child(2){animation-delay:.2s} .dots i:nth-child(3){animation-delay:.4s}
  @keyframes blink{0%,60%,100%{opacity:.28} 30%{opacity:1}}
  @keyframes pop{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
  .think{font-size:var(--fs-md);color:var(--dim);border-left:2px solid var(--line2);padding:2px 0 2px var(--sp-4);margin-bottom:8px;
    white-space:pre-wrap;max-height:140px;overflow:auto;display:none}
  .think.show{display:block}
  .thinktog{font-size:var(--fs-sm);color:var(--accent);margin-bottom:6px;display:none;align-items:center;gap:6px;cursor:pointer;user-select:none}

  /* markdown */
  .bubble p{margin:.5em 0}
  .bubble p:first-child{margin-top:0}.bubble p:last-child{margin-bottom:0}
  .bubble h1,.bubble h2,.bubble h3,.bubble h4{margin:.7em 0 .4em;line-height:1.3}
  .bubble h1{font-size:1.35em}.bubble h2{font-size:1.2em}.bubble h3{font-size:1.08em}
  .bubble ul,.bubble ol{margin:.4em 0;padding-left:1.3em}
  .bubble li{margin:.2em 0}
  .bubble code{background:var(--code-inline);padding:.12em .4em;border-radius:var(--r-sm);font-size:.9em;
    font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
  .row.me code{background:rgba(255,255,255,.2)}
  .codeblock{position:relative;margin:.6em 0}
  .codeblock .codecopy{position:absolute;top:8px;right:8px;width:26px;height:26px;display:flex;align-items:center;
    justify-content:center;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel2);color:var(--dim);
    cursor:pointer;opacity:.7}
  .codeblock .codecopy:hover{opacity:1}
  .codeblock .codecopy .ic{width:14px;height:14px}
  .bubble pre.code{background:var(--code-bg);border:1px solid var(--line);border-radius:var(--r-lg);padding:var(--sp-4) var(--sp-5);
    padding-right:40px;overflow-x:auto;margin:0}
  .bubble pre.code code{background:none;padding:0;font-size:.86em;line-height:1.5;color:var(--code-fg);
    white-space:pre-wrap;word-break:break-word}
  .bubble blockquote{margin:.5em 0;padding:.2em .9em;border-left:3px solid var(--accent2);color:var(--dim)}
  .bubble table{border-collapse:collapse;margin:.6em 0;width:100%;font-size:.92em;display:block;overflow-x:auto}
  .bubble th,.bubble td{border:1px solid var(--line);padding:var(--sp-2) var(--sp-4);text-align:left}
  .bubble th{background:var(--panel2);font-weight:600}
  .bubble a{word-break:break-all}
  .bubble img{max-width:100%;border-radius:var(--r-md)}
  .imgs{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
  .imgs img{width:120px;height:120px;object-fit:cover;border-radius:var(--r-md);cursor:zoom-in}
  .auds{display:flex;flex-direction:column;gap:6px;margin-top:8px}
  .audiorow .audioname{margin-bottom:var(--sp-1);font-size:var(--fs-sm);color:var(--dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .audiorow audio{width:100%;max-width:320px;height:36px}
  .audiorow .atranscript{margin-top:4px;font-size:var(--fs-sm);color:var(--dim)}
  .audiorow .atranscript summary{cursor:pointer;color:var(--accent)}
  .audiorow .atranscript div{margin-top:4px;white-space:pre-wrap;color:var(--text)}
  /* 视频组:气泡内的播放器/「点击加载」占位按钮,见 stream.js appendVids */
  .vids{display:flex;flex-direction:column;gap:var(--sp-2);margin-top:var(--sp-2)}
  .videorow .videohead{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-2);margin-bottom:var(--sp-1)}
  .videorow .videoname{font-size:var(--fs-sm);color:var(--dim);
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .videorow .videodl{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;flex-shrink:0;
    margin-left:auto;border-radius:var(--r-sm);color:var(--dim);cursor:pointer;opacity:.7;border:none;background:none;
    transition:background var(--t-fast),color var(--t-fast),opacity var(--t-fast)}
  .videorow .videodl:hover{opacity:1;background:var(--panel2);color:var(--text)}
  .videorow .videodl:has(.dllabel){width:auto;gap:var(--sp-1);padding:0 var(--sp-2);opacity:1;color:var(--text)}
  .videorow .videodl.ready{color:var(--accent)}
  .videorow .videodl .dllabel{font-size:var(--fs-sm);white-space:nowrap;font-variant-numeric:tabular-nums}
  .videorow .videodl .ic{width:14px;height:14px}
  .videorow video{width:100%;max-width:360px;border-radius:var(--r-md);background:#000;display:block}
  .videorow .videoerr{display:inline-flex;align-items:center;margin-top:var(--sp-2);padding:var(--sp-2) var(--sp-4);
    border-radius:var(--r-xl);background:var(--panel2);border:1px solid var(--err);color:var(--err);
    font-size:var(--fs-sm);cursor:pointer;transition:background var(--t-fast)}
  /* AI 消息底部:回复时间 + 复制/重新生成小按钮,见 buildTurnFoot */
  .turnfoot{display:flex;align-items:center;gap:2px;margin-top:4px;min-height:24px}
  .turnfoot .tftime{font-size:var(--fs-sm);color:var(--dim2);margin-right:2px;font-variant-numeric:tabular-nums;user-select:none}
  .turnfoot .tfbtn{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;
    border-radius:var(--r-sm);color:var(--dim);cursor:pointer;opacity:.6;flex-shrink:0;border:none;background:none;
    transition:background var(--t-fast),color var(--t-fast),opacity var(--t-fast)}
  .turnfoot .tfbtn:hover{opacity:1;background:var(--panel2);color:var(--text)}
  .turnfoot .tfbtn:active{transform:scale(.9)}
  .turnfoot .tfbtn:disabled{opacity:.3;cursor:default}
  .turnfoot .tfbtn .ic{width:14px;height:14px}
  .turnfoot .tfregen:disabled .ic{animation:spin .8s linear infinite}
  /* 重启中断的回复:「继续生成」按钮(见 buildTurnFoot interrupted=true)要高亮醒目 */
  .turnfoot .tfbtn.tfrgen-resume{width:auto;padding:0 var(--sp-4);height:26px;font-size:var(--fs-sm);font-weight:600;
    color:var(--on-accent);background:var(--accent);opacity:1;border-radius:var(--r-md);margin-left:4px}
  .turnfoot .tfbtn.tfrgen-resume:hover{background:var(--accent2);opacity:1}
  .turn-block.interrupted .bubble{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent) inset}

  /* 图片大图查看器:点聊天里的图放大,支持上/下一张与关闭 */
  #imgViewer{position:fixed;inset:0;z-index:120;display:flex;align-items:center;justify-content:center;background:var(--ov-4)}
  #imgViewer[hidden]{display:none}
  #imgViewer img{max-width:92vw;max-height:88vh;object-fit:contain;border-radius:var(--r-md);user-select:none;-webkit-user-select:none}
  #imgViewer .ivbtn{position:absolute;display:flex;align-items:center;justify-content:center;width:40px;height:40px;
    border:none;border-radius:50%;background:var(--wh-1);color:var(--on-accent);font-size:22px;line-height:1;
    cursor:pointer;transition:background var(--t-fast);z-index:1}
  #imgViewer .ivbtn:hover{background:var(--wh-2)}
  #imgViewer .ivclose{top:calc(14px + env(safe-area-inset-top,0px));right:14px;font-size:17px}
  #imgViewer .ivprev{left:12px;top:50%;transform:translateY(-50%)}
  #imgViewer .ivnext{right:12px;top:50%;transform:translateY(-50%)}
  #imgViewer .ivcount{position:absolute;bottom:calc(16px + env(safe-area-inset-bottom,0px));left:50%;transform:translateX(-50%);
    font-size:var(--fs-sm);color:var(--wh-3);background:rgba(0,0,0,.45);padding:var(--sp-1) var(--sp-4);border-radius:var(--r-pill)}

  /* 选择/审批面板:复刻 Claude Code TUI —— 选项竖排带编号,选中项左侧 ❯ + 整行高亮条,其余置灰。
     外框由所在的工具卡(审批)或气泡(/model)提供,这里只负责排选项 */
  .choice{margin:6px 0 2px}
  .choice .opts{display:flex;flex-direction:column}
  .choice button{appearance:none;border:0;background:transparent;color:var(--fg);width:100%;
    display:flex;align-items:baseline;gap:7px;padding:var(--sp-4) var(--sp-4);font-size:var(--fs-base);line-height:1.45;
    border-radius:var(--r-md);text-align:left;cursor:pointer;transition:background var(--t-fast),color var(--t-fast),opacity var(--t-fast)}
  .choice button .arw{flex:0 0 10px;color:var(--accent);opacity:0;font-weight:700}
  .choice button .num{flex:0 0 auto;color:var(--muted);font-variant-numeric:tabular-nums}
  .choice button .lbl{flex:1;min-width:0}
  .choice button:hover:not(:disabled){background:color-mix(in srgb,var(--accent) 8%,transparent)}
  .choice button:active:not(:disabled){background:color-mix(in srgb,var(--accent) 14%,transparent)}
  .choice button.selected{background:color-mix(in srgb,var(--accent) 15%,transparent);color:var(--accent);font-weight:600}
  .choice button.selected .arw{opacity:1}
  .choice button.selected .num{color:var(--accent)}
  .choice button.dimmed{opacity:.4}
  .choice button:disabled{pointer-events:none}

  /* 工具卡片:diff / todo 清单 / 计划卡 / 命令预览(复刻 Claude Code 的结构化过程) */
  /* flow:一轮回复的过程区 —— 文字段与工具卡按真实顺序交错排列(像 Claude Code) */
  .flow{display:flex;flex-direction:column;gap:2px}
  .flow>.seg{margin:2px 0}
  .compactline{font-size:var(--fs-sm);color:var(--dim);margin:6px 0;display:flex;align-items:center;gap:8px}
  .compactline::before,.compactline::after{content:"";flex:1;border-top:1px dashed var(--dim);opacity:.4}
  /* 工具卡:无边框,默认收起成 1 行,点头部展开(复刻 Claude Code 的简洁风) */
  .toolcard{font-size:var(--fs-md)}
  .tc-head{padding:var(--sp-1) var(--sp-2);border-radius:var(--r-sm);font-weight:400;font-size:var(--fs-sm);
    font-family:ui-monospace,Menlo,Consolas,monospace;color:var(--dim);
    display:flex;gap:7px;align-items:center;cursor:pointer;user-select:none;transition:background var(--t-fast),color var(--t-fast)}
  .tc-head:hover{background:var(--panel2)}
  .tc-head.tc-warn{color:var(--text);cursor:default;background:var(--panel2);font-weight:600}
  .tc-head.err{color:var(--err)}                                               /* 工具出错:整行标红 */
  .tc-head .tc-path{color:var(--dim2);font-size:var(--fs-sm);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0}
  .tc-body{padding:var(--sp-2) var(--sp-2) var(--sp-2) 24px}                                        /* 展开区:左缩进对齐标题文字 */
  .tc-body.collapsed{display:none}
  .tc-sep{height:7px;margin:0}                                               /* 展开区内:入参与结果之间的间距，无线 */
  .tc-code{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:var(--fs-sm);white-space:pre-wrap;word-break:break-all;
    background:var(--code-bg);color:var(--code-fg);padding:var(--sp-2) var(--sp-3);border-radius:var(--r-sm);line-height:1.5}
  .diff{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:var(--fs-sm);white-space:pre-wrap;word-break:break-all;line-height:1.55;
    border-radius:var(--r-sm);overflow:hidden}
  .diff .ln{display:block;padding:0 var(--sp-3)}
  .diff .del{background:rgba(248,81,73,.12)}
  .diff .add{background:rgba(63,185,80,.13)}
  .diff .del::before{content:"− ";opacity:.8;color:var(--diff-del)}
  .diff .add::before{content:"+ ";opacity:.8;color:var(--diff-add)}
  .todo{list-style:none;margin:0;padding:0;font-size:var(--fs-md)}
  .todo li{padding:var(--sp-1) 0;display:flex;gap:8px;align-items:flex-start;line-height:1.45}
  .todo li.done{opacity:.5;text-decoration:line-through}
  .todo li.doing{font-weight:600;color:var(--accent)}
  .plan{font-size:var(--fs-md);line-height:1.6}
  .plan h1,.plan h2,.plan h3{font-size:var(--fs-base);margin:.5em 0 .3em}
  /* 工具结果:折进展开区里的输出块(不再单独占一行) */
  .tc-res-body{margin:0;padding:var(--sp-2) var(--sp-3);font-family:ui-monospace,Menlo,Consolas,monospace;font-size:var(--fs-sm);
    white-space:pre-wrap;word-break:break-all;line-height:1.5;background:var(--code-bg);color:var(--code-fg);
    border-radius:var(--r-sm);max-height:340px;overflow-y:auto}
  /* Task 卡片内的子代理实时动态(工具步数 chips):始终可见,随标题缩进 */
  .tc-sub{padding:2px var(--sp-2) 2px 24px;display:flex;flex-wrap:wrap;gap:4px 10px;
    font-size:var(--fs-sm);color:var(--dim2);align-items:center}
  .tc-sub:empty{display:none}
  /* 指令折叠组:已完成的指令收进可展开的折叠区,只显示计数 */
  .tgroup{margin:4px 0}
  .tg-head{padding:var(--sp-1) var(--sp-2);font-size:var(--fs-sm);color:var(--dim);cursor:pointer;display:flex;align-items:center;gap:6px;
    user-select:none;border-radius:var(--r-sm);font-family:ui-monospace,Menlo,Consolas,monospace}
  .tg-head:hover{color:var(--text)}
  .tg-body{padding-left:var(--sp-5);display:flex;flex-direction:column;gap:2px}
  .tg-body.collapsed{display:none}
  .tg-head .chev{font-size:var(--fs-sm);display:inline-block;transition:transform var(--t-fast)}
  .tg-head .chev.down{transform:translateY(-1px) rotate(45deg)}
  /* 当前活跃(最新)指令呼吸灯:背景色脉冲 */
  @keyframes tc-breathe{0%,100%{background:transparent}50%{background:var(--panel2)}}
  .tc-active .tc-head{animation:tc-breathe 2.4s ease-in-out infinite;border-radius:var(--r-sm)}

  /* 切会话 loading 骨架屏 */
  #convLoading{display:none;padding:20px 32px;flex-direction:column;gap:14px}
  #convLoading.on{display:flex}
  .skel{border-radius:var(--r-xl);animation:skelshine 1.2s ease-in-out infinite}
  .skel.ai{align-self:flex-start;height:54px;width:68%;background:var(--panel2)}
  .skel.me{align-self:flex-end;height:36px;width:44%;background:var(--user1);opacity:.35}
  .skel.ai2{align-self:flex-start;height:80px;width:75%;background:var(--panel2)}
  @keyframes skelshine{0%,100%{opacity:.45}50%{opacity:.85}}
  /* 向上翻页时固定在消息区顶部的轻量加载提示 */
  #historyLoading{display:none;align-items:center;justify-content:center;gap:var(--sp-2);
    padding:var(--sp-2) var(--sp-5);color:var(--dim);font-size:var(--fs-sm)}
  #historyLoading.on{display:flex}
  .hloadspin{width:var(--sp-4);height:var(--sp-4);border:2px solid var(--line2);
    border-top-color:var(--accent);border-radius:50%;animation:spin .7s linear infinite;flex-shrink:0}

  /* 空状态 / 新对话欢迎屏:默认不显示,由 updateEmpty()/openConv() 按真实数据决定何时出现,
     避免 #app 刚显示、数据还没到位时先闪一下欢迎屏。2026-07-15 起首页(#homeView)已下架,
     语音通话入口 + 最近对话列表合并进这里,APP 启动后直接落地在一个新对话上。
     不再用 position:absolute 铺满居中——内容变多(带最近对话列表)要能跟 #messages 一起滚动。 */
  #empty{display:none;flex-direction:column;padding:var(--sp-3) var(--sp-2) 24px;pointer-events:auto;
    max-width:640px;margin:0 auto;width:100%}
  #empty .elogo{width:64px;height:64px;margin:12px auto 14px;
    display:flex;align-items:center;justify-content:center;animation:pop .5s ease}
  #empty .elogo .voco-mascot{--s:2.2}
  #empty h2{margin:0 0 6px;font-size:22px;font-weight:600;text-align:center;
    font-family:Optima,"Times New Roman","Songti SC",serif}
  #empty p{margin:0 0 20px;color:var(--dim);font-size:var(--fs-base);text-align:center}
  #empty .sugs{display:flex;flex-wrap:wrap;gap:9px;justify-content:center;margin:0 0 28px;pointer-events:auto}
  #empty .sug{background:var(--card);border:1px solid var(--line2);border-radius:var(--r-xl);padding:var(--sp-4) var(--sp-5);font-size:var(--fs-base);
    color:var(--text);transition:background var(--t-fast),border-color var(--t-fast),transform var(--t-fast)}
  #empty .sug:hover{border-color:var(--accent)}
  #empty .sug:active{transform:scale(.96)}
  /* 区域标题 */
  .home-section{margin-bottom:28px}
  .home-section-title{font-size:var(--fs-lg);font-weight:600;margin:0 0 12px;color:var(--dim2)}
  /* 最近会话列表:不带边框,轻量化——只靠背景色区分行,标题和时间同一行省纵向空间 */
  .home-recent{display:flex;flex-direction:column;gap:4px}
  .home-item{display:flex;align-items:center;gap:12px;padding:var(--sp-3) var(--sp-4);
    border-radius:var(--r-lg);background:var(--panel);
    cursor:pointer;transition:background var(--t-fast);color:var(--text)}
  .home-item:active{background:var(--panel2)}
  .home-item:hover{background:var(--panel2)}
  .home-item-icon{width:30px;height:30px;border-radius:50%;flex-shrink:0;
    display:flex;align-items:center;justify-content:center;
    background:var(--panel2);font-size:var(--fs-base)}
  .home-item-icon.voice{background:rgba(90,164,105,.15);color:var(--ok)}
  .home-item-icon.chat{background:rgba(217,119,87,.12);color:var(--accent)}
  .home-item-body{flex:1;min-width:0;display:flex;align-items:baseline;gap:8px}
  .home-item-title{flex:1;min-width:0;font-size:var(--fs-base);font-weight:500;overflow:hidden;
    text-overflow:ellipsis;white-space:nowrap}
  .home-item-time{flex-shrink:0;font-size:var(--fs-sm);color:var(--dim2)}
  .home-empty{padding:32px;text-align:center;color:var(--dim2);font-size:var(--fs-base)}
  /* 展开更多:默认只显示 5 条,避免欢迎屏信息量太大 */
  .home-more{display:block;width:100%;margin-top:4px;padding:var(--sp-3) 0;background:none;border:none;
    color:var(--dim2);font-size:var(--fs-sm);cursor:pointer;text-align:center}
  .home-more:hover{color:var(--accent)}

  /* #composer 只做「悬浮 + 滑动隐藏」的壳,不带背景/内边距——背景和内边距挪到
     .combg 这层实心遮罩上;::before 是遮罩上方一小截渐隐条(纯色实心 → 全透明,
     不用模糊),让滚上来的消息不是硬切进纯色背景,而是柔和淡出。 */
  #composer{position:absolute;bottom:0;left:0;right:0;z-index:10;
    transition:transform .35s cubic-bezier(.4,0,.2,1)}
  #composer::before{content:"";position:absolute;left:0;right:0;bottom:100%;height:24px;
    background:linear-gradient(to top, color-mix(in srgb, var(--bg2) 88%, transparent) 30%, transparent);
    pointer-events:none}
  /* .combg 宽度撑满整行。半透明毛玻璃渐变背景盖住 #messages 滚动上来的文字,
     同时透出底层壁纸感;padding 只留左右和下(贴近底部安全区的一侧),上=0。 */
  #composer .combg{width:100%;
    background:linear-gradient(155deg, color-mix(in srgb, var(--bg2) 94%, transparent) 0%,
      color-mix(in srgb, var(--bg2) 72%, transparent) 100%);
    backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px);
    padding:0 32px}
  @media(min-width:641px){
    #composer .combg{padding-bottom:var(--sp-4)}
  }
  /* 顶栏始终可见,输入框不随滚动隐藏 */
  #composer .cwrap{max-width:820px;margin:0 auto}
/* 输入框底部工具条:左=上传,右=模型 + 发送 */
  .inbar{display:flex;align-items:center;gap:2px;margin-top:2px}
  .inbar .spacer{flex:1}
  /* 模型选择器(发送按钮左侧,无边框)*/
  #modelBox{position:relative}
  #modelBtn{display:flex;align-items:center;gap:6px;font-size:var(--fs-sm);color:var(--dim);font-weight:500;
    padding:var(--sp-2) var(--sp-3);border-radius:var(--r-md);max-width:150px;transition:color var(--t-fast),background var(--t-fast),transform var(--t-fast)}
  #modelBtn #modelName{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  #modelBtn:hover{color:var(--text);background:var(--panel2)}
  #modelBtn:active{transform:scale(.96)}
  /* 定时任务会话:模型锁定编辑页的值,按钮只读展示,去掉下拉箭头避免误以为能点 */
  #modelBtn:disabled{cursor:default;pointer-events:none}
  #modelBtn:disabled .caret{display:none}
  /* 折线箭头(chevron):border 描边 + 旋转,替代实心三角,略大;默认指向右,.down 转朝下 */
  .chev{flex-shrink:0;width:6px;height:6px;border:solid currentColor;border-width:0 1.5px 1.5px 0;
    transform:translateX(-1px) rotate(-45deg);transition:transform var(--t-fast)}   /* 收起:朝右(向左补 1px 视觉居中) */
  .chev.down{transform:translateY(-1px) rotate(45deg)}                      /* 展开:朝下 */
  #modelBtn .caret{opacity:.6;flex-shrink:0}
  #modelPop{position:absolute;bottom:calc(100% + 8px);right:0;min-width:264px;max-width:300px;z-index:20;
    background:var(--card);border:1px solid var(--line2);border-radius:var(--r-xl);padding:var(--sp-2);
    box-shadow:var(--shadow);animation:pop .16s ease;max-height:70vh;overflow-y:auto}
  #modelPop[hidden]{display:none}
  #modelPop .mi{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;
    text-align:left;padding:var(--sp-3) var(--sp-4);border-radius:var(--r-md);font-size:var(--fs-md);color:var(--text);transition:background var(--t-fast)}
  #modelPop .mi:hover{background:var(--panel2)}
  #modelPop .mi.on{color:var(--accent)}
  #modelPop .mi .mk{color:var(--accent);font-size:var(--fs-sm);flex-shrink:0}
  #modelPop .mi .ml{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  #modelPop .mring{position:relative;width:16px;height:16px;flex-shrink:0;display:flex;align-items:center;justify-content:center}
  #modelPop .mring .mqtip{display:none}   /* 纯数据容器,内容由 JS 拷进 .mqfloat 悬浮显示;自己永不直接可见 */
  /* Hover 卡片:挂在 body 下用 fixed 定位(见 showUsageTip),不能放在 #modelPop 内部——
     #modelPop 设了 overflow-y:auto 让长列表能滚动,会连带把 overflow-x 强制裁成非 visible,
     绝对定位的卡片一旦超出面板边界就被裁没,表现为 hover 出一片空白。 */
  .mqfloat{display:none;position:fixed;z-index:9999;width:220px;padding:var(--sp-4) var(--sp-4);background:var(--card);border:1px solid var(--line2);border-radius:var(--r-lg);box-shadow:var(--shadow);font-size:var(--fs-sm);color:var(--text);pointer-events:none}
  .mqt .mqh{font-weight:600;margin-bottom:8px;font-size:var(--fs-md);color:var(--text)}
  .mqt .mqtag{font-size:var(--fs-sm);font-weight:500;color:var(--dim);background:var(--panel2);padding:1px var(--sp-2);border-radius:var(--r-md);vertical-align:middle}
  .mqt .mqrow{display:flex;justify-content:space-between;align-items:center;margin:4px 0}
  .mqt .mqsub{color:var(--dim);font-size:var(--fs-sm);justify-content:flex-end;margin-top:-2px}
  .mqt .mqwarn b{color:var(--err)}
  .mqt .mqsep{height:1px;background:var(--line2);margin:8px 0}
  .mqt .mqdist{display:flex;flex-wrap:wrap;gap:5px}
  .mqt .mqdist span{font-size:var(--fs-sm);color:var(--dim);background:var(--panel2);padding:2px var(--sp-2);border-radius:var(--r-md)}
  #modelPop .mgrouplabel{padding:var(--sp-2) var(--sp-4) var(--sp-1);font-size:var(--fs-sm);font-weight:600;color:var(--dim2);display:flex;align-items:center;justify-content:space-between;gap:8px}
  #modelPop .mgrouplabel .mgmeta{display:flex;align-items:center;gap:6px;flex-shrink:0}
  #modelPop .mgrouplabel .mreset{font-size:var(--fs-sm);color:var(--dim2);font-weight:400;white-space:nowrap}
  #modelPop .mdivider{height:1px;margin:5px 7px;background:var(--line2)}
  /* 思考深度选择器(模型切换胶囊左侧,样式与模型胶囊一致) */
  #effortBox{position:relative}
  #effortBtn{display:flex;align-items:center;gap:6px;font-size:var(--fs-sm);color:var(--dim);font-weight:500;
    padding:var(--sp-2) var(--sp-3);border-radius:var(--r-md);transition:color var(--t-fast),background var(--t-fast),transform var(--t-fast)}
  #effortBtn #effortName{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  #effortBtn:hover{color:var(--text);background:var(--panel2)}
  #effortBtn:active{transform:scale(.96)}
  #effortBtn .caret{opacity:.6;flex-shrink:0}
  #effortPop{position:absolute;bottom:calc(100% + 8px);right:0;min-width:132px;z-index:20;
    background:var(--card);border:1px solid var(--line2);border-radius:var(--r-xl);padding:var(--sp-2);
    box-shadow:var(--shadow);animation:pop .16s ease}
  #effortPop[hidden]{display:none}
  #effortPop .mi{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;
    text-align:left;padding:var(--sp-3) var(--sp-4);border-radius:var(--r-md);font-size:var(--fs-md);color:var(--text);transition:background var(--t-fast)}
  #effortPop .mi:hover{background:var(--panel2)}
  #effortPop .mi.on{color:var(--accent)}
  #effortPop .mi .mk{color:var(--accent);font-size:var(--fs-sm);flex-shrink:0}
  #effortPop .mi .ml{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  /* 新会话项目选择器:悬浮在 .inrow 左上角(position:absolute 脱离文档流,不挤占输入框布局) */
  #projSel{position:absolute;left:0;bottom:calc(100% + 8px);z-index:15}
  #projSel[hidden]{display:none}
  #projSelBtn{display:flex;align-items:center;gap:6px;font-size:var(--fs-sm);color:var(--dim);font-weight:500;
    padding:var(--sp-2) var(--sp-4);border-radius:var(--r-md);max-width:200px;background:var(--card);border:1px solid var(--line2);
    box-shadow:var(--shadow);transition:color var(--t-fast),background var(--t-fast),transform var(--t-fast)}
  #projSelBtn span:first-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  #projSelBtn:hover{color:var(--text);background:var(--panel2)}
  #projSelBtn:active{transform:scale(.96)}
  /* 往上开(bottom,不是 top):往下开会挤进输入框和键盘之间那条窄缝,列表一长就被裁掉 */
  #projSelPop{position:absolute;bottom:calc(100% + 6px);left:0;min-width:200px;z-index:20;
    background:var(--card);border:1px solid var(--line2);border-radius:var(--r-xl);padding:var(--sp-2);
    box-shadow:var(--shadow);animation:pop .16s ease}
  #projSelPop[hidden]{display:none}
  #projSelPop .mi{display:flex;align-items:center;justify-content:space-between;gap:10px;width:100%;
    text-align:left;padding:var(--sp-3) var(--sp-4);border-radius:var(--r-md);font-size:var(--fs-md);color:var(--text);transition:background var(--t-fast)}
  #projSelPop .mi:hover{background:var(--panel2)}
  #projSelPop .mi.on{color:var(--accent)}
  #projSelPop .mi .mk{color:var(--accent);font-size:var(--fs-sm);flex-shrink:0}
  #pending{display:flex;flex-direction:column;gap:6px;margin-bottom:8px}
  #pending:empty{display:none}
  #pending.shake{animation:shake .3s}
  @keyframes shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-5px)}75%{transform:translateX(5px)}}
  #pending .pi{display:flex;align-items:center;gap:8px;padding:var(--sp-2) var(--sp-4);border-radius:var(--r-md);
    background:var(--card);border:1px solid var(--line2);font-size:var(--fs-md);color:var(--dim)}
  #pending .pi .clock{flex-shrink:0}
  #pending .pi .ptext{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  #pending .pi .pdel{flex-shrink:0;width:20px;height:20px;border-radius:50%;border:none;cursor:pointer;
    background:transparent;color:var(--dim);font-size:var(--fs-lg);line-height:1;display:inline-flex;
    align-items:center;justify-content:center}
  #pending .pi .pdel:hover{background:var(--err);color:var(--on-accent)}
  /* 没图片时也保留这 3px:输入框 focus 态的外发光阴影要靠这点余量,
     不然贴着上边界会被裁掉一截 */
  #thumbs{display:flex;gap:8px;margin-bottom:3px;flex-wrap:wrap}
  #thumbs .t{position:relative}
  #thumbs img{width:56px;height:56px;object-fit:cover;border-radius:var(--r-md);border:1px solid var(--line2)}
  #thumbs .x{position:absolute;top:-6px;right:-6px;background:var(--err);color:var(--on-accent);border-radius:50%;
    width:20px;height:20px;font-size:var(--fs-md);display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px rgba(0,0,0,.4)}
  #thumbs .audiochip{display:flex;align-items:center;height:32px;padding:0 20px 0 var(--sp-4);border-radius:var(--r-xl);
    background:var(--panel2);border:1px solid var(--line2);max-width:220px}
  #thumbs .audiochip .alabel{font-size:var(--fs-sm);color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  #thumbs .audiochip.error{border-color:var(--err)}
  #thumbs .audiochip.error .alabel{color:var(--err)}
  #thumbs .audiochip.uploading .alabel{color:var(--dim)}
  #thumbs .filechip{display:flex;align-items:center;height:32px;padding:0 20px 0 var(--sp-4);border-radius:var(--r-xl);
    background:var(--panel2);border:1px solid var(--line2);max-width:220px}
  #thumbs .filechip .flabel{font-size:var(--fs-sm);color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  #thumbs .filechip.error{border-color:var(--err)}
  #thumbs .filechip.error .flabel{color:var(--err)}
  #thumbs .filechip.uploading .flabel{color:var(--dim)}
  /* 竖排输入框:文本区在上(默认约 2 行),工具条在下 */
  .inrow{position:relative;display:flex;flex-direction:column;background:var(--card);border:1px solid var(--line2);
    border-radius:20px;padding:var(--sp-3) var(--sp-4) var(--sp-2);transition:border-color var(--t-fast),box-shadow var(--t-fast),background var(--t-fast)}
  .inrow:focus-within,.inrow.dragover{border-color:var(--accent);box-shadow:0 0 0 3px var(--focus-ring)}
  .inrow.dragover{background:color-mix(in srgb,var(--accent) 8%,var(--card))}
  /* 斜杠命令菜单:输入 "/" 时弹出,悬浮在整个输入框上方,随前缀过滤;结构复用 #modelPop 样式 */
  #cmdPop{position:absolute;left:0;right:0;bottom:calc(100% + 8px);z-index:20;max-height:260px;overflow-y:auto;
    background:var(--card);border:1px solid var(--line2);border-radius:var(--r-xl);padding:var(--sp-2);
    box-shadow:var(--shadow);animation:pop .16s ease}
  #cmdPop[hidden]{display:none}
  #cmdPop .ci{display:flex;align-items:baseline;gap:10px;width:100%;text-align:left;
    padding:var(--sp-3) var(--sp-4);border-radius:var(--r-md);font-size:var(--fs-md);color:var(--text);transition:background var(--t-fast)}
  #cmdPop .ci .cn{color:var(--accent);font-weight:600;flex-shrink:0}
  #cmdPop .ci .cd{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dim);font-size:var(--fs-sm)}
  #cmdPop .ci:hover,#cmdPop .ci.active{background:var(--panel2)}
  #cmdPop .empty{padding:var(--sp-3) var(--sp-4);font-size:var(--fs-sm);color:var(--dim2)}
  #cmdPop .cmdsep{height:1px;margin:5px 7px;background:var(--line2)}
  /* font-size 固定 16px(不用 inherit):低于 16px 会触发 iOS Safari 聚焦自动缩放 */
  #ta{width:100%;background:none;border:none;color:var(--text);resize:none;font-family:inherit;font-size:16px;
    min-height:46px;max-height:180px;padding:2px var(--sp-1);outline:none;line-height:1.5}
  #ta::placeholder{color:var(--dim2)}
  /* 订阅配额小圆环(Anthropic/Kimi 订阅共用,嵌在模型选择面板每行里,见 .mring):
     20x20 viewBox,和顶部上下文环(#barMeta .ctxring)同规格,stroke 2.5,半径 8。 */
  .qr{width:20px;height:20px;display:block;color:var(--dim)}
  .qa{transition:stroke-dashoffset .5s ease,stroke .3s ease;stroke:var(--dim2);stroke-linecap:round}
  .qt{stroke:currentColor;stroke-linecap:round}
  #imgBtn{color:var(--dim);font-size:22px;width:34px;height:34px;border-radius:50%;flex-shrink:0;
    display:flex;align-items:center;justify-content:center;transition:color var(--t-fast),background var(--t-fast)}
  #imgBtn:hover{color:var(--text);background:var(--panel2)}
  #micBtn{position:relative;color:var(--dim);font-size:18px;width:34px;height:34px;border-radius:50%;flex-shrink:0;
    display:flex;align-items:center;justify-content:center;transition:color var(--t-fast),background var(--t-fast),transform var(--t-fast)}
  #micBtn:hover{color:var(--text);background:var(--panel2)}
  #micBtn:active{transform:scale(.9)}
  @keyframes spin{to{transform:rotate(360deg)}}
  @keyframes pulse{0%,100%{opacity:.55}50%{opacity:1}}
  @keyframes recIn{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
  /* 录音行:点 🎤 后整个输入框变成这一条,整行点按即完成(参考 iMessage) */
  #recRow{display:none;align-items:center;gap:11px;cursor:default;user-select:none;-webkit-user-select:none;
    background:var(--card);border:1px solid var(--line2);border-radius:20px;padding:0 var(--sp-3) 0 var(--sp-4);
    min-height:64px;animation:recIn .2s ease;transition:border-color var(--t-fast),transform var(--t-fast)}
  #recRow.show{display:flex}
  #recRow.show{border-color:var(--err)}
  #recRow .rdot{width:9px;height:9px;border-radius:50%;background:var(--err);animation:blink 1s infinite;flex-shrink:0;pointer-events:none}
  #recRow #recWave{flex:1;height:36px;min-width:0;pointer-events:none}
  #recRow #recTime{color:var(--err);font-variant-numeric:tabular-nums;font-size:var(--fs-base);flex-shrink:0;min-width:36px;text-align:right;pointer-events:none}
  #recRow #recCancel{flex-shrink:0;width:30px;height:30px;border-radius:50%;color:var(--dim);font-size:var(--fs-lg);
    display:flex;align-items:center;justify-content:center;background:var(--panel2);transition:color var(--t-fast),background var(--t-fast)}
  #recRow #recCancel:hover{color:var(--text);background:var(--line2)}
  #sendBtn,#recRow #recSend{background:linear-gradient(135deg,var(--user1),var(--user2));color:var(--on-accent);border-radius:50%;
    width:34px;height:34px;font-size:17px;flex-shrink:0;display:flex;align-items:center;justify-content:center;
    transition:transform var(--t-fast),opacity var(--t-base),box-shadow var(--t-base);box-shadow:0 2px 10px var(--glow2)}
  #sendBtn:hover,#recRow #recSend:hover{box-shadow:0 4px 16px var(--glow1)}
  #sendBtn:active,#recRow #recSend:active{transform:scale(.9)}
  /* 语音占位气泡:转写中 spinner / 没听清可重录 */
  .bubble .vwait{display:inline-flex;align-items:center;gap:8px}
  .bubble .vwait .sp{width:14px;height:14px;border-radius:50%;border:2px solid rgba(255,255,255,.42);border-top-color:var(--on-accent);animation:spin .7s linear infinite;flex-shrink:0}
  /* 音频发送后的 loading 圈(在用户气泡里):currentColor 跟随气泡文字色,深浅背景都可见 */
  .bubble .aspin{display:inline-block;vertical-align:middle;margin-left:8px;width:14px;height:14px;border-radius:50%;border:2px solid currentColor;border-top-color:transparent;opacity:.65;animation:spin .7s linear infinite;flex-shrink:0}
  .bubble .vretry{margin-left:9px;padding:2px var(--sp-4);border-radius:var(--r-lg);background:rgba(255,255,255,.24);color:var(--on-accent);font-size:var(--fs-md);cursor:pointer}
  .bubble .vretry:active{transform:scale(.94)}
  #sendBtn:disabled{opacity:.4;box-shadow:none}
  #sendBtn.stop-mode{background:linear-gradient(135deg,var(--danger),var(--danger2));font-size:var(--fs-md)}
  #sendBtn.stop-mode:hover{box-shadow:0 4px 16px rgba(192,48,48,.5)}
  /* 气泡内动作按钮(如"忽略并发送"降级选项) */
  .bubble .bact{display:inline-block;margin-top:8px;padding:var(--sp-2) var(--sp-5);border-radius:var(--r-lg);
    background:var(--panel2);color:var(--text);font-size:var(--fs-md);font-weight:600;cursor:pointer;
    transition:background var(--t-fast),transform var(--t-fast)}
  .bubble .bact:hover{background:var(--card)}
  .bubble .bact:active{transform:scale(.95)}

  #backdrop{display:none;position:fixed;inset:0;background:var(--ov-3);z-index:25;backdrop-filter:blur(2px)}

  @media(max-width:760px){
    /* 窄屏放不下"侧栏+内容"两栏,侧边栏默认收到画面外,点 ☰ 才以浮层盖在内容上方——
       这是空间不够的布局问题,任何设备都需要,不分设备类型(不然桌面窄窗口下侧栏会
       常年占 280px,内容被挤成一条缝)。真正分设备的是下面的视觉/手势细节:移动端是
       圆角抽屉+大字号+安全区留白,桌面窄窗口就是普通贴边浮层,没有那些"手机味"处理。 */
    /* 收起态必须 box-shadow:none:抽屉是靠 translateX 挪到画面左外侧,右边缘只差 8px
       就到屏幕边,28px 模糊的投影会溢过来,在左侧留一条灰边(桌面窄窗口下尤其明显)。
       投影只在 .open 时才挂,并跟着 transform 一起过渡,关的时候先淡掉。 */
    #sidebar{position:fixed;top:8px;bottom:8px;left:8px;z-index:26;width:280px;
      border-radius:var(--r-lg);box-shadow:none;
      transform:translateX(calc(-100% - 16px))}
    #sidebar.open{transform:translateX(0);box-shadow:0 10px 28px rgba(0,0,0,.28)}
    #hamb{display:flex}
    #backdrop.show{display:block}
    /* 移动端左右留白收窄:桌面 32px 在窄屏太挤,回到 16px;上下不额外加(见 .combg 基础规则)。
       这几条是纯版式收紧,跟设备类型无关,桌面窗口拉小同样适用。 */
    #messages,#convLoading{padding-left:var(--sp-5);padding-right:var(--sp-5)}
    header.bar{padding-left:var(--sp-5);padding-right:var(--sp-5)}
    #composer .combg{padding-left:var(--sp-5);padding-right:var(--sp-5)}
    /* 真手机/平板:圆角更大、四周留白挤到 8px、抽屉宽度加到 300px,配合下面字号加大;
       圆角变大后投影会跟着往里收,加深加大投影把这块阴影感补回来。 */
    html.device-mobile #sidebar{inset:8px auto 8px 8px;margin:0;border-radius:32px;width:300px}
    html.device-mobile #sidebar.open{box-shadow:0 10px 32px rgba(0,0,0,.34)}
    /* 移动端侧栏:菜单行加大触控尺寸、字号整体 +1px,圆角贴近 iOS 大圆角风格。
       是按 300px 抽屉宽度调的,桌面 280px 窄侧栏放大字号会挤/换行,只给真手机/平板。 */
    html.device-mobile #sidebar .shead .brand{font-size:21px}
    html.device-mobile .projgrp,html.device-mobile .conv{padding:var(--sp-3) var(--sp-4)}
    html.device-mobile .projgrp{font-size:var(--fs-base)}
    html.device-mobile .conv .ct{font-size:var(--fs-lg)}
    html.device-mobile .conv .ctime{font-size:var(--fs-sm)}
    html.device-mobile .sfoot{font-size:var(--fs-base);padding:var(--sp-4) var(--sp-4) var(--sp-4) var(--sp-5)}
    html.device-mobile .convmenu .cmitem{font-size:var(--fs-base)}
    html.device-mobile #convFilterPop .fmi{font-size:var(--fs-base)}
  }
  /* 宽屏基础字号统一为 16px,与窄屏一致,避免维护两套字号 */
  @media(min-width:761px){
    html,body{line-height:1.55}
    /* 宽屏收起:侧边栏宽度归零,顶栏 ☰ 变身为"展开"入口。窄屏下 #sidebar 已经在上面
       默认收到画面外了,sb-collapsed 在窄屏没有额外意义,不需要重复处理。 */
    html:not(.device-mobile) body.sb-collapsed #sidebar{width:0;margin-left:0;border-color:transparent;box-shadow:none;overflow:hidden}
  }
  /* 侧边栏收起按钮只给桌面设备用(移动端没有"收起态"这个概念,只有开/关抽屉)。 */
  html:not(.device-mobile) #collapseBtn{display:flex}
  html:not(.device-mobile) body.sb-collapsed #hamb{display:flex}
  @media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
  .ic{width:14px;height:14px;vertical-align:-2.5px;flex-shrink:0}
  #micBtn .ic{width:17px;height:17px;vertical-align:-4px}
  .pmrow .ic{width:15px;height:15px;vertical-align:-3px;margin-right:2px;color:var(--dim)}

  /* ── 通话视图(#callView,原独立 /voice 页):跟 #chatMain 同级互斥显隐,
     结构照抄原页面,只把裸标签选择器(header/footer/main/body)换成 id 作用域,
     避免污染 #chatMain 那一套同名标签的样式。──────────────────────────────── */
  #callView{flex:1;display:flex;flex-direction:column;min-width:0;position:relative;
    background:var(--bg2);overflow:hidden}
  #callView[hidden]{display:none}
  /* 底部只显示一种输入方式:语音控制或文本 composer,由 Tab 切换。 */
  #callDock{position:absolute;left:0;right:0;bottom:0;z-index:11;display:flex;
    flex-direction:column;align-items:stretch;pointer-events:none}
  #callModeTabs{pointer-events:auto;align-self:center;display:flex;gap:2px;padding:var(--sp-1);
    margin:0 auto 8px;background:color-mix(in srgb,var(--panel) 92%,transparent);
    border:1px solid var(--line2);border-radius:var(--r-xl);box-shadow:var(--shadow)}
  #callModeTabs[hidden]{display:none}   /* 通话进行中隐藏切换,防遮挡(display:flex 覆盖 UA 样式,须显式补) */
  #callModeTabs button{border:0;background:transparent;color:var(--dim);border-radius:var(--r-md);
    padding:var(--sp-2) 22px;font-size:var(--fs-md);cursor:pointer;transition:background var(--t-fast),color var(--t-fast)}
  #callModeTabs button[aria-selected="true"]{background:var(--accent);color:var(--on-accent)}
  #callVoicePanel,#callTextPanel{pointer-events:auto;width:100%}
  #callVoicePanel[hidden],#callTextPanel[hidden]{display:none}
  #callTextPanel > #composer{position:relative;left:auto;right:auto;bottom:auto;z-index:0}
  #callTextPanel > #composer::before{display:none}
  #callVoicePanel #callFoot{position:relative;left:auto;right:auto;bottom:auto}
  #callView #callBody{padding-bottom:calc(180px + env(safe-area-inset-bottom));
    scroll-padding-bottom:calc(180px + env(safe-area-inset-bottom))}
  #callHead{display:flex;align-items:center;gap:12px;padding:var(--sp-5) var(--sp-5);
    padding-top:calc(14px + env(safe-area-inset-top));border-bottom:1px solid var(--line)}
  #callHead #backLink{color:var(--dim);line-height:1;padding:var(--sp-1);display:inline-flex}
  #callHead #backLink .ic{width:20px;height:20px}
  #callHead .title{font-weight:600;flex:1}
  /* callFoot 改浮层后 callBody 一直铺到视图底;底 padding 让最新气泡的停靠点
     抬到渐变遮罩完全透明的边界(128px)之上——最新消息任何时候都清晰可读,
     只有往回翻的历史消息才滑进吉祥物身后的渐隐区。这个数值 2026-08-21 跟着
     #callFoot 一起从"横向声波"改"竖直吉祥物"收窄过一次,见下面 #callFoot 注释。 */
  #callBody{flex:1;overflow-y:auto;padding:var(--sp-5);
    padding-bottom:calc(130px + env(safe-area-inset-bottom));
    scroll-padding-bottom:calc(130px + env(safe-area-inset-bottom))}
  #transcript{display:flex;flex-direction:column;gap:12px;max-width:680px;margin:0 auto}
  /* .activity 是前台工具动作行(查记录/跑脚本),跟垫话术共用一套"透明小字"外观;
     区别只在数据来源:filler 是话术,activity 由 SSE activity 事件原地更新 */
  #callView .bubble.filler,#callView .bubble.activity{background:transparent;border:none;
    color:var(--dim2);font-size:var(--fs-base);padding:0 var(--sp-5);max-width:100%;box-shadow:none}
  .msgicon{display:inline-flex;margin-right:6px;vertical-align:-3px}
  .msgicon .ic{width:15px;height:15px}
  #callView .hint{text-align:center;color:var(--dim2);font-size:var(--fs-base);padding:40px 20px}
  #tasksBtn{position:relative;background:none;border:none;color:var(--dim);padding:var(--sp-1);display:inline-flex}
  #tasksBtn .ic{width:20px;height:20px}
  /* 清空语音上下文:通话界面顶栏的橡皮擦,清的是 voice-chat:main(见 /voice/clear),
     跟聊天页各清各的——放这里因为清的正是这块语音会话的上下文 */
  #clearVoiceCtxBtn{background:none;border:none;color:var(--dim);padding:var(--sp-1);display:inline-flex;
    transition:color var(--t-fast) ease}
  #clearVoiceCtxBtn .ic{width:20px;height:20px}
  #clearVoiceCtxBtn:hover,#clearVoiceCtxBtn:active{color:var(--err)}
  #tasksBadge{position:absolute;top:0;right:0;width:8px;height:8px;border-radius:50%;
    background:var(--accent);display:none}
  #tasksBadge.on{display:block}
  /* 后台任务状态条:顶栏下方常驻横幅——派发瞬间出现,最近7条按最后更新时间倒序;
     终态任务满 10 分钟自动隐藏,不再手动关闭。状态点:running 赤陶橙闪烁(同侧栏),
     其余按语义色;已完成项带删除线。
     点击空白处打开任务抽屉看详情(数据来自 SSE task_update/task_done)。
     PWA 拿不到 iOS 灵动岛(Live Activities 只开放给原生 App),这条是应用内的替代。 */
  #taskBar{border-bottom:1px solid var(--line);padding:var(--sp-3) var(--sp-5);display:flex;
    flex-direction:column;gap:6px;cursor:pointer;flex-shrink:0}
  #taskBar[hidden]{display:none}
  /* 聊天视图输入框顶部的任务状态条:套在带背景色的圆角矩形框内,悬浮在输入框顶部。
     活跃任务与已完成任务分区:已完成默认折叠;活跃任务默认最多 5 条,超出显示"显示更多"。 */
  #chatTaskBar{padding:0 0 var(--sp-2);display:flex;flex-direction:column;cursor:pointer}
  #chatTaskBar[hidden]{display:none}
  .chat-taskbar-box{background:color-mix(in srgb, var(--panel2) 55%, transparent);
    border:1px solid color-mix(in srgb, var(--line2) 55%, transparent);border-radius:var(--r-xl);
    padding:var(--sp-3) var(--sp-4) var(--sp-2);display:flex;flex-direction:column;gap:7px}
  .ctb-section{display:flex;flex-direction:column;gap:5px}
  .ctb-row{display:flex;align-items:center;gap:8px;font-size:var(--fs-sm);min-width:0}
  .ctb-row.done{opacity:.55;text-decoration:line-through}
  .ctb-dot{width:5px;height:5px;border-radius:50%;flex-shrink:0;background:var(--dim2)}
  /* 状态语义色,与 .taskbar-row .dot 同款(见上) */
  .ctb-dot.running,.ctb-dot.in_progress{width:6px;height:6px;background:var(--accent);
    animation:ctbPulse 1.2s ease-in-out infinite}
  .ctb-dot.paused{background:var(--warn)}
  .ctb-dot.done,.ctb-dot.completed{background:var(--ok)}
  .ctb-dot.failed,.ctb-dot.cancelled{background:var(--err)}
  .ctb-title{font-weight:500;flex-shrink:0;max-width:45%;overflow:hidden;
    text-overflow:ellipsis;white-space:nowrap}
  .ctb-note{color:var(--dim);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .ctb-more,.ctb-toggle{border:none;background:none;color:var(--accent);font-size:var(--fs-sm);
    cursor:pointer;text-align:left;padding:2px 0;width:fit-content;display:inline-flex;
    align-items:center;gap:6px}
  .ctb-more:hover,.ctb-toggle:hover{text-decoration:underline}
  .ctb-chev{display:inline-block;width:6px;height:6px;border:solid currentColor;
    border-width:0 1.5px 1.5px 0;transform:translateY(-2px) rotate(-45deg);
    transition:transform var(--t-fast);opacity:.65}
  .ctb-chev.open{transform:translateY(0) rotate(45deg)}
  .taskbar-row{display:flex;align-items:center;gap:8px;font-size:var(--fs-md);min-width:0}
  .taskbar-row.done{opacity:.55;text-decoration:line-through}
  .taskbar-row .dot{width:6px;height:6px;border-radius:50%;flex-shrink:0;background:var(--dim2)}
  /* 状态语义色(2026-08-24 对齐侧边栏 .conv .livedot):排队=灰,进行中=赤陶橙+脉冲,
     暂停=警告黄,完成=绿(静态,行级 done 有删除线区分),失败/取消=红。
     进行中不再用 --ok:绿是"已完成"的语义色,跑着的任务用 --accent 才和侧栏一致 */
  .taskbar-row .dot.running,.taskbar-row .dot.in_progress{background:var(--accent);
    animation:ctbPulse 1.2s ease-in-out infinite}
  .taskbar-row .dot.paused{background:var(--warn)}
  .taskbar-row .dot.done,.taskbar-row .dot.completed{background:var(--ok)}
  .taskbar-row .dot.failed,.taskbar-row .dot.cancelled{background:var(--err)}
  .taskbar-row .t{font-weight:600;flex-shrink:0;max-width:45%;overflow:hidden;
    text-overflow:ellipsis;white-space:nowrap}
  .taskbar-row .n{color:var(--dim);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  @keyframes ctbPulse{0%,100%{opacity:1}50%{opacity:.35}}
  #tasksDrawer{position:fixed;inset:0;background:var(--ov-3);z-index:10;display:none}
  #tasksDrawer.open{display:block}
  #tasksSheet{position:absolute;left:0;right:0;bottom:0;max-height:70vh;overflow-y:auto;
    background:var(--panel);border-radius:16px 16px 0 0;padding:var(--sp-5);
    padding-bottom:calc(16px + env(safe-area-inset-bottom))}
  #tasksSheet h3{margin:0 0 12px;font-size:var(--fs-lg);color:var(--dim)}
  .task{border:1px solid var(--line);border-radius:var(--r-md);padding:var(--sp-4) var(--sp-4);margin-bottom:8px}
  .task .row{display:flex;align-items:center;gap:8px;margin:0;animation:none}
  .task .dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
  .task .dot.queued{background:var(--dim2)}
  .task .dot.running{background:var(--accent);animation:ctbPulse 1.2s ease-in-out infinite}  /* 2026-08-24 与任务栏/侧栏统一:进行中=赤陶橙+脉冲 */
  .task .dot.done{background:var(--ok)}
  .task .dot.failed,.task .dot.cancelled{background:var(--err)}
  .task .title{flex:1;font-weight:600}
  .task .note{color:var(--dim);font-size:var(--fs-md);margin-top:4px}
  .task .full{color:var(--text);font-size:var(--fs-md);margin-top:8px;white-space:pre-wrap;display:none}
  .task .full.open{display:block}
  .task .stop{border:1px solid var(--err);color:var(--err);background:none;border-radius:var(--r-xl);
    padding:2px var(--sp-4);font-size:var(--fs-sm)}
  .task-empty{color:var(--dim2);text-align:center;padding:20px}
  /* 底部整块(吉祥物+状态+挂断)是叠在 callBody 上面的浮层,不占文档流——
     遮罩从下往上渐变:按钮+状态文字那截(~64px+安全区)实色,吉祥物区一路渐隐,
     顶部全透明,转写文字能从吉祥物后面透出来,显示范围更大。
     pointer-events 只留给按钮和吉祥物(点吉祥物=打断),透明区的点击/滚动穿透给转写区。
     2026-08-21:声波 canvas 换成小幽吉祥物后整块高度收窄——竖直角色不需要
     原来给横向声波留的那么高,顺带少遮一截聊天记录(280px→180px 见 #callBody)。 */
  #callFoot{position:absolute;left:0;right:0;bottom:0;pointer-events:none;
    padding:8px 16px calc(6px + env(safe-area-inset-bottom));display:flex;
    flex-direction:column;align-items:center;gap:6px;
    background:linear-gradient(to top,
      var(--bg2) 0,
      var(--bg2) calc(env(safe-area-inset-bottom) + 64px),
      transparent calc(env(safe-area-inset-bottom) + 128px))}
  #callFoot button,#callFoot #orbWrap,#callFoot #voicePickBtn{pointer-events:auto}
  .btnicon{display:inline-flex;margin-right:6px;vertical-align:-3px}
  .btnicon .ic{width:16px;height:16px}
  #stopBtn{border:1px solid var(--err);color:var(--err);background:none;border-radius:20px;
    padding:var(--sp-3) 20px;font-size:var(--fs-base);display:inline-flex;align-items:center}
  #talkBtn{width:120px;height:120px;border-radius:50%;background:var(--accent);color:var(--on-accent);
    border:none;font-size:var(--fs-xl);font-weight:600;box-shadow:0 8px 24px rgba(217,119,87,.35);
    transition:transform var(--t-fast) ease, background var(--t-fast) ease;
    -webkit-user-select:none;user-select:none;-webkit-touch-callout:none;touch-action:none}
  #talkBtn.recording{background:var(--err);transform:scale(1.08)}
  #talkBtn:disabled{opacity:.5}
  #talkBtn[hidden],#stopBtn[hidden]{display:none}

  /* P2 全双工:进 call view 即自动开始,唯一常驻视觉是小幽吉祥物(原来是声波 canvas,
     2026-08-21 换掉——动效收回吉祥物本体的眼睛/脚/身体伸缩,不再画外挂的音柱/
     三点/光晕,见 mascot.js STATES.listening/conn 和 voice.js driveOrbMascot)。
     状态文字紧贴在吉祥物正下方,挂断是吉祥物下方一个深灰圆角方块(停止语义)。 */
  #handsFreeUi{display:flex;flex-direction:column;align-items:center;gap:6px}
  #handsFreeUi[hidden]{display:none}
  #orbWrap{position:relative;width:280px;height:68px;display:flex;align-items:flex-end;
    justify-content:center;cursor:pointer}
  #orbWrap .voco-mascot{--s:2.5}

  #statusLine{display:flex;align-items:center;justify-content:center;gap:8px;min-height:18px}
  #connDot{width:8px;height:8px;border-radius:50%;flex-shrink:0;transition:background .4s ease,box-shadow .4s ease}
  #connDot.conn-connected{background:var(--ok);box-shadow:0 0 6px rgba(90,164,105,.5)}
  #connDot.conn-connecting{background:var(--warn);box-shadow:0 0 6px rgba(232,168,76,.5);animation:connPulse 1.2s ease-in-out infinite}
  #connDot.conn-disconnected{background:var(--err);box-shadow:0 0 6px rgba(209,103,74,.4)}
  @keyframes connPulse{0%,100%{opacity:.5} 50%{opacity:1}}
  #status{font-size:var(--fs-base);color:var(--dim);text-align:center;transition:color .3s ease;
    letter-spacing:.02em}
  #status.listening{color:var(--err)}
  #status.thinking,#status.playing{color:var(--accent)}

  /* 静音/音色/挂断同一行,三个圆形图标按钮并排 */
  #callActions{display:flex;align-items:center;gap:16px}
  /* 音色切换:静音和挂断中间的小圆钮,里面叠一个全透明的原生 select——
     点图标即弹系统选择器,不再占通话界面一整行 */
  #voicePickBtn{position:relative;width:46px;height:46px;border-radius:50%;
    background:var(--panel2);color:var(--dim);display:inline-flex;align-items:center;justify-content:center;
    transition:background var(--t-fast) ease,color var(--t-fast) ease,transform var(--t-fast) ease}
  #voicePickBtn span{display:inline-flex}
  #voicePickBtn .ic{width:22px;height:22px}
  #voicePickBtn:hover{background:var(--panel);color:var(--text)}
  #voicePickBtn:active{transform:scale(.92)}
  #voicePickBtn select{position:absolute;inset:0;width:100%;height:100%;opacity:0;
    -webkit-appearance:none;appearance:none;border:none;cursor:pointer}
  #endHandsFreeBtn{width:46px;height:46px;border-radius:50%;border:none;
    background:var(--err);color:var(--on-accent);display:inline-flex;align-items:center;justify-content:center;
    padding:0;transition:background var(--t-fast) ease,color var(--t-fast) ease,transform var(--t-fast) ease}
  #endHandsFreeBtn .ic{width:22px;height:22px;transform:rotate(135deg)}  /* 拨打图标转135°=挂断,复用同一套 path,不用另画丑图标 */
  #endHandsFreeBtn:hover{background:var(--accent2)}
  #endHandsFreeBtn:active{transform:scale(.92)}
  #muteToggleBtn{width:46px;height:46px;border-radius:50%;border:none;
    background:var(--panel2);color:var(--dim);display:inline-flex;align-items:center;justify-content:center;
    padding:0;transition:background var(--t-fast) ease,color var(--t-fast) ease,transform var(--t-fast) ease}
  #muteToggleBtn .ic{width:22px;height:22px}
  #muteToggleBtn:active{transform:scale(.92)}
  /* 静音=一个小图标切换态,开启后常驻标红提醒"麦克风关着",不需要文字 */
  #muteToggleBtn:hover{background:var(--panel);color:var(--text)}
  #muteToggleBtn.muted{background:var(--err);color:var(--on-accent)}

  /* ── 启动按钮模式:待机时中央一个圆形麦克风图标钮(与静音钮同款形态,略大突出主操作),
     点击进入录音;连接成功后此钮隐藏,由声波球界面接管 ────────── */
  #startCallBtn{width:64px;height:64px;border-radius:50%;border:none;cursor:pointer;
    pointer-events:auto;background:var(--panel2);color:var(--dim);padding:0;
    display:inline-flex;align-items:center;justify-content:center;outline:none;
    transition:background var(--t-fast) ease,color var(--t-fast) ease,transform var(--t-fast) ease}
  #startCallBtn .ic{width:26px;height:26px}
  #startCallBtn:hover{background:var(--panel);color:var(--text)}
  #startCallBtn:active{transform:scale(.92)}
  #startCallBtn:disabled{opacity:.5;pointer-events:none}

  /* ── 文档预览分屏(点聊天里的文档链接/工具卡文件路径,右侧滑出)────────────── */
  .doclink{display:inline-flex;align-items:center;gap:4px;padding:1px var(--sp-3) 1px var(--sp-2);
    background:var(--panel2);border:1px solid var(--line2);border-radius:var(--r-sm);cursor:pointer;
    color:var(--text);font-size:.93em;text-decoration:none;transition:border-color var(--t-fast),background var(--t-fast)}
  .doclink .ic{width:13px;height:13px;color:var(--accent)}
  @media(hover:hover){ .doclink:hover{border-color:var(--accent);background:var(--panel)} }
  .tc-path.tc-path-doc{cursor:pointer;text-decoration:underline;text-decoration-style:dotted;text-underline-offset:2px}
  @media(hover:hover){ .tc-path.tc-path-doc:hover{color:var(--text)} }

  #docPreview{width:min(46vw,640px);flex-shrink:0;display:flex;flex-direction:column;
    position:relative;background:var(--bg2);border-left:1px solid var(--line2);overflow:hidden}
  #docPreview[hidden]{display:none}
  #dpResize{position:absolute;left:-5px;top:0;bottom:0;width:10px;cursor:col-resize;
    z-index:6;touch-action:none}
  #dpResize::after{content:"";position:absolute;left:4px;top:0;bottom:0;width:2px;
    background:transparent;transition:background var(--t-fast)}
  @media(hover:hover){ #dpResize:hover::after{background:var(--accent)} }
  #dpHead{display:flex;align-items:center;gap:6px;padding:var(--sp-4) var(--sp-4);
    padding-top:calc(10px + env(safe-area-inset-top));border-bottom:1px solid var(--line2);
    background:var(--bar-bg);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);flex-shrink:0}
  .dp-title-wrap{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
  #dpTitle{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
    font-size:var(--fs-md);font-weight:600}
  #dpUrlRow{display:flex;align-items:center;gap:4px;min-width:0}
  #dpUrlText{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
    font-size:var(--fs-sm);color:var(--dim);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
  #dpHead #dpCopyBtn{width:22px;height:22px;border-radius:var(--r-sm);flex-shrink:0;color:var(--dim2);
    display:inline-flex;align-items:center;justify-content:center;transition:background var(--t-fast),color var(--t-fast)}
  #dpHead #dpCopyBtn .ic{width:13px;height:13px}
  #dpHead button{width:32px;height:32px;border-radius:var(--r-md);flex-shrink:0;color:var(--dim);
    display:inline-flex;align-items:center;justify-content:center;transition:background var(--t-fast),color var(--t-fast)}
  @media(hover:hover){ #dpHead button:hover{background:var(--panel2);color:var(--text)} }
  .dp-highlight{background:color-mix(in srgb,var(--accent) 35%,transparent);color:var(--text);border-radius:3px;padding:0 2px;box-decoration-break:clone;-webkit-box-decoration-break:clone}
  #dpBody{flex:1;overflow:auto;position:relative}
  .dp-loading{display:flex;align-items:center;justify-content:center;height:100%;color:var(--dim)}
  .dp-err{padding:20px;color:var(--dim);font-size:var(--fs-md);line-height:1.6}
  .dp-md.bubble{padding:18px 22px;font-size:var(--fs-base);line-height:1.65;max-width:720px}
  .dp-text{margin:0;padding:var(--sp-5) 20px;font-family:ui-monospace,Menlo,Consolas,monospace;
    font-size:var(--fs-sm);line-height:1.6;white-space:pre-wrap;word-break:break-word}
  .dp-frame{width:100%;height:100%;border:none;display:block}
  .dp-img{max-width:100%;display:block;margin:0 auto}

  @media(max-width:760px){
    #docPreview{position:fixed;inset:0;width:100%;z-index:40;border-left:none}
    #dpResize{display:none}
    /* 同样理由：手机上没有"多开一个窗口"这回事，藏起来。#dpWinBtn 在内嵌侧栏
       (index.html)和独立窗口自己的页面(doc-preview.html)都用同一份 styles.css，
       两处一起生效。 */
    #dpWinBtn{display:none}
  }
  #startCallBtn[hidden]{display:none}

  /* ── 核心工作台 Demo：暖黑纸张上的项目作战图 ─────────────────────────── */
  #workbenchView{flex:1;min-width:0;overflow-y:auto;background:
    radial-gradient(800px 520px at 88% -6%,color-mix(in srgb,var(--accent) 12%,transparent),transparent 60%),
    radial-gradient(520px 380px at 6% 28%,color-mix(in srgb,var(--tag-olive) 8%,transparent),transparent 70%),var(--bg2)}
  #workbenchView[hidden]{display:none}
  #wbContent{width:min(1280px,100%);margin:0 auto;padding:42px 42px 72px}
  .wb-hero{padding:var(--sp-4) 0 32px;border-bottom:1px solid var(--line)}
  .wb-kicker{display:flex;align-items:center;gap:8px;color:var(--dim);font-size:var(--fs-sm);font-weight:700;letter-spacing:.12em;text-transform:uppercase}
  .wb-kicker em{font-style:normal;color:var(--accent);font-size:var(--fs-sm);border:1px solid color-mix(in srgb,var(--accent) 60%,var(--line));border-radius:var(--r-pill);padding:1px var(--sp-2);letter-spacing:.08em}
  .wb-pulse{width:8px;height:8px;border-radius:50%;background:var(--tag-gold);box-shadow:0 0 0 5px color-mix(in srgb,var(--tag-gold) 12%,transparent)}
  .wb-hero-grid{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:end;gap:36px;margin-top:18px}
  .wb-hero h1{margin:0;font-family:Optima,"Songti SC","Noto Serif SC",serif;font-size:clamp(32px,4.2vw,58px);font-weight:500;letter-spacing:-.045em;line-height:1.08}
  .wb-hero h1 i{color:var(--accent);font-style:normal}
  .wb-hero p{max-width:570px;margin:16px 0 0;color:var(--dim);font-size:var(--fs-base);line-height:1.75}
  .wb-hero-stats{display:flex;border:1px solid var(--line);border-radius:var(--r-xl);overflow:hidden;background:color-mix(in srgb,var(--panel) 82%,transparent);backdrop-filter:blur(12px)}
  .wb-hero-stats div{min-width:92px;padding:var(--sp-4) var(--sp-5);border-left:1px solid var(--line);display:flex;flex-direction:column;gap:1px}
  .wb-hero-stats div:first-child{border-left:0}.wb-hero-stats b{font:600 24px/1.1 ui-monospace,SFMono-Regular,Menlo,monospace;font-variant-numeric:tabular-nums}.wb-hero-stats span{color:var(--dim2);font-size:var(--fs-sm)}
  .wb-hero-foot{display:flex;gap:14px;flex-wrap:wrap;margin-top:24px;color:var(--dim2);font-size:var(--fs-sm)}.wb-hero-foot span+span::before{content:"/";margin-right:14px;color:var(--line2)}
  .wb-section{margin-top:30px}.wb-section-head{display:flex;justify-content:space-between;align-items:end;gap:16px;margin-bottom:13px}.wb-section-head>div>span{display:block;color:var(--dim2);font-size:var(--fs-sm);line-height:1.2;font-weight:700;letter-spacing:.12em;text-transform:uppercase}.wb-section-head h2{margin:4px 0 0;font-family:Optima,"Songti SC","Noto Serif SC",serif;font-size:22px;line-height:1.1;font-weight:600;letter-spacing:-.02em}
  .wb-clear,.wb-switch{border:1px solid var(--line2);border-radius:var(--r-md);background:color-mix(in srgb,var(--panel) 75%,transparent);color:var(--dim);font-size:var(--fs-sm)}.wb-clear{display:flex;align-items:center;gap:6px;padding:var(--sp-2) var(--sp-4)}.wb-clear .ic{width:13px}.wb-clear.quiet{opacity:.72}.wb-switch{display:flex;padding:var(--sp-1);gap:2px}.wb-switch button{padding:var(--sp-2) var(--sp-3);border-radius:var(--r-sm);color:var(--dim2);font-size:var(--fs-sm)}.wb-switch button.on{color:var(--text);background:var(--panel2)}
  .wb-project-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}.wb-project-card{min-height:166px;border:1px solid var(--line);border-radius:var(--r-xl);padding:var(--sp-5);text-align:left;background:color-mix(in srgb,var(--panel) 68%,transparent);display:flex;flex-direction:column;transition:transform var(--t-fast),border-color var(--t-fast),background var(--t-fast);overflow:hidden;position:relative}.wb-project-card::after{content:"";position:absolute;right:-20px;bottom:-30px;width:115px;height:115px;border-radius:50%;background:var(--wb-wash);filter:blur(2px);opacity:.55}.wb-project-card.sun{--wb-wash:rgba(217,119,87,.20)}.wb-project-card.copper{--wb-wash:rgba(184,133,83,.19)}.wb-project-card.leaf{--wb-wash:rgba(112,151,108,.22)}.wb-project-card.ink{--wb-wash:rgba(127,137,164,.20)}.wb-project-card.selected{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 9%,var(--panel))}@media(hover:hover){.wb-project-card:hover{transform:translateY(-2px);border-color:var(--line2)}}
  .wb-project-top{display:flex;justify-content:space-between;align-items:center}.wb-monogram,.wb-project-state{position:relative;z-index:1}.wb-monogram{width:28px;height:28px;display:grid;place-items:center;border-radius:var(--r-md);background:var(--panel2);font:700 10px/1 ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--text);letter-spacing:.04em}.wb-project-state{font-size:var(--fs-sm);color:var(--dim2)}.wb-project-name{position:relative;z-index:1;margin-top:23px;font-size:var(--fs-xl);font-weight:700}.wb-project-focus{position:relative;z-index:1;margin-top:5px;color:var(--dim);font-size:var(--fs-sm);line-height:1.45}.wb-project-foot{position:relative;z-index:1;margin-top:auto;padding-top:var(--sp-5);display:flex;justify-content:space-between;color:var(--dim2);font-size:var(--fs-sm)}
  .wb-main-grid{display:grid;grid-template-columns:minmax(0,1.45fr) minmax(290px,.8fr);gap:28px;align-items:start}.wb-task-section,.wb-right-rail{min-width:0}.wb-task-list{border-top:1px solid var(--line)}.wb-task{display:flex;align-items:center;gap:12px;padding:var(--sp-4) var(--sp-1);border-bottom:1px solid var(--line);transition:opacity var(--t-fast)}.wb-task.done{opacity:.46}.wb-check{width:22px;height:22px;flex:0 0 22px;border:1px solid var(--line2);border-radius:var(--r-sm);display:grid;place-items:center;color:var(--bg);font-size:var(--fs-sm);font-weight:800}.wb-done .wb-check{background:var(--ok);border-color:var(--ok);color:var(--on-accent)}.wb-cancelled .wb-check{background:var(--dim2);border-color:var(--dim2);color:var(--on-accent)}.wb-block .wb-check{border-color:var(--err);color:var(--err)}.wb-task-copy{min-width:0;flex:1}.wb-task-title{font-size:var(--fs-base);line-height:1.35;font-weight:600}.wb-done .wb-task-title,.wb-cancelled .wb-task-title{text-decoration:line-through}.wb-task-meta{display:flex;align-items:center;gap:5px;margin-top:5px;color:var(--dim2);font-size:var(--fs-sm)}.wb-project-dot{display:inline-grid;place-items:center;width:16px;height:16px;border-radius:var(--r-sm);background:var(--panel2);color:var(--dim);font:700 7px/1 ui-monospace,SFMono-Regular,Menlo,monospace}.wb-project-dot.sun{color:var(--tag-sun)}.wb-project-dot.copper{color:var(--tag-copper)}.wb-project-dot.leaf{color:var(--tag-leaf)}.wb-project-dot.ink{color:var(--tag-ink)}.wb-task-side{display:flex;flex-direction:column;align-items:end;gap:3px;flex:0 0 auto}.wb-when{color:var(--dim2);font-size:var(--fs-sm)}.wb-state{font-size:var(--fs-sm);color:var(--dim)}.wb-focus .wb-state{color:var(--accent);font-weight:700}.wb-block .wb-state{color:var(--err);font-weight:700}.wb-demo-note{margin:13px 0 0;color:var(--dim2);font-size:var(--fs-sm)}
  .wb-right-rail{display:flex;flex-direction:column;gap:3px}.wb-right-rail .wb-section{margin-top:30px}.wb-goal-section{border-top:1px solid var(--line);padding-top:1px}.wb-goal{display:grid;grid-template-columns:28px minmax(0,1fr) auto;gap:9px;align-items:start;padding:var(--sp-4) 0;border-bottom:1px solid var(--line)}.wb-goal-mark{width:24px;height:24px;display:grid;place-items:center;border-radius:var(--r-sm);background:var(--panel2);color:var(--dim);font:700 8px/1 ui-monospace,SFMono-Regular,Menlo,monospace}.wb-goal-project{display:block;color:var(--dim2);font-size:var(--fs-sm)}.wb-goal strong{display:block;margin-top:2px;font-size:var(--fs-sm);line-height:1.38;font-weight:600}.wb-goal-progress{padding-top:var(--sp-2);color:var(--dim2);font:11px/1 ui-monospace,SFMono-Regular,Menlo,monospace;white-space:nowrap}.wb-alert{display:grid;grid-template-columns:3px minmax(0,1fr);gap:11px;padding:var(--sp-4) 0;border-bottom:1px solid var(--line)}.wb-alert-line{background:var(--line2);border-radius:var(--r-md)}.wb-alert.warn .wb-alert-line{background:var(--accent)}.wb-alert>div>span{display:block;color:var(--dim2);font-size:var(--fs-sm);font-weight:700;letter-spacing:.1em;text-transform:uppercase}.wb-alert strong{display:block;margin-top:3px;font-size:var(--fs-sm);line-height:1.3}.wb-alert p{margin:4px 0 0;color:var(--dim);font-size:var(--fs-sm);line-height:1.55}
  @media(max-width:1040px){.wb-project-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.wb-main-grid{grid-template-columns:1fr}.wb-right-rail{display:grid;grid-template-columns:1fr 1fr;gap:22px}.wb-right-rail .wb-section{margin-top:0}}
  @media(max-width:760px){#wbContent{padding:27px 18px 56px}.wb-hero-grid{grid-template-columns:1fr;gap:24px}.wb-hero-stats{width:max-content}.wb-hero h1{font-size:35px}.wb-project-grid{grid-template-columns:1fr 1fr;gap:8px}.wb-project-card{min-height:149px;padding:var(--sp-4)}.wb-project-name{margin-top:18px}.wb-project-foot{gap:7px;flex-direction:column}.wb-right-rail{grid-template-columns:1fr;gap:0}.wb-right-rail .wb-section{margin-top:28px}.wb-task{padding:var(--sp-4) 2px}.wb-task-side{display:none}.wb-section-head h2{font-size:20px}}
  @media(max-width:390px){.wb-project-grid{grid-template-columns:1fr}.wb-project-card{min-height:132px}.wb-project-foot{flex-direction:row}.wb-hero-stats div{min-width:76px;padding:var(--sp-4)}.wb-hero-stats b{font-size:20px}}

  /* ── 工作台：日 / 周 / 月的执行清单，不使用独立视觉语言 ───────────────── */
  #workbenchView{flex:1;min-width:0;overflow-x:hidden;overflow-y:scroll;scrollbar-gutter:stable;background:var(--bg2)}
  #workbenchView[hidden]{display:none}
  #wbContent{width:min(980px,100%);margin:0 auto;padding:26px 32px 56px}
  .wb-toolbar{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:20px;padding:0 0 var(--sp-5);border-bottom:1px solid var(--line)}
  .wb-title{display:flex;align-items:baseline;gap:9px}.wb-title h1{margin:0;font-size:21px;line-height:1.2;font-weight:650;letter-spacing:-.02em}.wb-title span{font-size:var(--fs-sm);color:var(--dim2)}
  .wb-switch{display:flex;gap:16px;padding:0;border:0;border-radius:0;background:none}.wb-switch button{min-width:0;padding:var(--sp-1) 2px;border-radius:var(--r-sm);color:var(--dim);font-size:var(--fs-sm)}.wb-switch button.on{background:var(--panel2);color:var(--text);font-weight:650}
  .wb-date-nav{display:flex;align-items:center;gap:5px;padding:var(--sp-1) 0 var(--sp-1);color:var(--dim)}.wb-date-nav strong{min-width:130px;text-align:center;color:var(--text);font-size:var(--fs-sm);font-weight:600;font-variant-numeric:tabular-nums}.wb-date-nav button{padding:var(--sp-2) var(--sp-4);border-radius:var(--r-sm);color:var(--dim);font-size:var(--fs-sm)}.wb-date-nav button:hover{background:var(--panel);color:var(--text)}.wb-date-nav button[data-nav]{font-size:19px;line-height:16px}
  .wb-rollover-banner{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);margin:var(--sp-4) 0;padding:var(--sp-3) var(--sp-4);border-radius:var(--r-md);background:color-mix(in srgb,var(--warn) 16%,var(--panel));border:1px solid color-mix(in srgb,var(--warn) 40%,transparent);color:var(--text);font-size:var(--fs-sm)}
  .wb-rollover-banner button{flex:0 0 auto;padding:var(--sp-1) var(--sp-4);border-radius:var(--r-sm);background:var(--warn);color:var(--bg);font-weight:650;font-size:var(--fs-sm)}
  .wb-rollover-banner button:hover{filter:brightness(1.08)}
  .wb-rolled-dot{display:inline-block;width:6px;height:6px;margin-right:6px;border-radius:50%;background:var(--warn);vertical-align:middle}
  .wb-project-filter{display:flex;gap:6px;overflow-x:auto;padding:var(--sp-5) 0 1px;border-bottom:1px solid var(--line)}.wb-project-filter button{flex:0 0 auto;padding:var(--sp-2) var(--sp-3);border-radius:var(--r-sm);color:var(--dim);font-size:var(--fs-sm)}.wb-project-filter button:hover,.wb-project-filter button.on{background:var(--panel);color:var(--text)}.wb-project-filter button.on{font-weight:600}
  .wb-section{margin-top:27px}.wb-section-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin-bottom:8px}.wb-section-head h2{margin:0;font-size:var(--fs-md);font-weight:700}.wb-section-head span{color:var(--dim2);font-size:var(--fs-sm)}
  .wb-task-list{border-top:1px solid var(--line)}.wb-task{display:grid;grid-template-columns:22px minmax(0,1fr);gap:10px;padding:var(--sp-4) 2px;border-bottom:1px solid var(--line);align-items:start}.wb-task.done{opacity:.48}.wb-check{width:20px;height:20px;margin-top:1px;border:1px solid var(--line2);border-radius:var(--r-sm);display:grid;place-items:center;color:var(--dim);font-size:var(--fs-sm);font-weight:800}.wb-done .wb-check{background:var(--ok);border-color:var(--ok);color:var(--on-accent)}.wb-cancelled .wb-check{background:var(--dim2);border-color:var(--dim2);color:var(--on-accent)}.wb-block .wb-check{color:var(--err);border-color:var(--err)}
  .wb-task-copy{min-width:0}.wb-task-line{display:flex;align-items:baseline;gap:8px;min-width:0}.wb-task-line strong{min-width:0;font-size:var(--fs-base);line-height:1.4;font-weight:600}.wb-done .wb-task-line strong,.wb-cancelled .wb-task-line strong{text-decoration:line-through}.wb-project-tag{flex:0 0 auto;color:var(--dim2);font-size:var(--fs-sm)}.wb-task-meta{display:flex;gap:5px;margin-top:3px;color:var(--dim2);font-size:var(--fs-sm)}.wb-focus .wb-task-meta{color:var(--accent)}.wb-block .wb-task-meta{color:var(--err)}.wb-task-sources{display:flex;flex-wrap:wrap;gap:5px;margin-top:5px}
  .wb-source-link{max-width:100%;padding:0;color:var(--dim);font-size:var(--fs-sm);line-height:1.4;text-align:left;text-decoration:underline;text-decoration-color:var(--line2);text-underline-offset:2px}.wb-source-link:hover{color:var(--accent);text-decoration-color:var(--accent)}.wb-manual{color:var(--dim2);font-size:var(--fs-sm)}.wb-empty{margin:0;padding:var(--sp-4) 0;border-top:1px solid var(--line);border-bottom:1px solid var(--line);color:var(--dim2);font-size:var(--fs-sm)}
  .wb-project-block{padding:var(--sp-5) 0 var(--sp-1);border-top:1px solid var(--line)}.wb-project-block:last-child{border-bottom:1px solid var(--line)}.wb-project-block>header{display:flex;justify-content:space-between;gap:14px;align-items:baseline}.wb-project-block h2{display:inline;margin:0;font-size:var(--fs-lg);font-weight:700}.wb-project-block header>div>span{margin-left:8px;color:var(--dim2);font-size:var(--fs-sm)}.wb-project-sources{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:7px}.wb-goals{margin-top:10px;padding:0 0 var(--sp-3);border-bottom:1px solid var(--line)}.wb-goal-row{display:flex;align-items:baseline;justify-content:space-between;gap:14px;padding:var(--sp-1) 0}.wb-goal-row strong{font-size:var(--fs-sm);font-weight:600}.wb-goal-row span{display:block;margin-top:1px;color:var(--dim2);font-size:var(--fs-sm)}.wb-project-tasks .wb-task:last-child{border-bottom:0}.wb-unaligned{margin:1px 0 10px;color:var(--accent);font-size:var(--fs-sm)}.wb-demo-note{margin:30px 0 0;padding-top:var(--sp-4);border-top:1px solid var(--line);color:var(--dim2);font-size:var(--fs-sm)}
  .wb-source-panel{position:sticky;bottom:12px;display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px 18px;margin-top:22px;padding:var(--sp-4) var(--sp-5);border:1px solid var(--line2);border-radius:var(--r-md);background:var(--card);box-shadow:var(--shadow)}.wb-source-panel>div>span{display:block;color:var(--dim2);font-size:var(--fs-sm)}.wb-source-panel>div>strong{display:block;margin-top:2px;font-size:var(--fs-md)}.wb-source-panel>button{width:20px;height:20px;border-radius:var(--r-sm);color:var(--dim);font-size:18px;line-height:18px}.wb-source-panel>button:hover{background:var(--panel2);color:var(--text)}.wb-source-panel dl{grid-column:1/-1;display:grid;grid-template-columns:42px minmax(0,1fr);gap:4px 8px;margin:0;font-size:var(--fs-sm)}.wb-source-panel dt{color:var(--dim2)}.wb-source-panel dd{min-width:0;margin:0;color:var(--dim);word-break:break-word}
  @media(max-width:760px){#wbContent{padding:20px var(--sp-5) 44px}.wb-toolbar{display:flex;align-items:flex-start;flex-direction:column;gap:12px}.wb-date-nav{flex:1;justify-content:flex-end}.wb-date-nav strong{min-width:0}.wb-project-block>header{align-items:flex-start;flex-direction:column;gap:5px}.wb-project-sources{justify-content:flex-start}.wb-goal-row{align-items:flex-start}.wb-task-line{align-items:flex-start;flex-direction:column;gap:1px}.wb-source-panel{bottom:8px}}
  @media(max-width:420px){.wb-date-nav{width:100%;justify-content:space-between}.wb-date-nav strong{flex:1}.wb-project-filter{margin:0 -2px}.wb-goal-row .wb-source-link{flex:0 0 auto}}

  /* 工作台沿用聊天页的 820px 内容列与系统字体；只保留 15 / 14 / 12 / 11 四档字号。 */
  #workbenchView,#workbenchView button{font-family:inherit}
  #wbContent{width:min(820px,100%);padding:18px 32px 48px}
  .wb-toolbar{min-height:42px;padding-bottom:var(--sp-4)}.wb-title{gap:8px}.wb-title h1{font-size:var(--fs-lg);letter-spacing:0;font-weight:600}.wb-title span{font-size:var(--fs-sm)}
  .wb-hamb{display:none;width:38px;height:38px;margin:-8px 0 -8px -8px;border-radius:var(--r-lg);align-items:center;justify-content:center;color:var(--dim)}.wb-hamb .ic{width:19px;height:19px}.wb-hamb:hover{background:var(--panel2);color:var(--text)}
  .wb-date-nav strong,.wb-date-nav button{font-size:var(--fs-lg)}.wb-date-nav button[data-nav]{font-size:18px}
  .wb-project-filter button{font-size:var(--fs-sm)}.wb-section{margin-top:24px}.wb-section-head h2{font-family:inherit;font-size:var(--fs-base);line-height:1.4;font-weight:600;letter-spacing:0}.wb-section-head span{font-size:var(--fs-sm)}
  .wb-task{padding:var(--sp-4) 2px}.wb-task-line strong{font-size:var(--fs-base)}.wb-project-tag,.wb-task-meta,.wb-source-link,.wb-manual{font-size:var(--fs-sm)}.wb-task-sources{margin-top:4px}.wb-empty{font-size:var(--fs-sm)}
  .wb-project-block h2{font-size:var(--fs-base)}.wb-project-block header>div>span,.wb-goal-row span,.wb-unaligned{font-size:var(--fs-sm)}.wb-goal-row strong{font-size:var(--fs-base)}.wb-demo-note{font-size:var(--fs-sm)}
  .wb-source-panel>div>span{font-size:var(--fs-sm)}.wb-source-panel>div>strong{font-size:var(--fs-base)}.wb-source-panel dl{font-size:var(--fs-sm)}
  /* 同 #hamb/#collapseBtn:按设备类型决定,不按窗口宽度。 */
  html:not(.device-mobile) body.sb-collapsed .wb-hamb{display:flex}
  @media(max-width:760px){#wbContent{width:100%;padding:18px var(--sp-5) 44px}.wb-hamb{display:flex}.wb-title{min-height:38px}.wb-toolbar{gap:10px}}

  /* 任务是工作台的基本阅读单位：一行看完，不用分割线切碎节奏。 */
  #workbenchView .wb-toolbar,#workbenchView .wb-project-filter,#workbenchView .wb-task-list,
  #workbenchView .wb-task,#workbenchView .wb-project-block,#workbenchView .wb-project-block:last-child,
  #workbenchView .wb-goals,#workbenchView .wb-empty,#workbenchView .wb-demo-note{border:0}
  #workbenchView .wb-section{margin-top:20px}
  #workbenchView .wb-section-head{margin-bottom:5px}
  #workbenchView .wb-task-list{display:flex;flex-direction:column;gap:1px}
  #workbenchView .wb-task{display:grid;grid-template-columns:20px minmax(0,1fr) auto;align-items:center;gap:10px;padding:var(--sp-3) 2px;border-radius:var(--r-sm)}
  @media(hover:hover){#workbenchView .wb-task:hover{background:var(--panel)}}
  #workbenchView .wb-check{margin:0}
  #workbenchView .wb-task-title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--fs-xl);line-height:20px;font-weight:600}
  #workbenchView .wb-task-side{display:flex;align-items:center;justify-content:flex-end;gap:8px;min-width:0;color:var(--dim2);font-size:var(--fs-sm);line-height:20px;white-space:nowrap}
  #workbenchView .wb-task-side .wb-project-tag{color:var(--dim)}
  #workbenchView .wb-task-side .wb-source-link{max-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  #workbenchView .wb-focus .wb-task-side{color:var(--accent)}
  #workbenchView .wb-block .wb-task-side{color:var(--err)}
  #workbenchView .wb-project-block{margin-top:18px;padding:0}
  #workbenchView .wb-project-block>header{padding:0 0 var(--sp-1)}
  #workbenchView .wb-goals{margin:2px 0 4px;padding:0}
  #workbenchView .wb-goal-row{padding:var(--sp-1) 0}
  #workbenchView .wb-demo-note{margin-top:22px;padding-top:0}
  @media(max-width:760px){#workbenchView .wb-task{grid-template-columns:20px minmax(0,1fr) minmax(0,44vw);gap:8px}#workbenchView .wb-task-side{gap:6px;overflow-x:auto;scrollbar-width:none}#workbenchView .wb-task-side::-webkit-scrollbar{display:none}#workbenchView .wb-task-side .wb-project-tag{display:none}#workbenchView .wb-task-side .wb-source-link{max-width:92px}}

  /* 工作台标题栏固定在自身滚动区顶部；列表只显示任务与项目，细节进入详情页。 */
  #workbenchView .wb-toolbar{position:sticky;top:0;z-index:8;padding-top:18px;background:var(--bg2)}
  #workbenchView .wb-task{grid-template-columns:20px minmax(0,1fr) auto;cursor:pointer}
  #workbenchView .wb-project-tag{padding:0;color:var(--dim2);font-size:var(--fs-sm);line-height:20px;white-space:nowrap}
  #workbenchView .wb-section-toggle{width:100%;display:flex;align-items:baseline;justify-content:space-between;gap:12px;padding:0;text-align:left;color:var(--text)}
  #workbenchView .wb-section-toggle h2{margin:0;font-family:inherit;font-size:var(--fs-xl);font-weight:600}
  #workbenchView .wb-section-toggle span{color:var(--dim2);font-size:var(--fs-base)}
  #workbenchView .wb-section-toggle:hover h2{color:var(--accent)}
  .wb-detail-bar{position:sticky;top:0;z-index:8;display:flex;align-items:center;gap:10px;min-height:56px;padding:18px 0 var(--sp-4);background:var(--bg2)}
  .wb-detail-bar button{padding:var(--sp-1) 0;color:var(--dim);font-size:var(--fs-sm)}.wb-detail-bar button:hover{color:var(--accent)}.wb-detail-bar span{color:var(--dim2);font-size:var(--fs-sm)}
  .wb-detail{padding-top:var(--sp-4)}.wb-detail-title{display:block;width:100%;border:0;border-radius:0;background:transparent;color:var(--text);font:600 18px/1.45 inherit;outline:none;padding:var(--sp-1) 0}.wb-detail-title:focus{color:var(--accent)}
  .wb-detail-label,.wb-detail-sources,.wb-detail-images,.wb-detail-context{display:block;margin-top:22px;color:var(--dim2);font-size:var(--fs-sm)}.wb-detail-label textarea{display:block;width:100%;min-height:132px;resize:vertical;margin-top:7px;padding:var(--sp-4) var(--sp-4);border:1px solid var(--line);border-radius:var(--r-md);background:var(--panel);color:var(--text);font:14px/1.6 inherit;outline:none}.wb-detail-label textarea:focus{border-color:var(--accent)}
  .wb-detail-schedule{display:flex;align-items:center;gap:9px;margin-top:22px}.wb-detail-schedule>div{display:flex;flex-direction:column;gap:1px;margin-right:auto}.wb-detail-schedule span{color:var(--dim2);font-size:var(--fs-sm)}.wb-detail-schedule strong{font-size:var(--fs-base)}.wb-detail-schedule button,.wb-detail-images button{padding:var(--sp-2) var(--sp-3);border-radius:var(--r-sm);background:var(--panel2);color:var(--text);font-size:var(--fs-sm)}.wb-detail-schedule button:hover,.wb-detail-images button:hover{background:var(--line2)}.wb-detail-schedule input{width:128px;padding:var(--sp-2) var(--sp-2);border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel);color:var(--text);font-size:var(--fs-sm)}
  .wb-detail-context strong{display:block;margin-top:4px;color:var(--text);font-size:var(--fs-base)}.wb-detail-sources>div{display:flex;flex-wrap:wrap;gap:10px;margin-top:5px}.wb-detail-sources small{display:block;margin-top:5px;color:var(--dim2);font-size:var(--fs-sm)}.wb-detail-sources .wb-source-link{font-size:var(--fs-sm)}
  .wb-detail-images>div:first-child{display:flex;align-items:center;justify-content:space-between;gap:12px}.wb-image-list{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}.wb-image-list figure{position:relative;width:104px;height:78px;margin:0;border-radius:var(--r-sm);overflow:hidden;background:var(--panel)}.wb-image-list img{display:block;width:100%;height:100%;object-fit:cover}.wb-image-list button{position:absolute;right:4px;top:4px;width:22px;height:22px;padding:0;border-radius:50%;background:rgba(0,0,0,.6);color:var(--on-accent);font-size:var(--fs-lg);line-height:20px}
  @media(max-width:760px){#workbenchView .wb-toolbar{padding-top:18px}.wb-detail-bar{padding-top:18px}.wb-detail-schedule{align-items:flex-end;flex-wrap:wrap}.wb-detail-schedule>div{width:100%;margin-right:0}.wb-detail-schedule input{flex:1}.wb-detail-title{font-size:var(--fs-xl)}}

  /* ── 工作台：项目是唯一分组，任务细节原地展开 ───────────────────────── */
  #workbenchView .wb-toolbar{position:sticky;top:0;z-index:8;display:flex;flex-direction:column;align-items:stretch;gap:16px;padding:18px 0 var(--sp-4);background:var(--bg2)}
  #workbenchView .wb-title-row{display:flex;align-items:center;justify-content:space-between;gap:12px}
  #workbenchView .wb-title{display:flex;align-items:center;gap:8px}#workbenchView .wb-title h1{font-size:20px;line-height:26px;font-weight:700}
  #workbenchView .wb-switch-row{display:flex;flex-wrap:wrap;gap:12px}
  #workbenchView .wb-switch{display:flex;gap:2px;padding:var(--sp-1);border-radius:var(--r-md);background:var(--panel)}
  #workbenchView .wb-switch button{padding:var(--sp-2) var(--sp-4);border-radius:var(--r-md);font-size:var(--fs-lg);color:var(--dim);font-weight:400}
  #workbenchView .wb-switch button.on{background:var(--card);color:var(--text);font-weight:600}
  #workbenchView .wb-switch-icon{display:inline-flex;align-items:center;justify-content:center;width:26px}#workbenchView .wb-switch-icon .ic{width:14px;height:14px;vertical-align:0}
  #workbenchView .wb-title-actions{display:flex;align-items:center;gap:4px}
  #workbenchView .wb-win-btn{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border-radius:var(--r-sm);color:var(--dim)}#workbenchView .wb-win-btn .ic{width:15px;height:15px}
  /* hover 只在真有鼠标悬停能力的设备上生效——不然触屏点一下,:hover 在 iOS/Android
     上不会像桌面那样随手指离开就清掉,会一直"糊"在按钮上,看着像卡死的选中状态。
     跟 .wb-project-toggle:hover 同一套写法(见上面)。 */
  @media(hover:hover){ #workbenchView .wb-win-btn:hover{background:var(--panel2);color:var(--text)} }
  /* 选中态不用强调色(橙色),跟 .wb-assignee-opt.is-on 同一个灰阶方案,只是"这个开关按下去了"，
     不是"有需要留意的重要状态"。 */
  #workbenchView .wb-win-btn.is-on{background:var(--panel2);color:var(--text)}
  /* 独立窗口本身(?view=workbench)不需要再开一层同样的窗口;侧边栏靠 sb-collapsed 收起
     但 wb-hamb 展开图标保留(见 app-core.js tryEnter 的 standaloneWorkbench 分支)。
     只挑独立窗口这一个按钮藏——「显示/隐藏备注」「折叠/展开子任务」两个开关跟它共用
     .wb-win-btn 做外观,不能被这条连坐一起藏掉。 */
  body.wb-standalone [data-workbench-win]{display:none!important}
  #workbenchView .wb-project-filter{display:flex;align-items:center;gap:5px;overflow-x:auto;padding:var(--sp-1) 0 var(--sp-1);border:0}#workbenchView .wb-project-filter button{padding:var(--sp-2) var(--sp-4);border-radius:var(--r-md);font-size:var(--fs-lg)}#workbenchView .wb-project-add{display:inline-flex;align-items:center;justify-content:center;padding:var(--sp-2) var(--sp-3);color:var(--dim2)}
  #workbenchView .wb-project-list{display:flex;flex-direction:column;gap:20px;margin-top:16px}#workbenchView .wb-project-block{margin:0;padding:0;border:0}
  #workbenchView .wb-project-toggle{display:flex;align-items:center;gap:8px;width:fit-content;max-width:100%;margin-left:-12px;padding:var(--sp-2) var(--sp-4);border-radius:var(--r-sm);text-align:left;color:var(--text);cursor:pointer;transition:background var(--t-fast),color var(--t-fast)}#workbenchView .wb-project-toggle>span:last-child{color:var(--dim2);font-size:var(--fs-base);line-height:20px}
  @media(hover:hover){ #workbenchView .wb-project-toggle:hover{background:var(--panel)} }
  #workbenchView .wb-project-icon{display:grid;place-items:center;flex:0 0 24px;width:24px;height:24px;color:var(--dim2)}#workbenchView .wb-project-icon .ic{width:17px;height:17px}
  #workbenchView .wb-project-name{display:inline-flex;align-items:center;gap:7px;min-width:0;margin-top:0}#workbenchView .wb-project-name strong{font-size:var(--fs-xl);line-height:20px;font-weight:650}#workbenchView .wb-project-name em{font-style:normal;color:var(--dim2);font-size:var(--fs-base);line-height:20px}
  #workbenchView .wb-chevron{width:7px;height:7px;flex:0 0 7px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(-45deg) translate(-1px,1px)}
  #workbenchView .wb-project-delete{display:block;margin:16px auto 0;padding:var(--sp-1) var(--sp-4);border:0;background:none;color:var(--dim2);font-size:var(--fs-md);opacity:.5;cursor:pointer;transition:opacity var(--t-fast),color var(--t-fast)}
  @media(hover:hover){ #workbenchView .wb-project-delete:hover{opacity:1;color:var(--err)} }
  #workbenchView .wb-task-list{position:relative;display:flex;flex-direction:column;gap:2px;margin:5px -12px 0;padding-bottom:var(--sp-2);border:0}#workbenchView .wb-task{display:grid;grid-template-columns:20px minmax(0,1fr) minmax(120px,170px);align-items:start;gap:10px;padding:var(--sp-2) var(--sp-4);border:0;border-radius:var(--r-sm);cursor:pointer;position:relative}#workbenchView .wb-task:hover{background:var(--panel)}#workbenchView .wb-task.is-selected{background:var(--panel2)}
  #workbenchView .wb-task:not(.wb-task-card){-webkit-user-select:none;user-select:none}
  #workbenchView .wb-task.wb-task-dragging{opacity:.4}
  #workbenchView .wb-task.wb-task-drop-before::before,#workbenchView .wb-task.wb-task-drop-after::after,#workbenchView .wb-task.wb-task-drop-promote::after{content:"";position:absolute;left:0;right:0;height:2px;background:var(--accent);border-radius:1px;pointer-events:none;z-index:2}
  #workbenchView .wb-task.wb-task-drop-before::before{top:-2px}
  #workbenchView .wb-task.wb-task-drop-after::after,#workbenchView .wb-task.wb-task-drop-promote::after{bottom:-2px}
  #workbenchView .wb-task.wb-task-drop-promote::after{left:calc(-1 * var(--wb-child-indent))}
  #workbenchView .wb-task.wb-swipeable.wb-task-drop-before::before{top:0}
  #workbenchView .wb-task.wb-swipeable.wb-task-drop-after::after{bottom:0}
  #workbenchView .wb-task.wb-task-drop-nest{background:color-mix(in srgb,var(--accent) 12%,var(--panel));box-shadow:inset 0 0 0 1.5px var(--accent)}
  #workbenchView .wb-children.is-drop-target::after,#workbenchView .wb-task-list.is-drop-target::after{content:"";position:absolute;left:0;right:0;bottom:calc(var(--sp-2) / 2);height:2px;background:var(--accent);border-radius:var(--r-sm);transform:translateY(50%)}
  #workbenchView .wb-children.is-drop-target::after{left:calc(-1 * var(--wb-child-indent))}
  #workbenchView .wb-check{display:grid;place-items:center;flex:none;width:20px;height:20px;margin:0;padding:0;line-height:1;border-radius:var(--r-sm)}#workbenchView .wb-task-list>.wb-task>.wb-check{margin-top:1px}#workbenchView .wb-task-copy{min-width:0}#workbenchView .wb-task-title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--fs-xl);line-height:20px;font-weight:600}#workbenchView .wb-task-detail{display:-webkit-box;width:100%;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow:hidden;margin:2px 0 0;color:var(--dim2);font-size:var(--fs-md);line-height:1.4}
  #workbenchView .wb-empty{margin:4px 0 0;padding:var(--sp-3) 2px;border:0;color:var(--dim2);font-size:var(--fs-base)}
  /* 整页级空状态：吉祥物 + 标题 + 提示，跟聊天页 #empty 是同一套语言（见该处 .elogo）。 */
  #workbenchView .wb-empty-hero{display:flex;flex-direction:column;align-items:center;margin:4px 0 0;padding:48px var(--sp-4) 40px;text-align:center}
  #workbenchView .wb-empty-hero .voco-mascot{--s:2.6;margin-bottom:var(--sp-4)}
  #workbenchView .wb-empty-hero strong{font-size:var(--fs-xl);font-weight:600;color:var(--text)}
  #workbenchView .wb-empty-hero span{display:block;margin-top:4px;color:var(--dim);font-size:var(--fs-base)}
  /* 移动端新建任务 FAB：只在没有 hover 能力的设备（触屏）上出现，桌面用键盘/侧边按钮就够了。 */
  #wbFab{display:none}
  @media(hover:none){
    #wbFab{display:flex;align-items:center;justify-content:center;position:fixed;right:20px;bottom:calc(20px + env(safe-area-inset-bottom));width:54px;height:54px;border:none;border-radius:50%;background:var(--accent);color:var(--on-accent);font-size:30px;font-weight:300;line-height:1;box-shadow:0 6px 20px rgba(0,0,0,.32);z-index:55;touch-action:none;-webkit-user-select:none;user-select:none}
    #wbFab.wb-fab-off{display:none}
    #wbFab.wb-fab-dragging{box-shadow:0 10px 30px rgba(0,0,0,.45)}
    #workbenchView #wbContent{padding-bottom:88px}
  }
  /* ── 移动端任务行左滑操作（日期 + 移动分组 + 删除）───────────────────── */
  @media(hover:none){
    #workbenchView .wb-task.wb-swipeable{display:block;overflow:hidden;touch-action:pan-y;position:relative;padding:0}
    #workbenchView .wb-swipe-body{display:grid;grid-template-columns:20px minmax(0,1fr) auto;align-items:start;gap:10px;padding:var(--sp-3) var(--sp-4);width:100%;transition:transform var(--t-base) ease}
    #workbenchView .wb-swiping .wb-swipe-body{transition:none}
    #workbenchView .wb-swiped .wb-swipe-body{transform:translateX(-132px)}
    .wb-swipe-actions{position:absolute;top:0;right:0;bottom:0;width:132px;display:flex;transform:translateX(100%);transition:transform var(--t-base) ease}
    .wb-swiping .wb-swipe-actions{transition:none}
    .wb-swiped .wb-swipe-actions{transform:translateX(0)}
    .wb-swipe-btn{flex:1;border:none;display:flex;align-items:center;justify-content:center;color:var(--on-accent);cursor:pointer}
    .wb-swipe-btn .ic{width:18px;height:18px}
    .wb-swipe-date{background:var(--dim2)}
    .wb-swipe-move{background:var(--dim2)}
    .wb-swipe-del{background:var(--err);border-radius:0 7px 7px 0}
    /* 右滑进多选：跟左滑的操作按钮同一个视觉语言，但不常驻展开——松手要么已经
       触发进多选（transform 复位），要么没拖够直接弹回，所以只用 opacity 做反馈。 */
    .wb-swipe-select{position:absolute;top:0;left:0;bottom:0;width:64px;display:flex;align-items:center;justify-content:center;background:var(--dim2);color:var(--on-accent);opacity:0;pointer-events:none}
    .wb-swipe-select .ic{width:18px;height:18px}
    .wb-swipe-select.wb-swipe-select-armed{background:var(--accent)}
    /* 多选模式下行尾常驻的圆形选中指示：平时不占地方（display:none + 0 宽列），
       进多选才现身，跟 is-selected 类联动，不需要为了显示/隐藏它去重渲染整行。 */
    .wb-select-circle{display:none;width:22px;height:22px;border-radius:50%;align-items:center;justify-content:center;border:1.5px solid var(--dim2);color:transparent;flex:none}
    .wb-select-circle .ic{width:13px;height:13px}
  }
  @media(hover:none){
    body.wb-multiselect-mode #workbenchView .wb-swipe-body{grid-template-columns:20px minmax(0,1fr) auto 26px}
    body.wb-multiselect-mode #workbenchView .wb-select-circle{display:flex}
    body.wb-multiselect-mode #workbenchView .wb-task.is-selected .wb-select-circle{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
  }
  /* ── 移动端多选：右上角"完成" + 底部批量操作栏（仿 Things 左滑进多选）──────── */
  #wbMultiDone{display:none}
  @media(hover:none){
    body.wb-multiselect-mode #wbFab{display:none}
    #wbMultiDone{display:flex;align-items:center;justify-content:center;position:fixed;top:calc(10px + env(safe-area-inset-top));right:14px;z-index:56;height:34px;padding:0 var(--sp-5);border:none;border-radius:var(--r-xl);background:var(--accent);color:var(--on-accent);font-size:var(--fs-base);font-weight:600;box-shadow:0 4px 14px rgba(0,0,0,.28)}
    #wbMultiDone[hidden]{display:none}
    #wbMultiBar{position:fixed;left:0;right:0;bottom:0;z-index:56;display:flex;padding:8px 6px calc(8px + env(safe-area-inset-bottom));background:var(--panel);box-shadow:0 -6px 20px rgba(0,0,0,.32)}
    #wbMultiBar[hidden]{display:none}
    #wbMultiBar button{flex:1;display:flex;flex-direction:column;align-items:center;gap:3px;padding:var(--sp-2) 0;border:none;background:transparent;color:var(--text);font-size:var(--fs-sm)}
    #wbMultiBar button:disabled{opacity:.35}
    #wbMultiBar button .ic{width:20px;height:20px}
    #wbMultiBar button.wb-multi-danger{color:var(--err)}
    body.wb-multiselect-mode #workbenchView #wbContent{padding-bottom:96px}
  }
  body.wb-multiselect-mode #workbenchView .wb-task.is-selected{background:color-mix(in srgb,var(--accent) 16%,var(--panel2))}
  /* FAB 新建的 docked 浮层：固定贴在键盘上方（bottom 由 JS 按 visualViewport 实时算），
     不占列表位置，避免被导航栏/键盘挡住；内容一多就自己滚，不会把面板越撑越高。 */
  #wbDock:empty{display:none}
  @media(hover:none){
    /* z-index 65：压过 FAB(55)/右键菜单(60)，但让给日期选择器 .wb-dp(70)——卡片里
       「设定日期」按钮开的就是它，不能被浮层自己盖住。 */
    #wbDock{position:fixed;left:12px;right:12px;bottom:12px;z-index:65;max-height:50vh;overflow-y:auto;border-radius:var(--r-xl);box-shadow:0 -10px 30px rgba(0,0,0,.4)}
    /* 双 id 选择器压过 #workbenchView .wb-editor-shell 那条负 margin（同权重按源码顺序，
       它在文件更后面会赢），不然 docked 卡片在手机宽度下会被拉出 #wbDock 的可视范围。 */
    #workbenchView #wbDock .wb-editor-shell{margin:0}
  }
  @keyframes wbCardIn{from{opacity:0}to{opacity:1}}
  /* 编辑卡沿用任务行的三列栅格：复选框 20px + 10px 间距 + 文字列。
     所有内容落在文字列起点，展开/收起时标题和描述不会左右跳动。 */
  #workbenchView .wb-editor-shell{margin:2px 0 8px;width:auto;padding:var(--sp-4) var(--sp-4);border:1px solid var(--line);border-radius:var(--r-md);background:var(--card);box-shadow:0 6px 12px color-mix(in srgb,var(--text) 4%,transparent);animation:wbCardIn .15s ease}
  #workbenchView .wb-task-card{display:block;cursor:default}
  #workbenchView .wb-task-card:hover{background:var(--card)}
  #workbenchView .wb-card-head{display:flex;align-items:center;gap:10px}#workbenchView .wb-card-title{flex:1;min-width:0;padding:2px 0;border:0;background:transparent;color:var(--text);font-family:inherit;font-size:var(--fs-lg);line-height:20px;font-weight:600;outline:none}
  #workbenchView .wb-editor-head{display:flex;align-items:center;gap:8px;margin-left:30px}#workbenchView .wb-editor-head input{flex:1;min-width:0;padding:2px 0;border:0;background:transparent;color:var(--text);font-family:inherit;font-size:var(--fs-lg);line-height:20px;font-weight:600;outline:none}
  #workbenchView .wb-editor-shell textarea{display:block;width:calc(100% - 30px);min-height:76px;max-height:240px;overflow-y:auto;margin:10px 0 0 30px;padding:0;border:0;background:transparent;color:var(--text);font-family:inherit;font-size:var(--fs-lg);font-weight:400;line-height:1.7;outline:none;resize:none}#workbenchView .wb-editor-shell textarea:focus{color:var(--text)}
  /* 改动还没确认落库时文字调暗，落库成功后恢复正常色，方便肉眼判断有没有保存 */
  #workbenchView .wb-card-title.wb-field-pending,#workbenchView .wb-editor-shell textarea.wb-field-pending{color:var(--dim);transition:color var(--t-fast)}
  #workbenchView .wb-editor-footer{display:flex;align-items:center;gap:7px;margin:10px 0 0 30px}#workbenchView .wb-editor-footer button,#workbenchView .wb-editor-footer select{height:28px;padding:0 var(--sp-3);border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel);color:var(--dim);font-family:inherit;font-size:var(--fs-md);line-height:26px}#workbenchView .wb-editor-footer button:hover{background:var(--panel2);color:var(--text)}.wb-image-list{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}.wb-image-list figure{position:relative;width:104px;height:78px;margin:0;border-radius:var(--r-sm);overflow:hidden;background:var(--panel)}.wb-image-list img{display:block;width:100%;height:100%;object-fit:cover;cursor:zoom-in}.wb-image-list button{position:absolute;right:4px;top:4px;width:22px;height:22px;padding:0;border-radius:50%;background:rgba(0,0,0,.6);color:var(--on-accent);font-size:var(--fs-lg);line-height:20px}
  .wb-ctx-menu{position:fixed;z-index:60;display:none;min-width:180px;max-width:240px;padding:var(--sp-2);border:1px solid var(--line);border-radius:var(--r-md);background:var(--card);box-shadow:var(--shadow);font-size:var(--fs-xl)}
  .wb-ctx-menu button{display:block;width:100%;padding:var(--sp-2) var(--sp-4);border:0;border-radius:var(--r-sm);background:none;text-align:left;color:var(--text);font-size:var(--fs-xl)}
  .wb-ctx-menu button:hover{background:var(--panel2)}
  .wb-ctx-menu .wb-ctx-sep{margin:5px 2px;border-top:1px solid var(--line)}
  .wb-ctx-menu .wb-ctx-danger{color:var(--err)}
  /* 通用"选择浮层"背景层：桌面端透明不挡点击（靠 mousedown 判外部关闭），移动端
     在下面 @media 里变实体半透明+可点击，配合 .wb-ctx-menu 的底部弹出样式一起用。
     .wb-dp 系列（日期选择器）走自己独立的 #wbDpBackdrop，不共用这层。 */
  #wbSheetBackdrop{position:fixed;inset:0;z-index:59;display:none;background:transparent;pointer-events:none}
  #wbSheetBackdrop.show{display:block}
  .wb-sheet-handle{display:none}
  #workbenchView .wb-dp-trigger{display:inline-flex;align-items:center;gap:5px}
  #workbenchView .wb-dp-trigger .ic{width:14px;height:14px;flex:0 0 auto}
  #wbDpBackdrop{position:fixed;inset:0;z-index:69;display:none;background:transparent;pointer-events:none}
  #wbDpBackdrop.show{display:block}
  .wb-dp{position:fixed;z-index:70;display:none;width:280px;padding:var(--sp-4);border:1px solid var(--line);border-radius:var(--r-lg);background:var(--card);box-shadow:var(--shadow);font-size:var(--fs-xl)}
  .wb-dp-search{position:relative;margin-bottom:8px}
  .wb-dp-search input{width:100%;padding:var(--sp-2) 26px var(--sp-2) var(--sp-3);border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel);color:var(--text);font-family:inherit;font-size:var(--fs-xl);outline:none}
  .wb-dp-search-clear{position:absolute;right:4px;top:50%;transform:translateY(-50%);display:grid;place-items:center;width:20px;height:20px;padding:0;border:0;border-radius:50%;background:none;color:var(--dim2)}
  .wb-dp-search-clear:hover{background:var(--panel2);color:var(--text)}
  .wb-dp-search-clear .ic{width:11px;height:11px}
  .wb-dp-results{display:flex;flex-direction:column;gap:2px;max-height:220px;overflow-y:auto}
  .wb-dp-result{display:flex;align-items:center;gap:8px;width:100%;padding:var(--sp-2) var(--sp-3);border:0;border-radius:var(--r-md);background:none;text-align:left;font-family:inherit;font-size:var(--fs-xl);color:var(--text)}
  .wb-dp-result:hover{background:var(--panel2)}
  .wb-dp-result.is-active{background:var(--accent);color:var(--on-accent)}
  .wb-dp-result.is-active .wb-dp-result-weekday{color:var(--wh-3)}
  .wb-dp-result-icon{display:grid;place-items:center;flex:0 0 auto;width:22px;height:22px;border-radius:var(--r-sm);background:var(--err);color:var(--on-accent)}
  .wb-dp-result-icon .ic{width:13px;height:13px}
  .wb-dp-result-label{flex:1;min-width:0;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .wb-dp-result-weekday{flex:0 0 auto;color:var(--dim2);font-size:var(--fs-xl)}
  .wb-dp-actions{display:flex;gap:6px;margin-bottom:10px}
  .wb-dp-actions button{flex:1;display:flex;align-items:center;justify-content:center;gap:5px;height:30px;padding:0;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel);color:var(--text);font-family:inherit;font-size:var(--fs-xl)}
  .wb-dp-actions button .ic{width:13px;height:13px}
  .wb-dp-actions button:hover{background:var(--panel2)}
  .wb-dp-actions button.is-on{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
  .wb-dp-actions button[disabled]{opacity:.4;pointer-events:none}
  .wb-dp-clear{display:grid;place-items:center;width:24px;height:24px;margin:7px 0 0 auto;padding:0;border:0;border-radius:var(--r-sm);background:none;color:var(--dim2);opacity:.45}
  .wb-dp-clear .ic{width:13px;height:13px}
  .wb-dp-clear:hover{background:var(--panel);color:var(--err);opacity:1}
  .wb-dp-clear[disabled]{visibility:hidden;pointer-events:none}
  .wb-dp-picker{min-height:190px}
  .wb-dp-weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:2px;color:var(--dim2);font-size:var(--fs-xl);text-align:center}
  .wb-dp-grid{display:flex;flex-direction:column;gap:8px}
  .wb-dp-grid.is-expanded{max-height:260px;overflow-y:auto;scrollbar-width:thin}
  .wb-dp-week{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}
  .wb-dp-day{display:grid;place-items:center;height:30px;padding:0;border:0;border-radius:var(--r-sm);background:none;color:var(--text);font-family:inherit;font-size:var(--fs-xl);line-height:1.15}
  .wb-dp-day:hover{background:var(--panel2)}
  .wb-dp-day.is-today{color:var(--accent);font-weight:700}
  .wb-dp-day.is-selected{background:var(--accent);color:var(--on-accent);font-weight:700}
  .wb-dp-day.is-month-start{font-size:var(--fs-xl);font-weight:600}
  .wb-dp-expand{display:flex;justify-content:center;width:100%;padding:var(--sp-2) 0 0;border:0;background:none;color:var(--dim2)}
  .wb-dp-expand:hover{color:var(--text)}
  .wb-dp-expand .ic{width:15px;height:15px}
  .wb-dp-week-pager{display:flex;justify-content:space-between;gap:6px;margin-bottom:4px}
  .wb-dp-week-pager button{padding:var(--sp-2) var(--sp-3);border:0;border-radius:var(--r-sm);background:none;color:var(--dim2);font-family:inherit;font-size:var(--fs-md)}
  .wb-dp-week-pager button:hover{background:var(--panel2);color:var(--text)}
  .wb-dp-week-list{display:flex;flex-direction:column;gap:2px;max-height:150px;overflow-y:auto;scrollbar-width:thin}
  .wb-dp-week-row{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;padding:var(--sp-3) var(--sp-4);border:0;border-radius:var(--r-md);background:none;text-align:left;color:var(--text);font-family:inherit;font-size:var(--fs-xl);font-variant-numeric:tabular-nums}
  .wb-dp-week-row:hover{background:var(--panel2)}
  .wb-dp-week-row.is-today{color:var(--accent);font-weight:700}
  .wb-dp-week-row.is-selected{background:var(--accent);color:var(--on-accent);font-weight:700}
  .wb-dp-tag{padding:2px var(--sp-2);border-radius:var(--r-sm);background:var(--panel2);color:var(--dim);font-size:var(--fs-sm);font-weight:600}
  .wb-dp-week-row.is-selected .wb-dp-tag{background:rgba(255,255,255,.25);color:var(--on-accent)}
  .wb-dp-month-nav{display:flex;align-items:center;justify-content:center;gap:14px;margin-bottom:8px;color:var(--dim)}
  .wb-dp-month-nav button{padding:var(--sp-1) var(--sp-4);border:0;border-radius:var(--r-sm);background:none;color:var(--dim);font-size:17px;line-height:16px}
  .wb-dp-month-nav button:hover{background:var(--panel2);color:var(--text)}
  .wb-dp-month-nav strong{min-width:64px;text-align:center;color:var(--text);font-size:var(--fs-xl);font-weight:600;font-variant-numeric:tabular-nums}
  .wb-dp-month-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
  .wb-dp-month{padding:var(--sp-4) 0;border:0;border-radius:var(--r-md);background:var(--panel);color:var(--text);font-family:inherit;font-size:var(--fs-xl)}
  .wb-dp-month:hover{background:var(--panel2)}
  .wb-dp-month.is-today{color:var(--accent);font-weight:700}
  .wb-dp-month.is-selected{background:var(--accent);color:var(--on-accent);font-weight:700}
  @media(max-width:760px){
    /* 底部弹层这套(全屏宽度贴底+拖拽抓手)只给真手机/平板;桌面窗口拉小时
       日期选择器/右键菜单照旧走上面定义的悬浮小面板,不整体变成移动端抽屉。 */
    html.device-mobile #wbDpBackdrop.show{background:var(--ov-3);pointer-events:auto}
    html.device-mobile #wbSheetBackdrop.show{background:var(--ov-3);pointer-events:auto}
    html.device-mobile .wb-ctx-menu{left:0!important;right:0!important;top:auto!important;bottom:0;width:100%;max-width:100%;max-height:70vh;overflow-y:auto;border-radius:16px 16px 0 0;padding:10px 12px calc(10px + env(safe-area-inset-bottom))}
    html.device-mobile .wb-ctx-menu button{padding:var(--sp-4) var(--sp-4)}
    html.device-mobile .wb-dp{left:0!important;right:0;top:auto!important;bottom:0;width:100%;max-width:100%;max-height:78vh;overflow-y:auto;border-radius:16px 16px 0 0;padding:14px 16px calc(14px + env(safe-area-inset-bottom))}
    /* 底部弹层顶部的抓手：只在移动端底部弹出态出现，向下拖拽这一条即可关闭面板
       （逻辑见 workbench.js 里的通用 pointerdown/move/up 拖拽处理）。 */
    html.device-mobile .wb-sheet-handle{display:flex;justify-content:center;margin:-6px -8px 6px;padding:var(--sp-2) 0;touch-action:none}
    html.device-mobile .wb-sheet-handle::after{content:"";width:36px;height:4px;border-radius:2px;background:var(--line2);opacity:.8}
    html.device-mobile .wb-dp-actions button{height:36px}
    html.device-mobile .wb-dp-day{height:36px}
    html.device-mobile .wb-dp-month{padding:var(--sp-4) 0}
    html.device-mobile .wb-dp-picker{min-height:232px}
    html.device-mobile .wb-dp-week-list{max-height:170px}
    html.device-mobile .wb-dp-grid{gap:10px}
  }
  #workbenchView .wb-trash-row{display:flex;align-items:center;justify-content:space-between;gap:12px;cursor:pointer}
  #workbenchView .wb-trash-row .wb-task-title{text-decoration:line-through;color:var(--dim)}
  #workbenchView .wb-trash-row-expanded{display:block;cursor:default}
  #workbenchView .wb-trash-row-expanded .wb-card-head{display:flex;align-items:center;justify-content:space-between;gap:12px}
  #workbenchView .wb-trash-row-expanded .wb-task-title{white-space:normal}
  #workbenchView .wb-trash-detail{margin:8px 0 0;color:var(--dim2);font-size:var(--fs-md);line-height:1.5;white-space:pre-wrap}
  #workbenchView .wb-trash-actions{display:flex;gap:6px;flex:0 0 auto}
  #workbenchView .wb-trash-actions button{display:inline-flex;align-items:center;gap:4px;padding:var(--sp-2) var(--sp-4);border:1px solid var(--line);border-radius:var(--r-sm);background:none;color:var(--dim);font-size:var(--fs-md)}
  #workbenchView .wb-trash-actions button:hover{background:var(--panel2);color:var(--text)}
  #workbenchView .wb-trash-actions .wb-ctx-danger:hover{color:var(--err);border-color:var(--err)}
  #workbenchView .wb-trash-toolbar{display:flex;justify-content:flex-end;padding:2px 0 var(--sp-4)}
  #workbenchView .wb-trash-toolbar .wb-ctx-danger{padding:var(--sp-2) var(--sp-4);border:1px solid var(--line);border-radius:var(--r-sm);color:var(--dim);font-size:var(--fs-md)}
  #workbenchView .wb-trash-toolbar .wb-ctx-danger:hover{color:var(--err);border-color:var(--err)}
  #workbenchView .wb-completed-list{display:flex;flex-direction:column;gap:18px;margin-top:4px}
  #workbenchView .wb-completed-group{padding-top:var(--sp-4);border-top:1px solid var(--line)}#workbenchView .wb-completed-group:first-child{border-top:0;padding-top:0}
  #workbenchView .wb-completed-date{margin:0 0 4px;color:var(--dim2);font-size:var(--fs-md);font-weight:650}
  #workbenchView .wb-new-task{margin-top:8px;border-color:var(--line2)}#workbenchView .wb-new-task .wb-editor-footer{flex-wrap:wrap}#workbenchView .wb-new-task .wb-primary{margin-left:auto;background:var(--text);color:var(--bg2);border-color:var(--text)}
  /* 移动端(≤760px):顶栏改单层内边距(#wbContent 顶部清零,只留 .wb-toolbar 自己
     那一层),仿聊天页 header.bar/callHead 的做法,不再两层内边距叠加。字号已在桌面基础
     上统一到移动端原来的档位,这里不再重复覆盖。 */
  @media(max-width:760px){
    #wbContent{padding-top:0}
    /* iOS PWA(standalone + black-translucent + viewport-fit=cover)下页面顶到状态栏底下,
       顶栏必须自己补 safe-area,做法同 header.bar / #callHead / .shead / .sethead。
       Safari 标签页模式该值为 0,所以浏览器里看不出差别,只有装到桌面才暴露。 */
    #workbenchView .wb-toolbar{gap:10px;padding-top:calc(10px + env(safe-area-inset-top));padding-bottom:var(--sp-4)}
    .wb-detail-bar{padding-top:calc(10px + env(safe-area-inset-top));padding-bottom:var(--sp-4);min-height:0}
    #workbenchView .wb-title h1{font-size:18px;line-height:24px}
    #workbenchView .wb-switch-row{gap:6px}
    #workbenchView .wb-switch{flex-wrap:wrap;gap:1px;padding:2px}
    #workbenchView .wb-switch button{padding:var(--sp-2) var(--sp-3)}
    #workbenchView .wb-task{grid-template-columns:20px minmax(0,1fr) minmax(0,max-content);gap:8px;padding:var(--sp-3) var(--sp-4)}
    /* 编辑卡贴边出血(抵消 #wbContent 左右 16px 内边距,占满整屏宽度)是手机专属的
       视觉选择,只给真手机/平板;桌面窄窗口保留正常两侧留白,不然卡片会算错宽度
       溢出窗口边缘(左侧文字被裁掉)。 */
    html.device-mobile #workbenchView .wb-editor-shell{margin-left:-16px;margin-right:-16px}
    #workbenchView .wb-editor-footer{align-items:flex-start;flex-wrap:wrap}
    /* 独立窗口在移动端点了也没意义(手机浏览器没有多窗口这回事)，直接不显示；
       同一排的「显示/隐藏备注」「折叠/展开子任务」两个开关照常留着。 */
    #workbenchView [data-workbench-win]{display:none}
  }

  /* ── 子任务 / 执行者 / 会话绑定 ─────────────────────────────────── */
  #workbenchView .wb-children{--wb-child-indent:30px;position:relative;margin:0 0 0 var(--wb-child-indent);padding-bottom:var(--sp-2);display:flex;flex-direction:column;gap:2px;will-change:height,opacity}
  #workbenchView .wb-task-child{opacity:.92}
  #workbenchView .wb-task-child .wb-task-title{font-weight:500}
  #workbenchView .wb-editor-footer .wb-add-child{display:inline-flex;align-items:center;gap:4px;color:var(--dim);cursor:pointer}
  #workbenchView .wb-editor-footer .wb-add-child .ic{width:13px;height:13px}
  #workbenchView .wb-editor-footer .wb-add-child:hover{color:var(--accent)}
  #workbenchView .wb-assignee{display:grid;place-items:center;flex:0 0 auto;width:20px;height:20px;color:var(--dim2)}
  #workbenchView .wb-assignee .ic{width:15px;height:15px}
  #workbenchView .wb-schedule{display:inline-flex;align-items:center;gap:4px;min-width:0;padding:0;color:var(--dim);font-size:var(--fs-base);line-height:20px;white-space:nowrap}
  #workbenchView .wb-schedule.is-unscheduled{color:var(--dim2)}
  #workbenchView .wb-schedule:hover{color:var(--accent)}
  #workbenchView .wb-child-toggle{display:grid;place-items:center;flex:0 0 auto;width:20px;height:20px;padding:0;border:0;border-radius:var(--r-sm);background:none;color:var(--dim2);cursor:pointer;transition:background var(--t-fast) ease,color var(--t-fast) ease}
  #workbenchView .wb-child-toggle .ic{width:15px;height:15px}
  #workbenchView .wb-child-toggle:hover{background:var(--panel2);color:var(--text)}
  #workbenchView .wb-task-title-row{display:flex;align-items:center;gap:5px;min-width:0}
  #workbenchView .wb-task-title-row .wb-task-title{flex:0 1 auto}
  #workbenchView .wb-parent-badge{display:inline-flex;align-items:center;gap:3px;min-width:0;max-width:45%;color:var(--dim2);font-size:var(--fs-base);line-height:20px;white-space:nowrap}
  #workbenchView .wb-parent-badge .ic{flex:0 0 auto;width:13px;height:13px}
  #workbenchView .wb-parent-badge span{overflow:hidden;text-overflow:ellipsis}
  #workbenchView .wb-parent-link{display:inline-flex;align-items:center;gap:5px;margin:0 0 8px;padding:0;border:0;background:none;color:var(--dim2);font-size:var(--fs-base);line-height:16px;cursor:pointer}
  #workbenchView .wb-parent-link .ic{width:13px;height:13px}
  #workbenchView .wb-parent-link:hover{color:var(--accent)}
  #workbenchView .wb-task-end{display:flex;align-items:center;gap:8px;min-width:0;justify-content:flex-end}
  #workbenchView .wb-assignee-switch{display:inline-flex;align-items:center;gap:0;padding:0;border:0;background:none}
  #workbenchView .wb-assignee-opt{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:1px solid var(--line);background:none;color:var(--dim2);cursor:pointer;opacity:.35;transition:opacity var(--ease)}
  #workbenchView .wb-assignee-opt:first-child{border-radius:var(--r-sm) 0 0 var(--r-sm)}
  #workbenchView .wb-assignee-opt:last-child{border-radius:0 var(--r-sm) var(--r-sm) 0;border-left:0}
  #workbenchView .wb-assignee-opt .ic{width:15px;height:15px}
  #workbenchView .wb-assignee-opt:hover{opacity:.7}
  #workbenchView .wb-assignee-opt.is-on{color:var(--text);opacity:1}
  #workbenchView .wb-dispatch-btn{display:inline-flex;align-items:center;gap:3px;height:28px;padding:0 var(--sp-4);margin-left:auto;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel);color:var(--dim);font-size:var(--fs-base);font-weight:600;cursor:pointer}
  #workbenchView .wb-dispatch-btn:hover{background:var(--panel2);color:var(--text)}
  #workbenchView .wb-session-links{display:flex;flex-wrap:wrap;align-items:center;gap:6px;min-width:0;margin-left:auto}
  #workbenchView .wb-session-links + .wb-dispatch-btn{margin-left:0}
  #workbenchView .wb-session-link{display:inline-flex;align-items:center;height:28px;max-width:220px;padding:0 var(--sp-3);border-radius:var(--r-sm);overflow:hidden;color:var(--dim);font-size:var(--fs-md);white-space:nowrap;text-overflow:ellipsis;text-decoration:none;cursor:pointer}
  #workbenchView .wb-session-link:hover{background:var(--panel2)}
  #workbenchView .wb-new-child{margin:4px 0 0}
