/* Remote workspace portal. Theme colors are centralized below; panels manage their own
   overflow so desktop and mobile layouts remain usable within the viewport. */
@font-face{font-family:"Geist";src:url(/gateway/geist.woff2) format("woff2");font-weight:100 900;font-display:swap}
@font-face{font-family:"Geist Mono";src:url(/gateway/geist-mono.woff2) format("woff2");font-weight:100 900;font-display:swap}
:root{color-scheme:dark;
  /* 边界分三级（对底色的对比度）：--line 分隔线与卡片外框 ≈1.6:1，--line2 按钮 / 输入框等可交互控件 ≈2.8:1，
     --line3 悬停与强调 ≈3.9:1；面板与底色也拉开一档。以后调色时保持这三级的相对关系，不要再调回接近底色。 */
  --bg:#0E0F11;--panel:#181A1E;--raise:#22252B;--raise2:#2E3239;--line:#33383F;--line2:#565C66;--line3:#6E7580;
  --text:#ECEDEE;--text2:#A6ACB4;--text3:#868D95;
  --signal:#FFB224;--signal-hover:#FFC24D;--on-signal:#141109;--signal-ink:#FFB224;--signal-display:#FFB224;
  --signal-soft:rgba(255,178,36,.14);--signal-line:rgba(255,178,36,.35);--signal-tint:rgba(255,178,36,.06);--signal-tint2:rgba(255,178,36,.05);--signal-ring:rgba(255,178,36,.15);--signal-track:rgba(255,178,36,.2);
  --danger:#FF6B6B;--danger-hover:#FF8585;--on-danger:#170707;--danger-ink:#FF8A8A;--danger-warn:#FF9B9B;--danger-line:rgba(255,107,107,.45);--danger-tint:rgba(255,107,107,.1);--danger-tint2:rgba(255,107,107,.08);
  --ok:#34D399;--ok-ink:#34D399;--ok-halo:rgba(52,211,153,.16);--busy:#F2B33D;
  --track:#343940;--groove:#131518;--groove-shade:rgba(0,0,0,.62);--groove-edge:rgba(0,0,0,.55);--groove-lit:rgba(255,255,255,.14);--folder:#FFB224;--check:#FFB224;--row-hover:#16181B;--drawer-bg:#121417;--surface-float:#1B1E22;--dialog-bg:#16181B;--input-bg:#0E0F11;
  --scrim:rgba(8,9,10,.55);--overlay:rgba(5,6,7,.7);--shadow-float:0 18px 50px rgba(0,0,0,.5);--shadow-dialog:0 30px 80px rgba(0,0,0,.6);
  --term-bg:#08090A;--m-space:#5B9DFF;--m-files:#C4A3FF;--m-traffic:#34D399;--a-claude:#E8875F;--a-codex:#9AA6FF;
  --mono:"Geist Mono",ui-monospace,"SFMono-Regular","Cascadia Mono",Consolas,"DejaVu Sans Mono",monospace;
  --sans:"Geist",system-ui,-apple-system,"Segoe UI","PingFang SC","Hiragino Sans GB","Microsoft YaHei","Noto Sans CJK SC","Noto Sans SC",sans-serif}
:root[data-theme="light"]{color-scheme:light;
  /* 浅色主题是“暗调纸面”而不是纯白：最亮的面（输入框、浮层）亮度约 0.86，页面底色约 0.76，
     比原先的纯白面板（1.0）低约 15%～25%，长时间使用不刺眼。正文、次要文字、强调文字、成功 / 危险文字
     在底色和面板上的对比度都保持 ≥ 4.5:1（以后调整色值时需重新核对）。不要再引入 #FFFFFF 大面积底色。
     边界同样分三级：--line ≈1.35～1.5:1，--line2（控件）≈2.4～2.7:1，--line3 ≈3:1；面板比底色亮一档以区分区块。 */
  --bg:#E1DFD7;--panel:#EEECE6;--raise:#D6D4CC;--raise2:#CBC9C0;--line:#C4C2B9;--line2:#96948B;--line3:#7E7C73;
  --text:#1B1C1F;--text2:#41454C;--text3:#545960;
  --signal:#FFB224;--signal-hover:#F5A300;--on-signal:#1A1203;--signal-ink:#8A5100;--signal-display:#A86500;
  --signal-soft:rgba(198,126,0,.2);--signal-line:rgba(138,81,0,.4);--signal-tint:rgba(255,178,36,.14);--signal-tint2:rgba(255,178,36,.11);--signal-ring:rgba(198,126,0,.24);--signal-track:rgba(138,81,0,.18);
  --danger:#C92828;--danger-hover:#B01F1F;--on-danger:#FFFFFF;--danger-ink:#A81C1C;--danger-warn:#961818;--danger-line:rgba(201,40,40,.42);--danger-tint:rgba(201,40,40,.08);--danger-tint2:rgba(201,40,40,.08);
  --ok:#12965F;--ok-ink:#08653F;--ok-halo:rgba(18,150,95,.18);--busy:#B87D00;
  --track:#CBC9C0;--groove:#D5D1C5;--groove-shade:rgba(104,90,60,.42);--groove-edge:rgba(92,80,54,.34);--groove-lit:rgba(255,255,255,.85);--folder:#9A6300;--check:#8A5100;--row-hover:#D8D6CE;--drawer-bg:#ECEAE4;--surface-float:#EFEDE8;--dialog-bg:#EFEDE8;--input-bg:#F1EFEA;
  --scrim:rgba(22,23,26,.3);--overlay:rgba(22,23,26,.45);--shadow-float:0 14px 40px rgba(40,36,28,.16);--shadow-dialog:0 24px 70px rgba(40,36,28,.22);
  --term-bg:#ECEAE4;--m-space:#2A64D6;--m-files:#7546DE;--m-traffic:#0A7650;--a-claude:#B4502A;--a-codex:#4B57CF}
html.theme-anim *,html.theme-anim *::before,html.theme-anim *::after{transition:background-color .3s ease,border-color .3s ease,color .3s ease,fill .3s ease,stroke .3s ease,box-shadow .3s ease!important}

/* ---------- base ---------- */
*{box-sizing:border-box}
html{height:100%;background:var(--bg)}
body{min-height:100%;margin:0;background:var(--bg);color:var(--text);font-family:var(--sans);font-size:14px;line-height:1.5;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
button,input,select,textarea{font:inherit;color:inherit}
button{cursor:pointer}
a{color:var(--signal-ink)}
:focus-visible{outline:2px solid var(--signal-ink);outline-offset:2px}
[hidden]{display:none!important}
.visually-hidden{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0 0 0 0)!important;white-space:nowrap!important;border:0!important}
code{font-family:var(--mono);font-feature-settings:"tnum" 1}
.muted{color:var(--text3)}
/* 分区小标题；不要叫 .label，文件行里的文件名元素也叫 label（曾因此把文件名渲染成大写小字）。 */
.kicker{margin:0 0 12px;font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--text3)}
/* .mark 是内联 SVG 图标（见网关 LOGO_MARK），自带圆角外框；线条颜色跟随文字颜色。 */
.mark{display:block;flex:none;width:40px;height:40px;color:var(--text)}
.mark svg{display:block;width:100%;height:100%}
.mark .mk-accent{stroke:var(--signal-ink)}.mark .mk-dot{fill:var(--signal-ink)}
@keyframes fade{from{opacity:0}}
@keyframes pop{from{opacity:0;transform:translateY(8px) scale(.985)}}
@keyframes rise{from{opacity:0;transform:translateY(8px)}}
@keyframes spin{to{transform:rotate(360deg)}}

/* ---------- buttons ---------- */
.btn,.dlg-actions button,.dlg-menu button,.picker-list button,.fm-transfer button,.fm-transfers-head button{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:40px;margin:0;padding:0 16px;border:1px solid var(--line2);border-radius:8px;background:transparent;color:var(--text);font-size:13px;font-weight:500;line-height:1.2;text-decoration:none;white-space:nowrap;transition:background .15s,border-color .15s,transform .1s}
.btn:hover,.dlg-actions button:hover,.dlg-menu button:hover,.fm-transfer button:hover,.fm-transfers-head button:hover{background:var(--raise);border-color:var(--line3)}
.btn:active{transform:translateY(1px)}
.btn svg{flex:none;width:16px;height:16px}
.btn.primary,.dlg-actions button:not([class]),.dlg-actions button[class=""]{border-color:var(--signal);background:var(--signal);color:var(--on-signal);font-weight:600}
.btn.primary:hover,.dlg-actions button:not([class]):hover,.dlg-actions button[class=""]:hover{border-color:var(--signal-hover);background:var(--signal-hover)}
.btn.danger,.dlg-menu button.danger{border-color:var(--danger-line);color:var(--danger-ink)}
.btn.danger:hover,.dlg-menu button.danger:hover{border-color:var(--danger);background:var(--danger-tint)}
.dlg-actions button.danger-strong{border-color:var(--danger);background:var(--danger);color:var(--on-danger);font-weight:600}
.dlg-actions button.danger-strong:hover{border-color:var(--danger-hover);background:var(--danger-hover)}
.btn.ghost,.dlg-actions button.secondary{border-color:transparent;color:var(--text2)}
.btn.ghost:hover,.dlg-actions button.secondary:hover{color:var(--text)}
.btn.big{min-height:48px;padding:0 22px;font-size:14px}
.btn[disabled],button[disabled],.btn[aria-disabled="true"]{opacity:.45;cursor:not-allowed}
.icon-btn{display:grid;flex:none;place-items:center;width:44px;height:44px;margin:0;padding:0;border:0;border-radius:8px;background:transparent;color:var(--text3)}
.icon-btn:hover{background:var(--raise);color:var(--text)}
.icon-btn svg{width:18px;height:18px}
.icon-btn[disabled]{opacity:.35}

/* ---------- forms & messages ---------- */
.field{display:grid;gap:6px;margin-bottom:16px}
.field label,.dlg-body label{font-size:12px;color:var(--text2)}
.field input,.dlg-body input[type=text],.dlg-body input[type=password],.dlg-body textarea{width:100%;height:44px;padding:0 12px;border:1px solid var(--line2);border-radius:8px;background:var(--input-bg);color:var(--text);font-family:var(--mono)}
.dlg-body textarea{height:auto;min-height:140px;padding:10px 12px;resize:vertical}
.field input:focus,.dlg-body input:focus,.dlg-body textarea:focus{outline:none;border-color:var(--signal-ink);box-shadow:0 0 0 3px var(--signal-ring)}
.flash{margin:0 0 16px;padding:10px 12px;border-radius:8px;background:var(--raise);font-size:13px}
.flash.error{background:var(--danger-tint2);color:var(--danger-warn)}
.flash.ok{color:var(--ok-ink)}

/* ---------- login & notice pages ---------- */
.login{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(380px,1fr);min-height:100vh;min-height:100dvh}
.login-left{position:relative;display:flex;flex-direction:column;justify-content:space-between;gap:40px;padding:48px 56px 44px;border-right:1px solid var(--line);overflow:hidden}
.login-left::before{content:"";position:absolute;inset:0;background-image:linear-gradient(var(--line) 1px,transparent 1px),linear-gradient(90deg,var(--line) 1px,transparent 1px);background-size:72px 72px;opacity:.35;-webkit-mask-image:linear-gradient(180deg,#000 0%,transparent 75%);mask-image:linear-gradient(180deg,#000 0%,transparent 75%);pointer-events:none}
.login-left>*{position:relative}
.brand{display:flex;align-items:center;gap:12px;font-family:var(--mono);font-size:12px;letter-spacing:.14em;color:var(--text2)}
/* 品牌文字 ciaude.xyz（小写域名，收紧字距）。 */
.brand-name{font-size:16px;font-weight:500;letter-spacing:.02em;color:var(--text)}.brand-name span{color:var(--text3)}
.headline{margin:0;font-size:clamp(40px,5.4vw,76px);font-weight:700;line-height:1.08;letter-spacing:-.02em}
.headline em{font-style:normal;color:var(--signal-display)}
.lede{max-width:520px;margin:22px 0 0;font-size:16px;line-height:1.7;color:var(--text2)}
.features{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));border-top:1px solid var(--line)}
.feature{padding:18px 18px 0 0}
.feature+.feature{padding-left:18px;border-left:1px solid var(--line)}
.feature span{display:block;margin-bottom:8px;font-family:var(--mono);font-size:11px;color:var(--signal-ink)}
.feature b{display:block;margin-bottom:4px;font-size:14px;font-weight:600}
.feature p{margin:0;font-size:12.5px;line-height:1.6;color:var(--text3)}
.login-right{display:flex;align-items:center;justify-content:center;padding:48px 40px;background:var(--panel)}
.form{width:min(100%,360px)}
.form h2{margin:0 0 6px;font-size:24px;font-weight:600}
.form .sub{margin:0 0 28px;font-size:13px;color:var(--text3)}
.pw-wrap{position:relative}
.pw-wrap input{padding-right:64px}
.pw-toggle{position:absolute;right:6px;top:6px;height:32px;padding:0 10px;border:0;border-radius:6px;background:transparent;color:var(--text2);font-size:12px}
.pw-toggle:hover{background:var(--raise);color:var(--text)}
.form .btn.primary{width:100%;min-height:48px;margin-top:8px;font-size:15px}
.form-note{margin:22px 0 0;padding-top:18px;border-top:1px solid var(--line);font-size:12px;line-height:1.7;color:var(--text3)}
.login-theme{margin-left:auto;width:40px;height:40px;border:1px solid var(--line2);border-radius:999px}
.notice{display:grid;place-content:center;justify-items:start;gap:14px;min-height:100vh;min-height:100dvh;padding:40px 24px;max-width:520px;margin:0 auto}
.notice h1{margin:8px 0 0;font-size:28px;font-weight:600}
.notice p{margin:0;color:var(--text2)}

/* ---------- workspace shell ---------- */
body.workspace{height:var(--app-height,100vh);overflow:hidden}
/* 整页严格单屏：行高固定为容器高度（minmax(0,1fr)），各面板只在内部内容区滚动。左栏本身从不滚动（overflow:hidden）：
   窗口变矮时按下方 max-height 断点逐级收紧间距、字号和图标，最矮时只显示图标（文字仍作为读屏名称与悬停提示）。
   不要改回由内容决定或加最小高度，也不要给左栏加滚动，否则矮窗口里底部的主题、退出会被截掉或出现滚动条。 */
.ws{position:relative;display:grid;grid-template-columns:84px minmax(0,1fr);grid-template-rows:minmax(0,1fr);height:100%;overflow:hidden}
.rail{display:flex;flex-direction:column;align-items:center;gap:4px;min-height:0;padding:16px 0 12px;overflow:hidden;border-right:1px solid var(--line);background:var(--bg);z-index:4}
.rail>*{flex-shrink:0}
.rail>.mark{margin-bottom:14px}
.nav-item{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;width:68px;min-height:58px;margin:0;padding:8px 0 6px;border:0;border-radius:10px;background:transparent;color:var(--text3);font-size:12px;line-height:1.2;transition:color .18s,background .18s}
.nav-item:hover{background:var(--raise);color:var(--text)}
.nav-item[aria-selected=true]{color:var(--text)}
.nav-item[aria-selected=true]::before{content:"";position:absolute;left:-8px;top:14px;bottom:14px;width:3px;border-radius:0 3px 3px 0;background:var(--signal-ink)}
.nav-item svg{flex:none;width:22px;height:22px}
.nav-label{white-space:nowrap}
/* 任务导航项的徽标：右上红色 = 需要处理（需要输入 + 失败），左上中性色 = 运行中。 */
.nav-badge{position:absolute;top:3px;display:grid;place-items:center;min-width:17px;height:17px;padding:0 4px;border-radius:9px;font:600 10px/1 var(--mono);pointer-events:none}
.nav-badge.alert{right:7px;background:var(--danger);color:#fff}
.nav-badge.run{left:7px;background:var(--signal-soft);color:var(--signal-ink);box-shadow:inset 0 0 0 1px var(--signal-line)}
.nav-item.attention{color:var(--text)}
.nav-item.attention svg{animation:task-attention 1.6s ease-in-out 3;border-radius:6px}
@keyframes task-attention{50%{box-shadow:0 0 0 4px rgba(255,178,36,.28)}}
.rail-gap{flex:1 1 0;min-height:0}
/* 用量：一个紧凑的三段式圆环按钮（右上空间 / 下文件数 / 左上流量），中间是最高占用百分比；悬停提示与读屏名称
   写明三项名称和“已用 / 上限”，点击打开铺满主工作区的用量面板。暂不可用的一段显示虚线轨道。 */
.usage-ring{display:flex;flex-direction:column;align-items:center;gap:4px;width:68px;margin:0;padding:8px 0 6px;border:1px solid transparent;border-radius:10px;background:transparent;color:var(--text3);font-size:11px;line-height:1.2;transition:background .18s,border-color .18s,color .18s}
.usage-ring:hover,.usage-ring[aria-expanded=true]{background:var(--raise);border-color:var(--line);color:var(--text)}
.usage-ring-dial{position:relative;display:block;width:clamp(38px,6vh,46px);aspect-ratio:1}
.usage-ring-dial svg{display:block;width:100%;height:100%;overflow:visible}
.ring-track,.ring-fill{fill:none;stroke-width:13}
.ring-track{stroke:var(--track)}
.ring-fill{stroke:var(--c);transition:stroke-dasharray .6s cubic-bezier(.2,.8,.2,1)}
.ring-seg.na .ring-track{stroke:var(--line2);stroke-dasharray:4 4}
.ring-seg.na .ring-fill{display:none}
.ring-peak{position:absolute;inset:0;display:grid;place-items:center;font:600 10px/1 var(--mono);letter-spacing:-.03em;color:var(--text2)}
.usage-ring-label{white-space:nowrap}
/* Agent 额度入口（紧挨用量圆环上方）：Claude Code、Codex 各一行，色点 + 主额度窗口里已使用最多的百分比（未读取为“—”；≥90% 标红），
   下面是名称；悬停提示与读屏名称写明两者的状态。点击打开铺满主工作区的额度面板。低矮窗口与用量圆环一起逐级收紧。 */
.quota-entry{display:flex;flex-direction:column;align-items:center;gap:4px;width:68px;margin:0;padding:7px 0 6px;border:1px solid transparent;border-radius:10px;background:transparent;color:var(--text3);font-size:11px;line-height:1.2;transition:background .18s,border-color .18s,color .18s}
.quota-entry:hover,.quota-entry[aria-expanded=true]{background:var(--raise);border-color:var(--line);color:var(--text)}
.quota-lines{display:grid;gap:4px}
.quota-line{display:flex;align-items:center;gap:6px;font:600 11px/1 var(--mono);letter-spacing:-.02em;color:var(--text2)}
.quota-line b{min-width:4ch;font-weight:600;text-align:left;white-space:nowrap}
.quota-dot{flex:none;width:7px;height:7px;border-radius:50%;background:var(--a-claude)}
.quota-line[data-quota-line=codex] .quota-dot{background:var(--a-codex)}
.quota-line[data-tone=good] b{color:var(--text)}
.quota-line[data-tone=low] b,.quota-line[data-tone=error] b{color:var(--danger-ink)}
.quota-line[data-tone=busy] b{color:var(--signal-ink)}
.quota-entry-label{white-space:nowrap}
/* 底部固定：头像一行，主题与退出并排一行。按钮宽度必须与格子一致（36px），否则会超出左栏且点击区域重叠。 */
.account{display:grid;grid-template-columns:repeat(2,36px);place-items:center;gap:6px 4px;width:76px;margin-top:6px;padding-top:8px;border-top:1px solid var(--line)}
.account .icon-btn{width:36px;height:36px}
.account .avatar{grid-column:1/-1}
.avatar{display:grid;place-items:center;width:30px;height:30px;border-radius:50%;background:var(--raise2);font-family:var(--mono);font-size:12px;font-weight:600;text-transform:uppercase}
.main{display:flex;flex-direction:column;min-width:0;min-height:0}
/* 标题与右侧组件放不下时（较窄桌面 + 长 IP + 删除授权倒计时），右侧整组换到下一行靠右，不挤压标题和地址。 */
.head{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:12px 24px;padding:26px 36px 18px;border-bottom:1px solid var(--line)}
.eyebrow{margin:0 0 6px;font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--text3)}
.title{margin:0;font-size:28px;font-weight:600;letter-spacing:-.01em;line-height:1.15}
.head-meta{display:flex;align-items:center;gap:10px;margin-left:auto}
.head-mobile{display:none;align-items:center;gap:2px}
/* ---------- 任务页（网关 task_page_html，app.js TaskMonitor）----------
   与其他功能同级的独立页面：顶部一条紧凑工具栏（筛选、汇总、通知、任务规则、清理已完成），其余高度全部给任务列表，
   只有列表在内部滚动。任务规则是工具栏下方的浮层，展开时盖在列表上方而不是把列表挤下去。 */
.tk{position:relative;display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden}
.tk-bar{display:flex;flex:none;flex-wrap:wrap;align-items:center;gap:8px 12px;padding:10px 36px;border-bottom:1px solid var(--line)}
.tk .btn.small,.tk-bar summary.btn{min-height:32px;padding:0 12px;font-size:12px}
.task-summary{flex:1 1 140px;min-width:0;overflow:hidden;color:var(--text3);font-size:12px;text-overflow:ellipsis;white-space:nowrap}
.tk-actions{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-left:auto}
.tk-actions .btn[aria-pressed=true]{border-color:var(--ok);color:var(--ok-ink)}
.task-filter{display:inline-flex;flex-wrap:wrap;gap:2px;padding:3px;border:1px solid var(--line);border-radius:10px;background:var(--raise)}
.task-filter button{min-height:28px;margin:0;padding:0 8px;border:0;border-radius:7px;background:transparent;color:var(--text2);font:500 11px var(--mono);white-space:nowrap;cursor:pointer}
.task-filter button:hover{color:var(--text)}
.task-filter button[aria-pressed=true]{background:var(--bg);color:var(--text);box-shadow:inset 0 0 0 1px var(--line3)}
.task-filter button:focus-visible,.task-delete:focus-visible{outline:2px solid var(--signal-ink);outline-offset:1px}
.task-rules summary{list-style:none;cursor:pointer}
.task-rules summary::-webkit-details-marker{display:none}
.task-rules[open] summary{border-color:var(--signal-line);background:var(--signal-tint);color:var(--text)}
.tk-bar{position:relative}
.task-rules-pop{position:absolute;z-index:8;top:calc(100% + 6px);right:24px;display:flex;flex-direction:column;width:min(620px,calc(100% - 48px));max-height:var(--pop-max,60vh);padding:14px;overflow:auto;border:1px solid var(--line2);border-radius:12px;background:var(--surface-float);box-shadow:var(--shadow-float);font-size:12px;overscroll-behavior:contain;animation:fade .15s ease}
.task-rules-pop>p{margin:0;color:var(--text2);line-height:1.55}
.task-rule-text{flex:0 1 auto;min-height:80px;max-height:min(46vh,360px);margin:8px 0 0;padding:10px;overflow:auto;border:1px solid var(--line);border-radius:8px;background:var(--input-bg);color:var(--text2);font:11px/1.6 var(--mono);white-space:pre-wrap;overflow-wrap:anywhere;overscroll-behavior:contain}
.task-rule-actions{display:flex;flex:none;flex-wrap:wrap;gap:8px;margin-top:10px}
.task-rule-status{margin:8px 0 0;color:var(--ok-ink);font-size:11px;line-height:1.5}.task-rule-status:empty{display:none}.task-rule-status[data-kind=error]{color:var(--danger-ink)}
.task-problem{flex:none;margin:10px 36px 0;padding:9px 12px;border:1px solid var(--danger-line);border-radius:8px;background:var(--danger-tint2);color:var(--danger-warn);font-size:12.5px;line-height:1.55}
.task-action-status{flex:none;max-height:30%;margin:8px 36px 0;overflow:auto;color:var(--ok-ink);font-size:12px;line-height:1.55}
.task-action-status:empty{display:none}.task-action-status[data-kind=error]{color:var(--danger-ink)}
.task-action-status ul{margin:4px 0 0;padding-left:18px}.task-action-status li+li{margin-top:2px}
.task-action-status small{display:block;color:var(--text3);font-size:11px}
/* 列表占满剩余高度并只在内部滚动；每条任务一张紧凑卡片：标题与状态一行，阶段 · 说明最多两行，右侧是时间与删除。 */
.task-list{display:flex;flex:1 1 0;flex-direction:column;gap:6px;min-height:0;padding:10px 36px 12px;overflow-y:auto;overscroll-behavior:contain}
.task-card{position:relative;display:grid;flex:none;grid-template-columns:minmax(0,1fr) auto;align-items:center;column-gap:14px;row-gap:3px;padding:8px 12px;border:1px solid var(--line);border-left:3px solid var(--line2);border-radius:10px;background:var(--raise)}
.task-card.task-run{border-left-color:var(--signal)}.task-card.task-done{border-left-color:var(--ok)}.task-card.task-input{border-left-color:#d99b32}.task-card.task-failed{border-left-color:var(--danger)}
.task-card-head{display:flex;grid-column:1;align-items:baseline;gap:10px;min-width:0}
.task-card strong{min-width:0;overflow:hidden;font-size:13.5px;text-overflow:ellipsis;white-space:nowrap}
.task-state{flex:none;color:var(--text3);font:500 11px var(--mono)}
.task-detail{display:-webkit-box;grid-column:1;margin:0;overflow:hidden;color:var(--text2);font-size:12px;line-height:1.45;overflow-wrap:anywhere;-webkit-box-orient:vertical;-webkit-line-clamp:2}
.task-detail .task-stage{margin-right:6px;color:var(--text3)}.task-detail .task-stage::after{content:" ·"}
.task-progress{grid-column:1;height:3px;margin-top:2px;overflow:hidden;border-radius:2px;background:var(--track)}.task-progress span{display:block;height:100%;border-radius:inherit;background:var(--signal)}
.task-card-foot{display:flex;grid-column:2;grid-row:1/span 3;align-items:center;gap:8px}
.task-card time{color:var(--text3);font:10.5px var(--mono);white-space:nowrap}
.task-delete{flex:none;min-height:28px;margin:0;padding:0 8px;border:1px solid transparent;border-radius:7px;background:transparent;color:var(--text3);font-size:11px;cursor:pointer}
.task-delete:hover{border-color:var(--danger-line);color:var(--danger-ink)}
.task-empty{margin:auto;text-align:center;color:var(--text3);font-size:13px}
.task-foot{display:flex;flex:none;flex-wrap:wrap;gap:2px 14px;margin:0;padding:6px 36px 8px;border-top:1px solid var(--line);color:var(--text3);font-size:11px;line-height:1.45}
.task-notify-note{color:var(--text2)}
@media(max-width:900px){.tk-bar{padding:8px 16px}.task-list{padding:8px 12px 10px}.task-problem,.task-action-status{margin-left:16px;margin-right:16px}.task-foot{padding:5px 16px 6px}.task-rules-pop{right:12px;width:calc(100% - 24px)}}
@media(max-width:760px){
  /* 手机：筛选按钮已带各状态数量，汇总行只在有异常（格式有误、属主异常、目录不可用）时显示；
     卡片右侧竖排时间与删除，说明最多两行，一屏能看到更多任务。 */
  .tk-bar{gap:6px 8px}.task-summary{order:-1;flex-basis:100%}.task-summary:not([data-issues]){display:none}.tk-actions{margin-left:0}
  .tk .btn.small,.tk-bar summary.btn{min-height:34px;padding:0 10px}.task-filter button{min-height:30px;padding:0 7px}
  .task-card{column-gap:8px;padding:7px 10px}.task-card-foot{flex-direction:column;align-items:flex-end;gap:0}
  .task-card time{font-size:10px}
  .task-delete{min-height:30px;margin-right:-6px}
}
/* 窄手机（≤420px）：筛选占满一行、按钮均分；三个操作按钮三等分一行，文字过长时在按钮内折成两行，工具栏只占两行。 */
@media(max-width:420px){
  .task-filter{display:flex;width:100%}.task-filter button{flex:1 1 auto;padding:0 3px;font-size:10.5px}
  .tk-actions{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));width:100%;gap:6px}
  .tk-actions>.btn.small,.tk-actions summary.btn{width:100%;padding:0 4px;font-size:11px;line-height:1.15;text-align:center;white-space:normal}
  /* 固定说明（删除确认对话框里同样写明）让位给列表；通知说明仍显示。 */
  .task-foot>span:last-child{display:none}.task-foot:has(.task-notify-note[hidden]){display:none}
}
/* ---------- 服务器系统时间（网关 server_clock_html，app.js setupServerClock） ----------
   桌面：标题栏右侧、双 IP 卡片左边的两行文字（时间 + 日期 / 地标（时区名）· UTC 偏移），不加边框，与 IP 卡片区分层级；
   日期（服务器日历日“11月7日 周六”）与时间同一行、次一级颜色，不增加行数，标题栏高度不变。
   秒数用次一级颜色，让“时:分”成为视觉重点。等宽数字，走字时宽度不变、不会推动旁边的卡片。
   手机：标题栏一行放不下第三个组件，时钟改为占用标题上方英文眉标的位置（时间 + 月日 + UTC 偏移），
   标题栏高度不变；星期和完整时区名在悬停提示里。两种只显示其一，读屏只读一次。 */
.server-clock{display:grid;grid-template-columns:minmax(0,1fr) auto;justify-items:end;align-items:baseline;column-gap:7px;row-gap:3px;margin-right:6px;font-family:var(--mono);font-feature-settings:"tnum" 1;line-height:1.2;white-space:nowrap;cursor:default}
.server-clock .clock-time{font-size:15px;font-weight:500;letter-spacing:.02em;color:var(--text)}
.server-clock .clock-date{font-family:var(--sans);font-size:12px;font-weight:500;color:var(--text2)}
.clock-sec{color:var(--text3)}
.server-clock .clock-zone{grid-column:1/-1;justify-self:end;font-size:11px;letter-spacing:.02em;color:var(--text3)}
.head-clock .clock-date{font-family:var(--sans);letter-spacing:.02em}
.head-clock{display:none}
.head-clock .clock-time{color:var(--text2)}
/* 较窄的桌面窗口里双 IP 是长地址（IPv6）时，时钟让位：改到眉标位置，保证两个地址不换行。 */
@media (min-width:761px) and (max-width:1100px){
  .head:has(.ip-route--long) .head-meta>.server-clock{display:none}
  .head:has(.ip-route--long) [data-page-eyebrow]{display:none}
  .head:has(.ip-route--long) .head-clock{display:block;white-space:nowrap}
}
/* ---------- 双 IP 路由（网关 ip_pair_html） ----------
   一条两站的“路由”：上行访问者出口 IP（灰、删除线、空心节点），细线连到下行服务器出口 IP
   （强调色、实心节点）。没有可见标题，语义由节点与连线表达，悬停提示在 title 上。
   约束：地址必须完整显示——不用 ellipsis、不 nowrap 截断，放不下时在任意字符处换行；
   删除线用背景渐变画在行内文本上（box-decoration-break:clone），换行后每一行都有，也能做绘制动画。 */
.head-meta{min-width:0}
.ip-route{--ip-node:7px;--ip-gap:5px;--ip-cycle:3.2s;--ip-dot-r:2.4px;--ip-pad-r:8px;--ip-row-pad:5px;--ip-axis:calc(var(--ip-row-pad) + var(--ip-node) / 2);position:relative;isolation:isolate;display:flex;flex-direction:column;align-items:flex-end;gap:var(--ip-gap);min-width:0;max-width:100%;
  padding:7px var(--ip-pad-r) 7px 10px;border:1px solid var(--line);border-radius:12px;
  background:linear-gradient(180deg,var(--ip-surface,rgba(255,255,255,.025)),transparent);
  font-family:var(--mono);font-feature-settings:"tnum" 1,"zero" 0;text-align:right;transition:border-color .2s}
:root[data-theme="light"] .ip-route{--ip-surface:rgba(255,255,255,.28)}
.ip-route:hover,.ip-route:focus-within{border-color:var(--line2)}
.ip-row{position:relative;display:flex;align-items:center;justify-content:flex-end;gap:11px;max-width:100%;min-width:0;margin:0;padding:1px var(--ip-row-pad);border:0;border-radius:6px;background:none;color:inherit;font:inherit;text-align:right;cursor:copy;transition:color .2s}
.ip-row:disabled{cursor:default}
/* break-word 而不是 anywhere：后者会把最小内容宽度缩到一个字符，导致有空间时也被挤成两行。 */
.ip-val{min-width:0;max-width:100%;overflow-wrap:break-word;word-break:normal}
.ip-user{color:var(--text3);font-size:11.5px;line-height:1.35;letter-spacing:.02em}
.ip-user .ip-text{background:linear-gradient(var(--ip-strike,var(--text3)),var(--ip-strike,var(--text3))) 0 56%/100% 1px no-repeat;
  -webkit-box-decoration-break:clone;box-decoration-break:clone}
.ip-user[data-state="none"] .ip-text{background:none}
.ip-server{color:var(--signal-ink);font-size:13.5px;font-weight:500;line-height:1.3;letter-spacing:.01em}
.ip-server[data-state="pending"]{color:var(--text3)}
.ip-server[data-state="none"]{color:var(--text3);font-weight:400}
.ip-row:not(:disabled):hover{color:var(--text2)}
.ip-server:not(:disabled):hover{color:var(--signal-hover)}
:root[data-theme="light"] .ip-server:not(:disabled):hover{color:var(--signal-display)}
/* 节点：空心（访问者）与实心带光晕（服务器）。连线由两行各画一半：上行从节点中心向下，下行从上方到节点中心。 */
.ip-node{position:relative;z-index:1;flex:none;width:var(--ip-node);height:var(--ip-node);border-radius:50%;box-sizing:border-box;transition:background .2s,box-shadow .2s,border-color .2s}
.ip-user .ip-node{border:1.5px solid var(--line3)}
.ip-server .ip-node{background:var(--signal);box-shadow:0 0 0 3px var(--signal-soft)}
.ip-server[data-state="pending"] .ip-node{background:none;box-shadow:none;border:1.5px solid var(--signal-line);border-top-color:var(--signal);animation:spin .9s linear infinite}
.ip-server[data-state="none"] .ip-node{background:none;box-shadow:none;border:1.5px dashed var(--line3)}
/* 节点中心线（--ip-axis）：行右边缘向左 行内边距 + 节点半径。连线、光点都用 right 从同一条边量起。 */
.ip-user::after,.ip-server::before{content:"";position:absolute;right:calc(var(--ip-axis) - .5px);width:1px;pointer-events:none}
.ip-user::after{top:calc(50% + var(--ip-node) / 2 + 1px);bottom:calc(var(--ip-gap) / -2);background:var(--line2);transform-origin:top}
.ip-server::before{top:calc(var(--ip-gap) / -2);bottom:calc(50% + var(--ip-node) / 2 + 4px);background:linear-gradient(var(--line2),var(--signal-line));transform-origin:top}
.ip-server[data-state="none"]::before{background:var(--line2)}
/* 复制反馈：文字与节点短暂变为完成色，读屏通过 data-ip-live 播报。 */
.ip-row.copied,.ip-row.copied:hover{color:var(--ok-ink)}
.ip-row.copied .ip-node{border-color:var(--ok);background:var(--ok);box-shadow:0 0 0 3px var(--ok-halo)}
.ip-row:focus-visible{outline:2px solid var(--signal-ink);outline-offset:1px}
/* ---- 双 IP 路由的动效状态（data-route 由网关生成、app.js 随服务器地址更新）----
   约束：只动 transform / opacity / background-position（节点光晕、信号光点都是伪元素），不改任何尺寸和位置，
   所以文字、节点、连线和页面布局都不会跳动；全部是 CSS 动画，不用 JS 定时器逐帧改 DOM，
   页面在后台时浏览器自动暂停。减少动态效果时由文件末尾的全局规则关闭全部动画（完全静止）。
   1. pending（查询中）：两段连线柔和呼吸，服务器节点转圈。
   2. ok（两端地址都可用）：常驻信号，见下方“常驻信号时序”。
   3. none（任一端暂不可用）：连线和节点弱化，不显示信号。
   4. is-entering：每次进入工作台播放一次的完整进入动画，期间暂停常驻信号；
      is-settling：载入时仍在查询、随后查询成功，只播放节点点亮 + 地址淡入；
      ip-updated：后台刷新得到新的服务器地址，地址与节点短暂提示。
   5. 复制成功（.copied）时隐藏该行节点的光晕，避免橙色光晕盖住绿色的复制反馈。 */
/* ---- 常驻信号时序 ----
   - 光点只有一个元素 .ip-route::after，从用户节点中心直到服务器节点中心一整段。水平位置纯 CSS：两行都右对齐到
     内容区右边缘，所以与连线一样用 right = --ip-pad-r + --ip-axis 定位，与节点、连线同一条中心线，不经过测量与
     取整。竖直方向的 --ip-y0 / --ip-d 由 app.js measureIpRoute 实测写入（各种宽度、缩放、IPv4 / IPv6 换行都按实际排版）。
   - 光点、用户端发射（ip-signal-emit）、服务器端光晕（ip-signal-arrive）同用 --ip-cycle 与同一组选择器
     同时开始；复制反馈和 ip-updated 都不替换这组动画（见 .copied 与 .ip-node::before），所以不会错位或漂移。
   - 接触规则：光点外缘（半径 --ip-dot-r）首次接触服务器节点圆盘边缘的时刻 = 70%。光点在 6%~100% 匀速：
     6% 位于用户节点中心，70% 前进 d - c（c = 节点半径 + 光点半径，即刚好接触），之后保持同一速度
     （100% 处为 (d - c) × 94 / 64）。光晕关键帧在 70% 之前透明度为 0，所以首个可见光晕帧里光点已接触节点。
   - 节点 z-index:1 盖在光点上方（.ip-route 用 isolation 限制层叠范围），光点越过接触点后被实心节点逐渐遮住，
     等于“进入”节点；光点画在背景里、超出元素底边（节点中心）的部分被裁掉，不会从节点下方穿出。
     94% 之后才把透明度降为 0（此时已完全在节点内），100% → 0% 回到起点时不可见。
   - 只动 background-position / opacity，不改元素尺寸和位置；测量值变化时浏览器沿用当前动画进度，不会重启。 */
.ip-route::after{content:"";position:absolute;right:calc(var(--ip-pad-r) + var(--ip-axis) - 2.5px);top:var(--ip-y0,0px);width:5px;height:var(--ip-d,0px);
  --ip-contact:calc(var(--ip-node) / 2 + var(--ip-dot-r));opacity:0;pointer-events:none;
  background:radial-gradient(circle at 50% 50%,var(--signal) 0 1.4px,transparent var(--ip-dot-r)) 0 -2.5px/5px 5px no-repeat}
.ip-node::after,.ip-node::before{content:"";position:absolute;inset:-4px;border-radius:50%;opacity:0;pointer-events:none}
.ip-user .ip-node::after{inset:-1.5px;background:var(--text3)}
.ip-server .ip-node::after,.ip-server .ip-node::before{background:var(--signal)}
.ip-route[data-route="ok"][data-ip-geo]:not(.is-entering):not(.is-settling)::after{animation:ip-signal-dot var(--ip-cycle) linear infinite}
.ip-route[data-route="ok"][data-ip-geo]:not(.is-entering):not(.is-settling) .ip-user .ip-node::after{animation:ip-signal-emit var(--ip-cycle) ease-out infinite}
.ip-route[data-route="ok"][data-ip-geo]:not(.is-entering):not(.is-settling) .ip-server .ip-node::after{animation:ip-signal-arrive var(--ip-cycle) ease-out infinite}
/* 只盖住透明度，不停止动画：!important 声明优先于动画值，复制反馈结束后光晕仍与光点同一进度。 */
.ip-row.copied .ip-node::after{opacity:0!important}
.ip-route[data-route="pending"]:not(.is-entering) .ip-user::after,.ip-route[data-route="pending"]:not(.is-entering) .ip-server::before{animation:ip-wait 1.6s ease-in-out infinite alternate}
.ip-route[data-route="none"] .ip-user::after,.ip-route[data-route="none"] .ip-server::before{opacity:.4}
.ip-route[data-route="none"] .ip-node{opacity:.7}
@keyframes ip-signal-emit{0%{opacity:0}6%{opacity:.55}16%,100%{opacity:0}}
@keyframes ip-signal-dot{0%,6%{background-position:0 -2.5px;opacity:0}12%,94%{opacity:.7}
  70%{background-position:0 calc(var(--ip-d,0px) - var(--ip-contact) - 2.5px)}
  100%{background-position:0 calc((var(--ip-d,0px) - var(--ip-contact)) * 1.46875 - 2.5px);opacity:0}}
@keyframes ip-signal-arrive{0%,70%{opacity:0;transform:scale(.55)}78%{opacity:.24;transform:scale(1.15)}94%,100%{opacity:0;transform:scale(1.55)}}
@keyframes ip-wait{from{opacity:.3}to{opacity:1}}
/* 完整进入动画：删除线自左向右划过 → 连线向下生长 → 服务器节点点亮并扩散一圈（地址可用时）。 */
.ip-route.is-entering .ip-user .ip-text{animation:ip-strike .55s .25s cubic-bezier(.65,0,.35,1) both}
.ip-route.is-entering .ip-user::after,.ip-route.is-entering .ip-server::before{animation:ip-grow .26s cubic-bezier(.2,.8,.2,1) both}
.ip-route.is-entering .ip-user::after{animation-delay:.72s}.ip-route.is-entering .ip-server::before{animation-delay:.9s}
.ip-route.is-entering .ip-server[data-state="ok"] .ip-node,.ip-route.is-settling .ip-server .ip-node{animation:ip-light .5s 1.08s cubic-bezier(.2,.8,.2,1) both}
.ip-route.is-entering .ip-server[data-state="ok"] .ip-text,.ip-route.is-settling .ip-server .ip-text{animation:ip-reveal .5s 1.08s ease both}
.ip-route.is-settling .ip-server .ip-node,.ip-route.is-settling .ip-server .ip-text{animation-delay:0s}
.ip-server.ip-updated .ip-text{animation:ip-update .9s ease}
/* 更新提示画在 ::before 上，不替换 ::after 的常驻光晕，结束后光晕与光点仍同步。 */
.ip-server.ip-updated .ip-node::before{animation:ip-ping .9s ease-out}
@keyframes ip-strike{from{background-size:0 1px}}
@keyframes ip-grow{from{transform:scaleY(0)}}
@keyframes ip-light{0%{transform:scale(.3);box-shadow:0 0 0 0 var(--signal-soft)}60%{transform:scale(1.15);box-shadow:0 0 0 7px transparent}100%{transform:scale(1);box-shadow:0 0 0 3px var(--signal-soft)}}
@keyframes ip-reveal{from{opacity:.35;filter:saturate(0)}}
@keyframes ip-update{0%{opacity:.2}35%{opacity:1}100%{opacity:1}}
@keyframes ip-ping{0%{opacity:.45;transform:scale(.6)}100%{opacity:0;transform:scale(2)}}
.grant{display:flex;flex:none;align-items:center;gap:8px;white-space:nowrap;padding:5px 12px 5px 7px;border:1px solid var(--signal-line);border-radius:999px;color:var(--signal-ink);font-family:var(--mono);font-size:12px;animation:fade .25s ease}
.grant svg{width:22px;height:22px;transform:rotate(-90deg)}
.grant .ring-track{stroke:var(--signal-track)}.grant .ring-run{stroke:var(--signal-ink);transition:stroke-dashoffset 1s linear}
.ws-panel{position:relative;display:flex;flex:1;flex-direction:column;min-height:0;animation:rise .28s cubic-bezier(.2,.8,.2,1)}
/* ---------- help ----------
   帮助中心：固定工具栏（左上角目录 + 全文搜索 + 阅读进度）下是唯一可滚动的阅读区，文章以“纸页”连续排列。
   颜色全部取自主题变量；搜索高亮用 CSS Custom Highlight API（::highlight，不改写正文 DOM），
   当前命中再由 .help-locator 图层描边。高亮变量放在 :root 上，::highlight 在各浏览器里都能取到。 */
:root{--help-hit:rgba(255,178,36,.22);--help-hit-active:rgba(255,178,36,.86);--help-hit-on:#141109;--help-ring:rgba(255,194,77,.95);
  --help-sheet:var(--panel);--help-well:var(--raise);--help-frame:var(--bg);--help-bar:58px}
:root[data-theme="light"]{--help-hit:rgba(255,178,36,.36);--help-hit-active:#F5B13A;--help-hit-on:#1A1203;--help-ring:#8A5100;
  --help-sheet:#F1EFEA;--help-well:var(--panel);--help-frame:#E7E5DE}
::highlight(help-hit){background-color:var(--help-hit);color:var(--text)}
::highlight(help-hit-active){background-color:var(--help-hit-active);color:var(--help-hit-on)}
.help-shell{position:relative;display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden;background:var(--bg)}
.help-toolbar{position:relative;z-index:9;display:flex;flex:none;align-items:center;gap:12px;height:var(--help-bar);padding:0 clamp(16px,3vw,36px);border-bottom:1px solid var(--line);background:var(--bg)}
.help-menu-btn{display:flex;flex:0 1 auto;align-items:center;gap:9px;min-width:0;max-width:min(440px,46%);height:40px;padding:0 13px 0 11px;border:1px solid var(--line2);border-radius:10px;background:var(--help-sheet);color:var(--text2);cursor:pointer;transition:border-color .15s,background .15s}
.help-menu-btn:hover,.help-menu-btn[aria-expanded=true]{border-color:var(--signal-line);background:var(--signal-tint2)}
.help-menu-btn>svg{flex:none;width:17px;height:17px;color:var(--signal-ink)}
.help-menu-label{flex:none;padding-right:9px;border-right:1px solid var(--line2);color:var(--text3);font-size:12px;line-height:14px}
.help-menu-btn strong{min-width:0;overflow:hidden;color:var(--text);font-size:13px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}
.help-menu-btn i{flex:none;width:7px;height:7px;margin-left:2px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(45deg) translateY(-2px);transition:transform .15s}.help-menu-btn[aria-expanded=true] i{transform:rotate(225deg) translate(-1px,-1px)}
.help-search{position:relative;display:flex;flex:1 1 280px;align-items:center;gap:4px;min-width:0;max-width:460px;height:40px;margin-left:auto;padding:0 5px 0 36px;border:1px solid var(--line2);border-radius:10px;background:var(--input-bg);transition:border-color .15s,box-shadow .15s}
.help-search:hover{border-color:var(--line3)}.help-search:focus-within{border-color:var(--signal-ink);box-shadow:0 0 0 3px var(--signal-ring)}
.help-search>svg{position:absolute;top:50%;left:11px;width:17px;height:17px;margin-top:-8.5px;color:var(--text3);pointer-events:none}
.help-search:focus-within>svg,.help-shell[data-search] .help-search>svg{color:var(--signal-ink)}
.help-search input{flex:1;min-width:0;height:100%;padding:0;border:0;background:transparent;color:var(--text);font-size:13.5px;outline:0;-webkit-appearance:none;appearance:none}
.help-search input::placeholder{color:var(--text3);opacity:1}.help-search input::-webkit-search-cancel-button,.help-search input::-webkit-search-decoration{-webkit-appearance:none;appearance:none}
.help-search-key{flex:none;margin-right:5px;padding:1px 7px;border:1px solid var(--line2);border-radius:5px;color:var(--text3);font:11px/16px var(--mono)}
.help-search:focus-within .help-search-key,.help-shell[data-search] .help-search-key{display:none}
.help-find{display:flex;flex:none;align-items:center;gap:1px}
.help-find-count{padding:0 6px 0 4px;color:var(--text3);font:12px var(--mono);white-space:nowrap}.help-shell[data-search=empty] .help-find-count{color:var(--danger-ink)}
.help-find button{display:grid;place-items:center;width:30px;height:30px;padding:0;border:0;border-radius:7px;background:transparent;color:var(--text2);cursor:pointer}
.help-find button:hover:not(:disabled){background:var(--raise);color:var(--text)}.help-find button:disabled{opacity:.35;cursor:default}
.help-find svg{width:16px;height:16px}.help-find [data-help-next] svg{transform:rotate(180deg)}.help-find [data-help-clear]{margin-left:2px}.help-find [data-help-clear] svg{width:14px;height:14px}
.help-progress{position:absolute;right:0;bottom:-1px;left:0;height:2px;overflow:hidden;pointer-events:none}
.help-progress i{display:block;height:100%;background:linear-gradient(90deg,var(--signal-line),var(--signal));transform:scaleX(0);transform-origin:left}
/* 浮层：目录（左）与搜索结果（右）共用一套外观，互斥打开。 */
.help-popover,.help-results{position:absolute;z-index:10;top:calc(var(--help-bar) + 6px);display:flex;flex-direction:column;max-height:min(520px,calc(100% - var(--help-bar) - 16px));overflow:hidden;border:1px solid var(--line2);border-radius:14px;background:var(--surface-float);box-shadow:var(--shadow-float);animation:rise .16s ease}
.help-popover{left:clamp(16px,3vw,36px);width:min(360px,calc(100% - 32px))}
.help-results{right:clamp(16px,3vw,36px);width:min(560px,calc(100% - 32px))}
.help-popover-head,.help-results-head{display:flex;flex:none;align-items:center;justify-content:space-between;gap:12px;margin:0;padding:12px 16px 10px;border-bottom:1px solid var(--line);color:var(--text);font-size:12.5px;font-weight:600}
.help-results-head{display:block;color:var(--text2);font-weight:500}.help-results-head b{color:var(--text);font-weight:600}
.help-count{color:var(--text3);font-size:11.5px;font-weight:500}
.help-list{display:flex;flex-direction:column;gap:2px;min-height:0;padding:6px;overflow:auto;overscroll-behavior:contain;counter-reset:help}
.help-list button{display:flex;align-items:center;gap:12px;min-height:42px;padding:8px 12px;border:0;border-radius:9px;background:transparent;color:var(--text2);text-align:left;cursor:pointer;counter-increment:help}
.help-list button::before{content:counter(help,decimal-leading-zero);flex:none;min-width:20px;color:var(--text3);font:500 11.5px var(--mono)}
.help-list button:hover{background:var(--row-hover);color:var(--text)}
.help-list button[aria-current=true]{background:var(--signal-tint2);box-shadow:inset 2px 0 0 var(--signal);color:var(--signal-ink);font-weight:600}.help-list button[aria-current=true]::before{color:var(--signal-ink)}
.help-list button:focus-visible{outline:2px solid var(--signal-ink);outline-offset:-2px}
.help-results-list{min-height:0;padding:0 6px 6px;overflow:auto;overscroll-behavior:contain}
.help-results-group+.help-results-group{margin-top:2px;border-top:1px solid var(--line)}
.help-results-doc{position:sticky;z-index:1;top:0;display:flex;align-items:center;gap:8px;margin:0;padding:10px 10px 6px;background:var(--surface-float);color:var(--text);font-size:12.5px;font-weight:600}
.help-results-doc span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.help-results-doc b{flex:none;color:var(--signal-ink);font:600 11px var(--mono)}
.help-results-doc small{flex:none;margin-left:auto;padding:1px 8px;border-radius:999px;background:var(--raise);color:var(--text2);font:500 11px/16px var(--mono)}
.help-results-list [role=option]{display:block;padding:7px 10px 8px 12px;border-radius:9px;color:var(--text2);font-size:13px;line-height:1.55;cursor:pointer}
.help-results-list [role=option]:hover{background:var(--row-hover)}
.help-results-list [role=option][aria-selected=true]{background:var(--signal-tint2);box-shadow:inset 2px 0 0 var(--signal);color:var(--text)}
.help-results-section{display:block;overflow:hidden;color:var(--text3);font-size:11.5px;line-height:1.5;text-overflow:ellipsis;white-space:nowrap}
.help-results-snippet{display:-webkit-box;overflow:hidden;overflow-wrap:anywhere;-webkit-box-orient:vertical;-webkit-line-clamp:2}
.help-results-snippet mark{padding:0 2px;border-radius:3px;background:var(--help-hit);color:var(--text);font-weight:600}
.help-no-results{flex:none;margin:0;padding:22px 18px 24px;color:var(--text3);font-size:13px;text-align:center}
/* 阅读区 */
.help-reader{position:relative;flex:1;min-width:0;min-height:0;padding:clamp(18px,2.6vw,32px) clamp(14px,4vw,56px) 72px;overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable}
.help-locator{position:absolute;top:0;left:0;z-index:1;width:0;height:0;pointer-events:none}
.help-locator span{position:absolute;border-radius:3px;box-shadow:0 0 0 2px var(--help-ring)}
.help-locator span.pulse{animation:help-locate 1.2s cubic-bezier(.2,.8,.2,1)}
@keyframes help-locate{0%{box-shadow:0 0 0 2px var(--help-ring),0 0 0 0 var(--signal-soft)}35%{box-shadow:0 0 0 2px var(--help-ring),0 0 0 10px var(--signal-soft)}100%{box-shadow:0 0 0 2px var(--help-ring),0 0 0 16px transparent}}
.help-doc{width:min(1180px,100%);margin:0 auto;padding:clamp(22px,3vw,44px) clamp(18px,3.4vw,52px) clamp(26px,3.2vw,48px);border:1px solid var(--line);border-radius:18px;background:var(--help-sheet);color:var(--text2);font-size:15px;line-height:1.8;overflow-wrap:anywhere}
.help-doc+.help-doc{margin-top:clamp(18px,2.6vw,30px)}
.help-doc-head{margin:0 0 clamp(18px,2.2vw,26px);padding-bottom:clamp(14px,1.8vw,20px);border-bottom:1px solid var(--line)}
.help-doc-kicker{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px;margin:0 0 10px;color:var(--text3);font-size:12px;line-height:1.4}
.help-doc-kicker span:last-child::before{content:"";display:inline-block;width:3px;height:3px;margin:0 10px 3px 0;border-radius:50%;background:currentColor;vertical-align:middle}
.help-doc-no{display:inline-grid;place-items:center;min-width:32px;height:22px;padding:0 7px;border-radius:6px;background:var(--signal-soft);color:var(--signal-ink);font:600 11.5px var(--mono)}
.help-doc-head h1{margin:0;color:var(--text);font-size:clamp(24px,2.4vw,31px);font-weight:650;line-height:1.25;letter-spacing:-.005em}
.help-doc>:is(p,ul,ol,blockquote,pre,h2,h3){max-width:50em}
/* 正文里的 # 与 ## 都是小节标题（文章标题在 .help-doc-head 里）：左侧一道强调色短线。 */
.help-doc>h1,.help-doc>section h1,.help-doc h2{position:relative;margin:clamp(30px,3.2vw,40px) 0 12px;padding-left:14px;color:var(--text);font-size:clamp(19px,1.7vw,22px);font-weight:650;line-height:1.4}
.help-doc>h1,.help-doc>section h1{font-size:clamp(20px,1.9vw,24px)}
.help-doc>h1::before,.help-doc>section h1::before,.help-doc h2::before{content:"";position:absolute;top:.3em;bottom:.3em;left:0;width:3px;border-radius:3px;background:var(--signal)}
.help-doc-head+:is(h1,h2){margin-top:6px}
.help-doc h3{margin:24px 0 8px;color:var(--text);font-size:16.5px;font-weight:600;line-height:1.45}
.help-doc p{margin:10px 0}.help-doc strong{color:var(--text);font-weight:600}
.help-doc code{padding:2px 6px;border:1px solid var(--line);border-radius:6px;background:var(--help-well);color:var(--signal-ink);font:12.5px var(--mono)}
.help-doc pre{margin:16px 0;padding:14px 16px;overflow:auto;border:1px solid var(--line);border-radius:10px;background:var(--help-frame);line-height:1.6}.help-doc pre code{padding:0;border:0;background:none;color:var(--text2)}
.help-doc blockquote{margin:14px 0;padding:11px 16px;border:1px solid var(--signal-line);border-left-width:3px;border-radius:10px;background:var(--signal-tint);color:var(--text)}
.help-doc a{color:var(--signal-ink);text-decoration-thickness:1px;text-underline-offset:3px}
.help-doc ul,.help-doc ol{margin:10px 0;padding-left:1.4em}.help-doc li{margin:6px 0;padding-left:3px}.help-doc li::marker{color:var(--signal-ink)}.help-doc ol>li::marker{font:600 .9em var(--mono)}
.help-doc img{display:block;max-width:100%;height:auto;margin:18px auto;border:1px solid var(--line);border-radius:10px}
.help-media-row,.help-card{display:grid;grid-template-columns:minmax(360px,62%) minmax(0,1fr);align-items:center;gap:0 clamp(22px,3vw,44px);margin:22px 0 30px;padding:clamp(14px,1.6vw,20px);border:1px solid var(--line);border-radius:16px;background:var(--help-well)}
.help-media{display:grid;place-items:center;aspect-ratio:16/9;min-width:0;margin:0;overflow:hidden;border:1px solid var(--line2);border-radius:11px;background:var(--help-frame)}
.help-image-open{position:relative;display:block;width:100%;height:100%;padding:0;border:0;background:transparent;cursor:zoom-in}.help-image-open:focus-visible{outline:2px solid var(--signal-ink);outline-offset:-3px}
.help-image-open::after{content:"放大";position:absolute;right:10px;bottom:10px;padding:3px 9px;border-radius:7px;background:var(--surface-float);box-shadow:0 0 0 1px var(--line2);color:var(--text2);font-size:11.5px;line-height:18px;opacity:0;transition:opacity .15s}
.help-image-open:hover::after,.help-image-open:focus-visible::after{opacity:.92}
.help-media img{width:100%;height:100%;max-width:none;margin:0;border:0;border-radius:0;object-fit:contain}
.help-media-copy{min-width:0}.help-media-copy>:first-child{margin-top:0}.help-media-copy>:last-child{margin-bottom:0}
.help-card>.help-media{grid-column:1;grid-row:1/span 99}.help-card>:not(.help-media){grid-column:2;min-width:0}.help-card>:first-child:not(.help-media){margin-top:0}.help-card>:last-child{margin-bottom:0}
.help-card h3{margin-top:0}
.help-lightbox{width:min(96vw,1800px);max-width:none;height:min(94vh,1100px);max-height:none;margin:auto;padding:44px 16px 16px;overflow:hidden;border:1px solid var(--line2);border-radius:14px;background:var(--surface-float);box-shadow:var(--shadow-float)}
.help-lightbox::backdrop{background:rgba(0,0,0,.82);backdrop-filter:blur(5px)}.help-lightbox img{display:block;width:100%;height:100%;margin:0;border:0;border-radius:8px;box-shadow:none;object-fit:contain}
.help-lightbox-close{position:absolute;top:8px;right:10px;display:grid;place-items:center;width:34px;height:34px;padding:0;border:1px solid var(--line2);border-radius:50%;background:var(--raise);color:var(--text);font-size:22px;line-height:1;cursor:pointer}.help-lightbox-close:hover{border-color:var(--signal-line);color:var(--signal-ink)}
.agreement-locked .rail-gap,.agreement-locked .usage-ring,.agreement-locked .quota-entry,.agreement-locked .account .avatar,.agreement-locked [data-theme-open],.agreement-locked .head-meta>*:not(.head-mobile){display:none}
.agreement-locked .head-mobile [data-theme-open]{display:none}.agreement-locked .help-menu-btn{pointer-events:none}.agreement-locked .help-menu-btn i{display:none}
.agreement-confirm{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:8px 20px;padding:14px 20px;border-top:1px solid var(--line);background:var(--help-sheet)}
.agreement-confirm>p{margin:0;color:var(--text2);font-size:12px}.agreement-confirm>label{display:flex;align-items:center;gap:8px;font-size:13px}.agreement-password{grid-column:1}.agreement-password input{min-width:220px;margin-left:8px}.agreement-confirm .btn{grid-column:2;grid-row:1/3}.agreement-status{grid-column:1/3;color:var(--danger)!important}
@media(max-width:760px){.agreement-confirm{grid-template-columns:1fr;padding:10px 14px}.agreement-password,.agreement-confirm .btn,.agreement-status{grid-column:1;grid-row:auto}.agreement-password{display:grid!important;grid-template-columns:1fr}.agreement-password input{width:100%;min-width:0;margin:0}}
.help-empty{display:grid;place-content:center;flex:1;min-height:0;padding:24px;text-align:center;color:var(--text3)}.help-empty>span{display:grid;place-items:center;width:52px;height:52px;margin:0 auto 16px;border:1px solid var(--line2);border-radius:50%;font:24px var(--mono);color:var(--signal-ink)}.help-empty h2{margin:0 0 8px;color:var(--text);font-size:18px}.help-empty p{margin:0;font-size:13px}
@media(max-width:900px){.help-media-row,.help-card{grid-template-columns:1fr;gap:16px}.help-media{width:100%}.help-card>.help-media,.help-card>:not(.help-media){grid-column:1;grid-row:auto}}
/* 手机：目录按钮与搜索框共用一行；正在搜索时目录按钮收成图标，把宽度让给搜索框和命中计数。 */
@media(max-width:760px){:root{--help-bar:54px}
  .help-toolbar{gap:8px;padding:0 12px}.help-menu-btn{flex:0 1 44%;max-width:none;padding:0 10px}.help-menu-label,.help-search-key{display:none}
  .help-shell.is-searching .help-menu-btn{flex:none;width:40px;padding:0;justify-content:center}.help-shell.is-searching .help-menu-btn :is(strong,i){display:none}
  .help-search{flex:1 1 0;max-width:none;margin-left:0;padding-left:32px}.help-search>svg{left:10px}.help-find-count{padding:0 3px}
  .help-popover,.help-results{right:12px;left:12px;width:auto}
  .help-reader{padding:12px 10px 48px}.help-doc{padding:20px 16px 24px;border-radius:14px;font-size:14.5px;line-height:1.75}.help-doc-head h1{font-size:23px}
  .help-media-row,.help-card{gap:14px;margin:16px 0 24px;padding:10px;border-radius:12px}
  .help-lightbox{width:100vw;height:100dvh;padding:56px 8px 8px;border:0;border-radius:0}.help-lightbox-close{top:8px;right:8px;width:40px;height:40px}.help-lightbox img{border-radius:4px}}
@media(max-width:380px){.help-find button{width:28px}.help-doc{padding:18px 13px 22px}}
@media(pointer:coarse){.help-find button{width:34px;height:34px}.help-search{height:42px}.help-image-open::after{opacity:.9}}
@media(max-height:560px) and (min-width:761px){:root{--help-bar:50px}.help-menu-btn,.help-search{height:36px}.help-reader{padding-top:16px}}
@media(max-height:480px){:root{--help-bar:48px}.help-menu-btn{height:36px}.help-search{height:38px}.help-find button{width:30px;height:30px}.help-reader{padding-top:10px}}
@media(forced-colors:active){::highlight(help-hit){background-color:Mark;color:MarkText}::highlight(help-hit-active){background-color:Highlight;color:HighlightText}.help-locator span{outline:2px solid Highlight}}
.flash-toast{position:fixed;right:28px;bottom:28px;z-index:30;display:flex;align-items:center;gap:10px;max-width:min(440px,calc(100vw - 24px));padding:10px 8px 10px 16px;border:1px solid var(--line2);border-radius:10px;background:var(--surface-float);box-shadow:var(--shadow-float);font-size:13px;animation:rise .25s cubic-bezier(.2,.8,.2,1)}
.flash-toast::before{content:"";flex:none;width:7px;height:7px;border-radius:50%;background:var(--ok)}
.flash-toast.error::before{background:var(--danger)}
.flash-toast .icon-btn{width:32px;height:32px}

/* ---------- remote browser ---------- */
.launch{flex:1;min-height:0;overflow:auto;display:grid;grid-template-columns:minmax(0,1.1fr) minmax(0,1fr);margin:0}
.launch-left{padding:36px;border-right:1px solid var(--line)}
.launch-right{display:flex;flex-direction:column;justify-content:flex-start;gap:22px;padding:36px 48px}
.launch.running{grid-template-columns:minmax(0,1fr)}
.launch.running .launch-right{max-width:720px}
.devices{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}
.device{position:relative;display:flex;flex-direction:column;align-items:center;gap:14px;min-height:190px;padding:22px 12px 16px;border:1px solid var(--line2);border-radius:10px;color:var(--text2);text-align:center;cursor:pointer;transition:border-color .15s,background .15s}
.device:hover{border-color:var(--line3);background:var(--row-hover)}
.device:has(input:checked){border-color:var(--signal-ink);background:var(--signal-tint2);color:var(--text)}
.device:has(input:focus-visible){outline:2px solid var(--signal-ink);outline-offset:2px}
.device-shape{display:flex;flex:1;align-items:center;justify-content:center}
.device-shape i{display:block;border:1.5px solid currentColor;border-radius:5px;opacity:.85}
.device:has(input:checked) .device-shape i{border-color:var(--signal-ink)}
.device b{display:block;font-size:14px;font-weight:600;color:var(--text)}
.device small{display:block;margin-top:2px;font-family:var(--mono);font-size:11px;color:var(--text3);white-space:nowrap}
.launch .res-hd{display:none}
.launch.running .launch-right{padding-top:48px}
.launch:has(input[name=quality][value=hd]:checked) .res-hd{display:inline}
.launch:has(input[name=quality][value=hd]:checked) .res-smooth{display:none}
.seg{display:inline-flex;padding:3px;border:1px solid var(--line2);border-radius:9px}
.seg label{position:relative;display:grid;place-items:center;min-height:34px;padding:0 16px;border-radius:6px;color:var(--text2);font-size:13px;cursor:pointer}
.seg label:has(input:checked){background:var(--raise);color:var(--text);box-shadow:inset 0 0 0 1px var(--line3)}
.seg label:has(input:focus-visible){outline:2px solid var(--signal-ink)}
.launch-title{margin:0;font-size:26px;font-weight:600;line-height:1.35}
.big-time{margin:0;font-family:var(--mono);font-size:64px;font-weight:500;letter-spacing:-.02em;line-height:1}
.big-time.late{color:var(--danger-ink)}
.facts{display:grid;grid-template-columns:auto 1fr;align-items:center;gap:10px 24px;margin:0;font-size:13px}
.facts dt{color:var(--text3)}
.facts dd{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0;font-family:var(--mono);color:var(--text)}
.facts code{font-size:15px;letter-spacing:.06em}
.facts .btn{min-height:30px;padding:0 10px;font-family:var(--sans);font-size:12px}
.actions{display:flex;flex-wrap:wrap;gap:10px}
.actions form{margin:0}

/* ---------- web terminal ---------- */
.term{display:flex;flex:1;flex-direction:column;min-height:0}
.term-bar{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;min-height:52px;padding:8px 36px 0;border-bottom:1px solid var(--line)}
.term-tabs{display:flex;align-items:flex-end;gap:2px;min-width:0;overflow-x:auto;scrollbar-width:none}
.term-tabs::-webkit-scrollbar{display:none}
.term-tab{display:flex;align-items:center;height:42px;padding:0 4px 0 12px;border:1px solid transparent;border-bottom:0;border-radius:8px 8px 0 0;color:var(--text3);font-size:13px;white-space:nowrap;animation:fade .2s ease}
.term-tab.active{position:relative;top:1px;border-color:var(--line);background:var(--term-bg);color:var(--text)}
.term-tab-open{display:flex;align-items:center;gap:8px;height:100%;margin:0;padding:0 4px 0 0;border:0;background:transparent;color:inherit}
.tab-no{font-family:var(--mono);font-size:11px;color:var(--text3)}
.term-tab.active .tab-no{color:var(--signal-ink)}
.term-tab-close{display:grid;place-items:center;width:28px;height:28px;margin:0;padding:0;border:0;border-radius:6px;background:transparent;color:var(--text3);font-size:16px;line-height:1}
.term-tab-close:hover{background:var(--raise);color:var(--text)}
.term-tab-new{display:flex;align-items:center;gap:6px;height:34px;margin:0 0 4px 8px;padding:0 12px;border:1px dashed var(--line2);border-radius:8px;background:transparent;color:var(--text2);font-size:12px;white-space:nowrap}
.term-tab-new:hover{border-color:var(--text3);color:var(--text)}
.term-tab-new[disabled]{border-style:solid;color:var(--text3);opacity:1}
.term-tab-new .short{display:none}
.term-tools{display:flex;flex:none;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:8px;min-width:0;padding-bottom:8px}.term-modes{display:inline-flex;padding:3px;border:1px solid var(--line);border-radius:10px;background:var(--raise)}.term-modes .btn{min-height:32px;margin:0;padding:0 10px;border:0}.term-modes .btn.active{background:var(--signal);color:var(--on-signal);box-shadow:none}
.term-frame{position:relative;flex:1;min-height:0;overflow:hidden;background:var(--term-bg)}
.term-frame .term-view{position:absolute;inset:0;display:block;width:100%;height:100%;border:0;background:var(--term-bg);visibility:hidden}
.term-frame .term-view.active{visibility:visible}
.term-frame .term-view.term-preload{visibility:hidden!important;pointer-events:none}
.term-placeholder{display:grid;place-content:center;justify-items:center;gap:10px;height:100%;padding:24px;text-align:center}
.term-placeholder .ph-title{margin:0;font-size:20px;font-weight:600}
.term-placeholder p{margin:0;color:var(--text3)}
.term-placeholder .btn{margin-top:8px}
.term-loading{position:absolute;inset:0;z-index:2;display:grid;place-content:center;justify-items:center;gap:10px;padding:24px;background:var(--term-bg);color:var(--text2);text-align:center}
.term-loading[hidden]{display:none}
.term-loading .muted{font-size:12px}
.term-spinner{width:26px;height:26px;border:3px solid var(--line2);border-top-color:var(--signal-ink);border-radius:50%;animation:spin .8s linear infinite}
.term-keys{position:relative;display:flex;flex:none;flex-wrap:wrap;align-items:center;gap:6px;padding:8px 36px;border-top:1px solid var(--line)}
.term-keys::-webkit-scrollbar{display:none}
.term-keys button{flex:none;min-width:52px;min-height:38px;margin:0;padding:0 12px;border:1px solid var(--line2);border-radius:8px;background:transparent;font-family:var(--mono);font-size:12px}
.term-keys button:hover{background:var(--raise)}
/* 快捷栏分组：按键 | Agent CLI、指令 | 粘贴（靠右）。“指令”面板在快捷栏上方展开（app.js toggleCommands），
   宽度跟随快捷栏而不是按钮，手机上也不会超出屏幕。 */
.term-keys-sep{flex:none;width:1px;height:22px;margin:0 4px;background:var(--line2)}
.term-keys .term-agent{font-family:var(--sans);font-weight:500}
.term-keys .term-paste{margin-left:auto;font-family:var(--sans)}
.term-keys .term-cmd-toggle{display:inline-flex;align-items:center;gap:6px;font-family:var(--sans);font-weight:500}
.term-cmd-toggle svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;transition:transform .2s}
.term-cmd-toggle[aria-expanded="false"] svg{transform:rotate(180deg)}
.term-keys .term-cmd-toggle[aria-expanded="true"]{border-color:var(--signal-line);background:var(--signal-tint);color:var(--text)}
.term-cmds{position:absolute;left:36px;right:36px;bottom:calc(100% + 8px);z-index:6;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:4px 18px;max-width:680px;max-height:min(60vh,460px);overflow:auto;padding:12px;border:1px solid var(--line2);border-radius:12px;background:var(--surface-float);box-shadow:var(--shadow-float);animation:rise .18s cubic-bezier(.2,.8,.2,1)}
.term-cmd-group{display:flex;flex-direction:column;gap:2px;min-width:0}
/* 分组标题保留原始大小写，不强制转换为全大写；字体、字号、间距不变。 */
.term-cmd-group>p{margin:2px 8px 6px;font-family:var(--mono);font-size:11px;letter-spacing:.12em;color:var(--text3)}
.term-keys .term-cmd{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:10px;min-width:0;min-height:36px;padding:0 8px;border:0;border-radius:7px;font-family:var(--sans);font-size:12.5px;text-align:left}
.term-cmd code{font-family:var(--mono);font-size:12.5px;color:var(--signal-ink)}
.term-cmd span{overflow:hidden;color:var(--text2);text-overflow:ellipsis;white-space:nowrap}
.term-cmd em{font-style:normal;font-size:11px;color:var(--text3);white-space:nowrap}
.term-keys .term-cmd:hover,.term-keys .term-cmd:focus-visible{background:var(--raise)}
.term-cmds-note{grid-column:1/-1;margin:6px 8px 0;padding-top:8px;border-top:1px solid var(--line);font-size:11.5px;color:var(--text3)}
.term-cmds-note strong{font-weight:600;color:var(--text2)}
.statusline{display:flex;flex:none;flex-wrap:wrap;align-items:center;gap:6px 14px;min-height:40px;padding:8px 36px;border-top:1px solid var(--line);font-family:var(--mono);font-size:11.5px;color:var(--text3)}
.statusline strong{font-weight:500;color:var(--text2)}
.term-dot{flex:none;width:7px;height:7px;border-radius:50%;background:var(--line3)}
.term-dot.running{background:var(--ok);box-shadow:0 0 0 3px var(--ok-halo)}
.term-dot.busy{background:var(--busy)}
.term-dot.error{background:var(--danger)}
.term-note{margin-left:auto}
.term-note.flash-note{color:var(--ok-ink)}

/* ---------- file manager ---------- */
.fm{position:relative;display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden}
.fbar{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px 12px;padding:14px 36px;border-bottom:1px solid var(--line)}
.fpath{display:flex;align-items:center;gap:4px;min-width:0}
.fpath .icon-btn{width:36px;height:36px}
.crumbs{display:flex;flex-wrap:wrap;align-items:center;gap:2px;min-width:0;font-family:var(--mono);font-size:13px;color:var(--text2)}
.crumbs button{max-width:24ch;min-height:32px;margin:0;padding:0 8px;overflow:hidden;border:0;border-radius:6px;background:transparent;color:var(--text2);font-family:var(--mono);text-overflow:ellipsis;white-space:nowrap}
.crumbs button:hover{background:var(--raise);color:var(--text)}
.crumbs button[aria-current=page]{color:var(--text)}
.crumbs .sep{color:var(--line3)}
.ftools{display:flex;flex-wrap:wrap;align-items:center;gap:8px}
.fm-upload{position:relative;cursor:pointer}
.fm-upload:focus-within{outline:2px solid var(--signal-ink);outline-offset:2px}
.toggle{display:inline-flex;align-items:center;gap:8px;min-height:40px;padding:0 10px;border-radius:8px;color:var(--text2);font-size:13px;cursor:pointer}
.toggle:hover{background:var(--raise);color:var(--text)}
.toggle input,.check input{width:16px;height:16px;margin:0;accent-color:var(--check);cursor:pointer}
.table{flex:1;min-height:0;overflow:auto;padding:0 20px max(92px,calc(var(--fm-bar,0px) + 32px));overscroll-behavior:contain}
.row,.fm-row{display:grid;grid-template-columns:44px minmax(0,1fr) 110px 160px 44px;align-items:center;min-height:52px;padding:0 16px;border-bottom:1px solid var(--line);transition:background .12s}
.fm-row:hover{background:var(--row-hover)}
.fm-row.selected{background:var(--signal-tint)}
.headrow{position:sticky;top:0;z-index:1;min-height:40px;background:var(--bg);font-family:var(--mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--text3)}
.check{display:grid;place-items:center;width:44px;height:44px;margin-left:-12px;cursor:pointer}
.fm-name{display:flex;align-items:center;gap:12px;min-width:0;min-height:44px;margin:0;padding:0 4px;border:0;border-radius:8px;background:transparent;color:var(--text);font-weight:500;text-align:left}
.fm-name:hover .label{color:var(--signal-ink)}
.fm-name .text{display:flex;flex-direction:column;min-width:0}
.fm-name .label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fm-meta{display:none;font-family:var(--mono);font-size:11px;font-weight:400;color:var(--text3)}
.fm-icon{flex:none;width:20px;height:20px;color:var(--text3)}
.fm-icon.dir{color:var(--folder)}
.fm-size,.fm-time{font-family:var(--mono);font-size:12px;color:var(--text2);white-space:nowrap}
.fm-size{padding-right:24px;text-align:right}
.headrow .fm-size,.headrow .fm-time{font-size:11px;color:var(--text3)}
.fm-size[data-state=pending],.fm-size[data-state=skipped]{color:var(--text3)}
.fm-size[data-state=partial]{color:var(--text)}
.fm-size[data-state=denied],.fm-size[data-state=error]{color:var(--danger-ink)}
/* 拖动移动（app.js FileManager.moveTarget）：可放下的文件夹行、路径栏按钮和“上一级”按钮显示强调色边框，
   不可放下（目录自身或其子目录）显示红色；拖动期间路径栏中的上级目录显示细边框，提示可作为落点。 */
.fm-row[draggable=true]{-webkit-user-drag:element}
.fm-row.fm-drop-ok,.crumbs button.fm-drop-ok,.icon-btn.fm-drop-ok{background:var(--signal-tint);box-shadow:inset 0 0 0 1.5px var(--signal-line)}
.fm-row.fm-drop-no,.crumbs button.fm-drop-no,.icon-btn.fm-drop-no{background:var(--danger-tint);box-shadow:inset 0 0 0 1.5px var(--danger-line);cursor:no-drop}
.fm.fm-moving .crumbs button:not([aria-current]){box-shadow:inset 0 0 0 1px var(--line3)}
.fm-drag-ghost{position:fixed;top:-100px;left:-100px;padding:6px 12px;border-radius:8px;background:var(--signal);color:var(--on-signal);font-size:13px;font-weight:600;white-space:nowrap;pointer-events:none}
.fm-more{display:grid;place-items:center;width:36px;height:36px;margin:0;padding:0;border:0;border-radius:6px;background:transparent;color:var(--text3)}
.fm-more:hover{background:var(--raise);color:var(--text)}
.fm-more svg{width:18px;height:18px}
.fm-empty{display:grid;place-items:center;min-height:180px;padding:40px 20px;color:var(--text3);text-align:center}
/* 拖放上传的“黑洞”落点（app.js FileManager.setupDrop / absorb）：覆盖文件管理区域，不改变布局、不接收指针事件。
   .open 有效内容进入、入口张开；.invalid 不支持的内容；.absorbing 松开后约 0.5 秒的吸入（卡片由 JS 动画）。
   减少动态效果时上面的全局规则关闭旋转与过渡，只保留静态落点；JS 同时跳过吸入动画。 */
.fm-drop{position:absolute;inset:8px;z-index:8;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;padding:16px;border:1.5px dashed var(--line3);border-radius:14px;background:var(--bg);background:color-mix(in srgb,var(--bg) 92%,transparent);text-align:center;pointer-events:none;overflow:hidden;container-type:size;opacity:0;transition:opacity .16s ease,border-color .16s ease}
.fm-drop[hidden]{display:none}
.fm-drop.open,.fm-drop.invalid{opacity:1}
.fm-drop.open{border-color:var(--signal-line)}
.fm-drop.invalid{border-color:var(--danger-line)}
.fm-drop.collapsing{opacity:0;transition:opacity .26s ease}
/* 黑洞落点：宽 16:10，按落点区域的宽高取最大可用尺寸，文字始终留在区域内，不产生滚动。
   .live 时由画布（WebGL 或 Canvas 2D）绘制，静态层隐藏；静态层用于减少动态效果、无法绘制和“不支持”状态。 */
.fm-hole{position:relative;flex:none;width:min(420px,88%);width:min(420px,88cqw,(100cqh - 100px) * 1.6);aspect-ratio:16/10;transform:scale(.55);opacity:.5;transition:transform .45s cubic-bezier(.2,.8,.2,1),opacity .3s ease}
.fm-drop.open .fm-hole{transform:scale(1);opacity:1}
.fm-drop.invalid .fm-hole{transform:scale(.62);opacity:.4;filter:grayscale(1)}
.fm-hole::before{content:"";position:absolute;inset:0 12%;border-radius:50%;background:radial-gradient(closest-side,rgba(4,3,8,.94) 40%,rgba(4,3,8,.7) 70%,transparent)}
.fm-hole>span{position:absolute;left:50%;top:50%;border-radius:50%;transform:translate(-50%,-50%)}
.fm-hole-lens{width:27%;aspect-ratio:1;background:radial-gradient(closest-side,transparent 60%,#FFE2AA 66%,rgba(255,150,40,.75) 78%,transparent);-webkit-mask:linear-gradient(#000 50%,rgba(0,0,0,.4) 50%);mask:linear-gradient(#000 50%,rgba(0,0,0,.4) 50%)}
.fm-hole-disk{width:75%;height:20%;background:radial-gradient(closest-side,transparent 32%,#FFF1D2 37%,#FFB347 47%,#E0561B 66%,rgba(140,30,8,.55) 84%,transparent);-webkit-mask:linear-gradient(90deg,#000,rgba(0,0,0,.5));mask:linear-gradient(90deg,#000,rgba(0,0,0,.5))}
.fm-hole-disk.front{clip-path:inset(50% 0 0 0)}
.fm-hole-core{width:16.25%;aspect-ratio:1;background:#000;box-shadow:0 0 0 1.5px rgba(255,220,160,.9),0 0 16px 3px rgba(255,140,30,.5)}
.fm-hole.live::before,.fm-hole.live>span{visibility:hidden}
.fm-hole-canvas{position:absolute;inset:0;display:block;width:100%;height:100%;pointer-events:none}
.fm-drop.absorbing .fm-hole:not(.live) .fm-hole-core{animation:fm-hole-swallow .6s cubic-bezier(.3,0,.2,1)}
.fm-drop-title,.fm-drop-hint{position:relative;z-index:2}
.fm-drop-title{margin:0;font-size:15px;font-weight:600;color:var(--text)}
.fm-drop-hint{max-width:min(460px,100%);margin:0;overflow-wrap:anywhere;font-size:12px;color:var(--text3)}
.fm-drop.invalid .fm-drop-title{color:var(--danger-ink)}
.fm-drop-chip{position:absolute;left:0;top:0;z-index:1;display:inline-flex;align-items:center;gap:6px;max-width:150px;padding:4px 8px;border:1px solid var(--signal-line);border-radius:7px;background:var(--surface-float);box-shadow:var(--shadow-float),0 0 14px rgba(255,160,50,.35);font-size:11.5px;line-height:1.3;white-space:nowrap;transform-origin:0 0;will-change:transform,opacity}
.fm-drop-chip>span{overflow:hidden;text-overflow:ellipsis}
.fm-drop-chip svg{flex:none;width:14px;height:14px;color:var(--text3)}.fm-drop-chip svg.dir{color:var(--folder)}
@keyframes fm-hole-swallow{0%{transform:translate(-50%,-50%) scale(1)}40%{transform:translate(-50%,-50%) scale(1.16)}100%{transform:translate(-50%,-50%) scale(.9)}}
.fm-status{position:absolute;left:36px;bottom:12px;z-index:2;max-width:calc(100% - 72px);margin:0;padding:6px 12px;border-radius:8px;background:var(--surface-float);box-shadow:var(--shadow-float);font-size:12.5px;color:var(--text2);pointer-events:none}
.fm-status:empty{display:none}
.fm-status.error{color:var(--danger-ink)}.fm-status.ok{color:var(--ok-ink)}
.fm-transfers{flex:none;max-height:30%;overflow:auto;margin:0 20px 14px;padding:4px 12px;border:1px solid var(--line);border-radius:10px;background:var(--panel)}
.fm-transfer{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:4px 10px;padding:8px 0;font-size:12px}
.fm-transfer+.fm-transfer{border-top:1px solid var(--line)}
.fm-transfer .t-name{overflow:hidden;font-weight:600;text-overflow:ellipsis;white-space:nowrap}
.fm-transfer .t-state{color:var(--text3)}
.fm-transfer.failed .t-state{color:var(--danger-ink)}.fm-transfer.done .t-state{color:var(--ok-ink)}
.fm-transfer button{min-height:30px;padding:0 10px;font-size:12px}
/* 传输区标题栏（统计 + 暂停队列 / 全部取消 / 清除已结束），滚动时固定在顶部。 */
.fm-transfers-head{position:sticky;top:-4px;z-index:1;display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:0 -12px;padding:8px 12px;border-bottom:1px solid var(--line);background:var(--panel)}
.fm-transfers-head .t-summary{font-size:12px;color:var(--text2);white-space:nowrap}
/* 收起 / 展开：统计文字连同箭头是一个按钮；收起后只保留标题栏，显示当前任务与底边细进度线。 */
.fm-transfers-head .t-toggle{display:inline-flex;align-items:center;gap:7px;min-height:30px;margin:0 auto 0 -6px;padding:0 8px 0 6px;border:0;border-radius:7px;background:transparent;color:var(--text2);font-size:12px;transition:background .15s,color .15s}
.fm-transfers-head .t-toggle:hover{background:var(--raise);border-color:transparent;color:var(--text)}
.t-chevron{width:16px;height:16px;flex:none;color:var(--text3);transition:transform .28s cubic-bezier(.2,.8,.2,1),color .15s}
.t-toggle:hover .t-chevron{color:var(--text)}
.fm-transfers.collapsed .t-chevron{transform:rotate(-90deg)}
.t-now{display:none;flex:1 1 auto;min-width:0;overflow:hidden;font-family:var(--mono);font-size:11.5px;color:var(--text3);text-overflow:ellipsis;white-space:nowrap;font-feature-settings:"tnum" 1}
.t-peek{position:absolute;left:0;bottom:-1px;width:0;height:2px;border-radius:0 2px 2px 0;background:var(--signal-ink);opacity:0;transition:width .25s linear,opacity .2s}
.fm-transfers.collapsed{overflow:hidden;padding-top:0;padding-bottom:0}
.fm-transfers.collapsed:not(.animating) .fm-transfer-list{display:none}
.fm-transfers.collapsed .fm-transfers-head{border-bottom-color:transparent}
.fm-transfers.collapsed .transfer-follow{display:none}
.fm-transfers.collapsed.peeking .t-now{display:block}
.fm-transfers.collapsed.peeking .t-toggle{margin-right:6px}
.fm-transfers.collapsed.peeking .t-peek{opacity:1}
.fm-transfers.animating{overflow:hidden;transition:height .28s cubic-bezier(.2,.8,.2,1)}
.fm-transfers-head button{min-height:30px;padding:0 10px;font-size:12px}
.fm-transfers-head button.danger{border-color:var(--danger-line);color:var(--danger-ink)}
.fm-transfers-head button.danger:hover{border-color:var(--danger);background:var(--danger-tint)}
.transfer-follow{display:inline-flex;align-items:center;gap:6px;min-height:30px;padding:0 6px;color:var(--text3);font-size:12px;white-space:nowrap;cursor:pointer}
.transfer-follow input{width:15px;height:15px;margin:0;accent-color:var(--signal)}
.fm-transfer.cancelled .t-state{color:var(--text3)}.fm-transfer.cancelled .meter span{background:var(--line3)}
/* 有传输任务时状态提示排在传输区下方，避免盖住传输进度。 */
.fm.has-transfers .fm-status{position:static;flex:none;align-self:flex-start;max-width:calc(100% - 40px);margin:0 20px 10px;box-shadow:none}
.meter{grid-column:1/-1;height:4px;border-radius:2px;background:var(--track);overflow:hidden}
.meter span{display:block;height:100%;border-radius:inherit;background:var(--signal-ink);transition:width .2s}
.selbar{position:absolute;left:50%;bottom:calc(16px + var(--fm-dock,0px));z-index:3;display:flex;align-items:center;gap:4px;max-width:calc(100% - 40px);overflow:hidden;padding:6px 6px 6px 18px;border:1px solid var(--line2);border-radius:12px;background:var(--surface-float);box-shadow:var(--shadow-float);transform:translateX(-50%);animation:fade .2s ease}
.selbar-count{margin-right:10px;font-size:13px;color:var(--text2);white-space:nowrap}
.selbar .sep{width:1px;height:24px;margin:0 4px;background:var(--line2)}
.selbar .icon-btn{width:40px;height:40px}

/* ---------- usage panel ---------- */
/* 展开的“账户使用情况”与 <main> 占同一个网格格子。内容是一张卡片（.usage-board）里的同一个网格，四格错落排布：
   左侧圆环跨两行，三项用量（全称、百分比、已用 / 总量）只在圆环上呈现；补充信息（最高占用 / 带宽上限 / 下次归零）
   在圆环下方；右侧上面是空间分析（标题、分类汇总、操作），下面是占右下最大一块的矩形树图，向左伸到补充信息旁。
   圆环格比空间分析格高、补充信息格与树图并排，格子边线彼此错开，没有横贯全宽的上下两段，也没有承载全部指标的侧栏。
   桌面整体不滚动；只有手机宽度（≤760px）在面板内部滚动。 */
.ws>.main{grid-area:1/2}
.usage-panel{grid-area:1/2;z-index:6;display:flex;flex-direction:column;min-width:0;min-height:0;overflow:hidden;background:var(--bg);visibility:hidden;opacity:0;transform:translateY(8px);transition:opacity .2s,transform .26s cubic-bezier(.2,.8,.2,1),visibility 0s linear .26s}
/* 打开时立即可见（可以马上把焦点移进来），关闭时等淡出结束再隐藏。 */
.usage-panel.open{visibility:visible;opacity:1;transform:none;transition:opacity .2s,transform .26s cubic-bezier(.2,.8,.2,1),visibility 0s}
.usage-panel-head{flex:none;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:18px 28px 12px 32px}
.usage-panel-head h2{margin:0;font-size:22px;font-weight:600;letter-spacing:-.01em}
/* 面板主体是尺寸容器：圆环列的宽度随可用高度变化（矮窗口窄、高窗口宽），使圆环格接近方形而不留大片空白。 */
.usage-panel-body{flex:1;min-height:0;display:flex;flex-direction:column;padding:2px 32px 22px;overflow:hidden;container-type:size}
/* Agent 额度面板：沿用 .usage-panel 外壳（与账户使用情况同一格子、同一开合方式），但让出顶部标题栏：上边距 --quota-top
   是标题栏的实际高度（app.js 测量），服务器时间、日期、地点与时区始终可见。内容是一张卡片里的两格（每个 Agent 一格，
   桌面并排、手机上下排列）：额度窗口（大号已使用百分比、同向进度条、剩余、重置倒计时与绝对时间）、状态说明和读取时间。
   标题栏右侧是“刷新额度”及其进度 / 结果。桌面不滚动，只有格子内容放不下时在格内滚动。 */
.quota-panel{margin-top:var(--quota-top,0px)}
.quota-panel .usage-panel-head h2{display:flex;align-items:center;gap:10px;min-width:0;white-space:nowrap}
.quota-panel .usage-panel-head h2 svg{flex:none;width:22px;height:22px;color:var(--signal-ink)}
.quota-actions{display:flex;align-items:center;justify-content:flex-end;gap:10px;min-width:0}
.quota-status{min-width:0;overflow:hidden;color:var(--text3);font-size:12.5px;text-overflow:ellipsis;white-space:nowrap}
.quota-status[data-tone=ok]{color:var(--ok-ink)}
.quota-status[data-tone=busy],.quota-status[data-tone=partial]{color:var(--signal-ink)}
.quota-status[data-tone=error]{color:var(--danger-ink)}
.quota-actions .btn{flex:none;min-height:36px;padding:0 14px}
.quota-auto{flex:none;display:inline-flex;align-items:center;gap:7px;min-height:36px;padding:0 10px;border:1px solid var(--line2);border-radius:10px;background:transparent;color:var(--text2);font:inherit;font-size:13px;white-space:nowrap;cursor:pointer}
.quota-auto:hover{color:var(--text)}
.quota-auto:focus-visible{outline:2px solid var(--signal);outline-offset:2px}
.quota-auto:disabled{opacity:.6;cursor:default}
.quota-switch{position:relative;width:28px;height:16px;border-radius:999px;background:var(--line2);transition:background .2s}
.quota-switch::after{content:"";position:absolute;top:2px;left:2px;width:12px;height:12px;border-radius:50%;background:var(--text2);transition:transform .2s,background .2s}
.quota-auto[aria-checked=true]{color:var(--text)}
.quota-auto[aria-checked=true] .quota-switch{background:var(--signal)}
.quota-auto[aria-checked=true] .quota-switch::after{transform:translateX(12px);background:var(--on-signal)}
@media (prefers-reduced-motion:reduce){.quota-switch,.quota-switch::after{transition:none}}
.btn.loading::before{content:"";flex:none;width:11px;height:11px;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:spin .8s linear infinite}
.quota-board{--gap:10px;flex:1 1 auto;min-width:0;min-height:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:minmax(0,1fr) auto;gap:var(--gap);padding:var(--gap);border:1px solid var(--line);border-radius:16px;background:var(--panel)}
.quota-card{min-width:0;min-height:0;display:flex;flex-direction:column;gap:14px;padding:16px 18px;overflow:auto;overscroll-behavior:contain;border-radius:11px;background:color-mix(in srgb,var(--raise) 42%,var(--panel))}
/* 尚未读取：说明放在卡片中央。 */
.quota-card[data-state=empty] .quota-msg{margin:auto;max-width:28em;text-align:center;color:var(--text3)}
.quota-card-head{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px;min-width:0}
.quota-card-head h3{display:flex;align-items:center;gap:9px;margin:0;font-size:17px;font-weight:600;white-space:nowrap}
.quota-card-head h3::before{content:"";flex:none;width:9px;height:9px;border-radius:50%;background:var(--a-claude)}
[data-quota-card=codex] .quota-card-head h3::before{background:var(--a-codex)}
.quota-plan{padding:1px 8px;border:1px solid var(--signal-line);border-radius:999px;background:var(--signal-tint);color:var(--signal-ink);font-size:11.5px}
.quota-state{margin-left:auto;color:var(--text3);font-size:12.5px;white-space:nowrap}
.quota-card[data-state=ok] .quota-state{color:var(--ok-ink)}
.quota-card[data-state=exhausted] .quota-state,.quota-card[data-state=unavailable] .quota-state{color:var(--danger-ink)}
.quota-card[data-state=loading] .quota-state{color:var(--signal-ink)}
/* 每个额度窗口是一块嵌在卡片里的格子；桌面上各格平分卡片高度（有上限），数字随卡片大小缩放，不留大片空白。 */
.quota-windows{display:flex;flex-direction:column;gap:10px;min-height:0}
.quota-window{display:grid;grid-template-columns:minmax(0,1fr) auto;align-content:center;align-items:baseline;gap:8px 12px;padding:14px 16px;border-radius:10px;background:var(--panel);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--line) 70%,transparent)}
.quota-window-label{min-width:0;overflow:hidden;color:var(--text2);font-size:13.5px;text-overflow:ellipsis;white-space:nowrap}
.quota-used{grid-column:2;grid-row:1;display:flex;align-items:baseline;gap:6px;color:var(--text2);font-size:12px;white-space:nowrap}
.quota-used b{font:600 26px/1 var(--mono);letter-spacing:-.03em;color:var(--text)}
.quota-bar{grid-column:1/-1;height:10px;overflow:hidden;border-radius:5px;background:var(--track)}
.quota-bar i{display:block;height:100%;border-radius:inherit;background:var(--a-claude);transition:width .5s cubic-bezier(.2,.8,.2,1)}
[data-quota-card=codex] .quota-bar i{background:var(--a-codex)}
.quota-window.low .quota-bar i{background:var(--danger)}
.quota-window.low .quota-used b{color:var(--danger-ink)}
.quota-left{align-self:start;color:var(--text3);font-size:12px;white-space:nowrap}
.quota-reset{display:flex;flex-wrap:wrap;justify-content:flex-end;align-items:baseline;gap:2px 8px;min-width:0;font-size:12px;color:var(--text3);text-align:right}
.quota-countdown{color:var(--text2);font-weight:500;white-space:nowrap}
.quota-reset[data-due=true] .quota-countdown{color:var(--signal-ink)}
.quota-reset-at{white-space:nowrap}
.quota-msg{margin:0;color:var(--text2);font-size:13px;line-height:1.55}
.quota-msg.fail{color:var(--danger-ink)}
.quota-time{margin:auto 0 0;font-family:var(--mono);font-size:11.5px;color:var(--text3)}
@media (min-width:761px){.quota-card{container-type:size}.quota-windows{flex:1 1 auto}.quota-window{flex:1 1 0;padding:clamp(10px,2.6cqh,28px) clamp(14px,3cqw,30px)}
  .quota-used b{font-size:clamp(22px,8cqh,64px)}.quota-used{font-size:clamp(12px,1.8cqh,15px)}.quota-window-label{font-size:clamp(13px,2.2cqh,17px)}
  .quota-bar{height:clamp(8px,1.8cqh,16px);border-radius:8px}.quota-left,.quota-reset{font-size:clamp(12px,1.7cqh,14px)}}
.quota-note{grid-column:1/-1;margin:0;padding:0 6px 2px;font-size:12px;line-height:1.55;color:var(--text3)}
.usage-board{--dial-min:232px;--side:clamp(262px,min(30%,50cqh),360px);--gap:10px;--tile-pad:14px;flex:1 1 auto;min-width:0;min-height:0;display:grid;
  grid-template-columns:var(--side) minmax(0,1fr);grid-template-rows:auto minmax(0,1fr) auto;
  grid-template-areas:"dial space" "dial map" "meta map";
  gap:var(--gap);padding:var(--gap);border:1px solid var(--line);border-radius:16px;background:var(--panel)}
.board-tile{min-width:0;min-height:0;margin:0;border-radius:11px;background:color-mix(in srgb,var(--raise) 42%,var(--panel))}
/* 圆环模块随所在格子缩放（取宽高中较小的一边）。 */
.dial-tile{grid-area:dial;display:grid;place-items:center;min-height:calc(var(--dial-min) + 2 * var(--tile-pad));padding:var(--tile-pad);container-type:size}
.dial{position:relative;width:min(100cqw,100cqh,340px);aspect-ratio:1;container-type:inline-size}
.dial svg{position:absolute;inset:0;display:block;width:100%;height:100%;overflow:visible}
/* 圆环是压进卡片的凹槽（新拟态，光从左上方来）：槽底比卡片深一档；#dial-groove 在槽壁上画出两层——
   左上内壁的背光暗边（一层宽而柔的阴影加一条细的接触线）与右下内壁的受光亮边（较窄、很淡），盖在彩色进度上，使进度像嵌在槽底；
   进度比槽窄，端点经 #dial-fill 只做轻微圆角（不是胶囊头）。槽底、暗边、亮边按深浅主题分别取值（--groove*）。 */
.dial .ring-track{stroke:var(--groove);stroke-width:7.6}
.dial .ring-fill{stroke-width:5.2;stroke-linecap:butt;filter:url(#dial-fill)}
.dial .ring-wall{fill:none;stroke:#000;stroke-width:7.6;filter:url(#dial-groove);pointer-events:none}
.dial .ring-seg.na .ring-track{stroke:var(--groove);stroke-dasharray:none;opacity:.6}
.dial-shade-color{flood-color:var(--groove-shade)}.dial-edge-color{flood-color:var(--groove-edge)}.dial-lit-color{flood-color:var(--groove-lit)}
/* 弧形文字（路径与方向见网关 usage_dial）：外层全称与百分比，内层已用 / 总量。圆环不小于 --dial-min，字号随圆环缩放。 */
.dial-text-path{fill:none;stroke:none}
.dial-arc-name,.dial-arc-value{text-anchor:middle;dominant-baseline:central;pointer-events:none}
.dial-arc-name{fill:var(--c);font-size:4.6px;font-weight:600;letter-spacing:.02em}
.dial-arc-pct{font-family:var(--mono);font-weight:500;letter-spacing:-.02em}
.dial-arc-value{fill:var(--text2);font-size:3.9px;font-variant-numeric:tabular-nums}
.ring-seg.na .dial-arc-name{fill:var(--text3)}.ring-seg.na .dial-arc-value{fill:var(--text3)}
.dial-peak{position:absolute;left:50%;top:51%;transform:translate(-50%,-50%);white-space:nowrap;line-height:1;font:500 13cqw/1 var(--mono);letter-spacing:-.03em;color:var(--text)}
/* 补充信息：名称在左、数值在右，一项一行；分析过空间后，分类汇总（总量、分类条、逐项占用）接在下面，
   与圆环的用户空间一段和右侧树图相邻。 */
.usage-meta{grid-area:meta;display:flex;flex-direction:column;gap:8px;padding:8px 16px 10px}
.usage-meta dl{margin:0}
.usage-meta dl div{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:0 12px;min-width:0;padding:5px 0}
.usage-meta dl div+div{border-top:1px solid color-mix(in srgb,var(--line) 70%,transparent)}
.usage-meta dt{font-size:12px;color:var(--text3)}
.usage-meta dd{margin:0;font-family:var(--mono);font-size:13px;color:var(--text2);overflow-wrap:anywhere}
.space-summary{min-width:0;padding-top:8px;border-top:1px solid color-mix(in srgb,var(--line) 70%,transparent)}
.space-summary .space-legend{display:grid;gap:0}
.space-summary .space-label{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis}
.space-summary .space-percent{min-width:3.6em;text-align:right}
/* 空间分析：标题与操作在树图上方一格；树图格占满其余高度。 */
.space-breakdown{grid-area:space;display:flex;flex-wrap:wrap;align-items:center;gap:8px 20px;padding:10px 14px}
.space-breakdown h3{flex:none;margin:0;font-size:15px}
.space-actions{flex:none;display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-left:auto}.space-actions .btn{min-height:34px;padding:0 12px}
.space-map{grid-area:map;display:flex;flex-direction:column;gap:8px;padding:10px 14px;overflow:hidden}
.space-loading{flex:none;margin:0;font-size:12px;color:var(--text3)}.space-loading.error{color:var(--danger-ink)}
/* 尚未分析（或没有结果）时，提示占据树图的位置。 */
.space-map:has(>.treemap[hidden])>.space-loading{flex:1 1 auto;display:grid;place-items:center;min-height:64px;padding:12px 20px;border:1px dashed var(--line2);border-radius:10px;font-size:13px;text-align:center}
.space-total{margin:0 0 6px;font-size:12px;color:var(--text3)}
.space-stack{display:flex;height:8px;margin-bottom:5px;overflow:hidden;border-radius:4px;background:var(--track)}.space-stack span{min-width:0}
.space-legend{display:flex;flex-wrap:wrap;gap:0 14px}
.space-row{display:flex;align-items:center;gap:5px;min-height:18px;font-size:11.5px;white-space:nowrap}.space-dot{flex:none;width:8px;height:8px;border-radius:2px;background:var(--space-color)}.space-label{color:var(--text2)}.space-value,.space-percent{font-family:var(--mono);color:var(--text3)}
/* 矩形树图：面积与字节数成正比（位置用百分比，窗口尺寸变化时按缓存结果重新排布，不重新扫描）。
   目录块内嵌一层子项；小块不显示文字，名称、大小和占比在悬停提示与下方详情行（键盘焦点同样显示）。 */
.tm-crumbs{display:flex;flex-wrap:wrap;align-items:center;gap:2px 4px;min-width:0;font-size:12px;color:var(--text3)}
.tm-crumbs button{max-width:16em;overflow:hidden;padding:2px 6px;border:0;border-radius:5px;background:transparent;color:var(--text2);text-overflow:ellipsis;white-space:nowrap}.tm-crumbs button:hover{background:var(--raise);color:var(--text)}
.tm-crumbs [aria-current]{color:var(--text);font-weight:600}
.treemap{position:relative;flex:1 1 auto;min-height:90px;overflow:hidden;border:1px solid var(--line);border-radius:8px;background:var(--panel)}
.tm-tile{position:absolute;display:block;min-width:0;margin:0;padding:0;overflow:hidden;border:0;border-radius:0;background:color-mix(in srgb,var(--tile) 26%,var(--panel));box-shadow:inset 0 0 0 1px var(--panel);color:var(--text);font-size:11px;line-height:1.25;text-align:left}
.tm-tile.tm-leaf{background:color-mix(in srgb,var(--tile) 40%,var(--panel))}
.tm-tile.tm-rest{background:repeating-linear-gradient(135deg,color-mix(in srgb,var(--tile) 22%,var(--panel)) 0 6px,color-mix(in srgb,var(--tile) 32%,var(--panel)) 6px 12px)}
button.tm-tile{cursor:default}button.tm-tile.tm-open{cursor:zoom-in}
.tm-tile:hover{background:color-mix(in srgb,var(--tile) 48%,var(--panel))}
button.tm-tile:focus-visible{z-index:2;outline:2px solid var(--signal-ink);outline-offset:-2px}
.tm-label{position:absolute;top:3px;left:5px;right:5px;display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;pointer-events:none}
.tm-label b{font-weight:600}.tm-label span{margin-left:6px;font-family:var(--mono);color:var(--text2)}
.tm-tile.tm-tiny .tm-label{display:none}
.tm-inner{position:absolute;inset:20px 2px 2px;pointer-events:none}.tm-inner .tm-tile{pointer-events:auto}
.tm-tile.tm-tiny>.tm-inner,.tm-tile.tm-short>.tm-inner{inset:1px}
.tm-detail{min-height:1.5em;margin:0;overflow:hidden;font-size:12px;color:var(--text2);text-overflow:ellipsis;white-space:nowrap}
.cleanup-options{display:grid;gap:8px;margin-top:8px}.cleanup-options label{display:flex;align-items:flex-start;gap:10px;padding:10px;border:1px solid var(--line);border-radius:8px;cursor:pointer}.cleanup-options label:hover{border-color:var(--line3);background:var(--raise)}.cleanup-options label.disabled{opacity:.45;cursor:not-allowed}.cleanup-options input{flex:none;width:16px;height:16px;margin:2px 0 0;accent-color:var(--signal)}.cleanup-options span{display:grid;gap:3px}.cleanup-options b{font-size:13px}.cleanup-options small{color:var(--text3);font-size:11px;line-height:1.4}
.dlg-body .cleanup-options label{display:flex;margin:0}.dlg-body h3.cleanup-group{margin:14px 0 0;color:var(--text);font-size:13px;font-weight:600;line-height:1.4}.dlg-body h3.cleanup-group:first-child{margin-top:0}.credential-options label.danger input{accent-color:var(--danger)}.credential-options label.danger:has(input:checked){border-color:var(--danger-line);background:var(--danger-tint)}.dlg-body ul.credential-effects li{line-height:1.5}
@media (max-height:720px){.cleanup-options{gap:6px}.dlg-body .cleanup-options label{padding:7px 10px}.cleanup-options small{line-height:1.3}}

/* ---------- dialogs & menus ---------- */
.dlg{width:min(calc(100vw - 32px),460px);max-height:min(86dvh,640px);padding:0;border:1px solid var(--line2);border-radius:14px;background:var(--dialog-bg);box-shadow:var(--shadow-dialog);color:var(--text)}
.dlg[open]{display:flex;animation:pop .22s cubic-bezier(.2,.8,.2,1)}
.dlg::backdrop{background:var(--overlay);backdrop-filter:blur(2px)}
.dlg-form{display:flex;flex:1;flex-direction:column;min-height:0;max-height:inherit;padding:24px}
.dlg-title{flex:none;margin:0 0 14px;font-size:18px;font-weight:600}
.dlg-body{flex:1;min-height:0;overflow:auto;color:var(--text2);font-size:14px;line-height:1.6}
.dlg-body p{margin:0 0 10px}
.dlg-body ul{margin:0 0 12px;padding:0;list-style:none;border:1px solid var(--line);border-radius:8px;word-break:break-all}
.dlg-body li{padding:9px 12px;font-size:13px;color:var(--text)}
.dlg-body li+li{border-top:1px solid var(--line)}
.dlg-body label{display:block;margin:6px 0}
.dlg-warning{margin:10px 0;padding:10px 12px;border-radius:8px;background:var(--danger-tint2);color:var(--danger-warn);font-weight:600}
.dlg-actions{display:flex;flex:none;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:18px}
.dlg-menu{display:grid;gap:6px}
.dlg-menu button{justify-content:flex-start;width:100%}
.picker{display:flex;flex-direction:column;gap:8px}
.picker-path{padding:8px 10px;border-radius:8px;background:var(--raise);font-family:var(--mono);font-size:12.5px;word-break:break-all}
.picker-list{max-height:min(40dvh,320px);overflow:auto;border:1px solid var(--line);border-radius:10px}
.picker-list button{justify-content:flex-start;width:100%;min-height:44px;border:0;border-radius:0}
.picker-list button+button{border-top:1px solid var(--line)}
.picker-list button:hover{background:var(--row-hover)}
.theme-btn .ico{display:none}
:root[data-theme-mode="system"] .theme-btn .ico-system,:root[data-theme-mode="light"] .theme-btn .ico-light,:root[data-theme-mode="dark"] .theme-btn .ico-dark{display:block}
.theme-menu{position:fixed;z-index:60;width:236px;padding:6px;border:1px solid var(--line2);border-radius:12px;background:var(--surface-float);box-shadow:var(--shadow-float);animation:pop .16s cubic-bezier(.2,.8,.2,1)}
.theme-menu p{margin:6px 10px 8px;font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--text3)}
.theme-opt{display:grid;grid-template-columns:30px 1fr 16px;align-items:center;gap:8px;width:100%;min-height:48px;margin:0;padding:6px 10px;border:0;border-radius:8px;background:transparent;color:var(--text);text-align:left}
.theme-opt:hover{background:var(--raise)}
.theme-opt svg{width:18px;height:18px;color:var(--text2)}
.theme-opt b{display:block;font-size:13px;font-weight:500}
.theme-opt small{display:block;font-size:11.5px;color:var(--text3)}
.theme-opt .tick{visibility:hidden;color:var(--signal-ink)}
.theme-opt[aria-checked=true] .tick{visibility:visible}
.theme-opt[aria-checked=true] svg:first-child{color:var(--signal-ink)}

/* ---------- welcome animation ---------- */
/* 欢迎动画（登录后约 2.8 秒，同一网页登录会话只播放一次），不随主题变化（全屏黑底）。 */
.intro-splash{position:fixed;inset:0;z-index:10000;visibility:hidden;overflow:hidden;background:#000;isolation:isolate;cursor:default;opacity:1;transition:opacity .8s ease,filter .8s cubic-bezier(.33,0,.2,1),transform .8s ease}.intro-splash.intro-active{visibility:visible}.intro-splash.intro-exit{opacity:0;filter:blur(28px) saturate(1.8) contrast(1.2);transform:scale(1.055);pointer-events:none}
.intro-stage{position:absolute;inset:0;overflow:hidden;background:#000;animation:intro-stage-in 2s cubic-bezier(.2,.72,.2,1) both}.intro-art{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center;filter:saturate(1.08) contrast(1.045) brightness(.88);transform:scale(1.035);animation:intro-cinematic-push 2.8s cubic-bezier(.18,.72,.28,1) both}.intro-stage:after{content:"";position:absolute;inset:-18%;background:radial-gradient(ellipse at 50% 52%,#b658ff2c 0,#0a73ff16 24%,transparent 53%);mix-blend-mode:screen;animation:intro-pulse 1.25s ease-in-out infinite alternate}.intro-light-sweep{position:absolute;inset:-35%;background:linear-gradient(110deg,transparent 39%,#bce8ff12 47%,#fff5 50%,#a564ff17 53%,transparent 61%);mix-blend-mode:screen;transform:translateX(-55%);animation:intro-sweep 2.4s .18s ease-in-out both}.intro-vignette{position:absolute;inset:0;box-shadow:inset 0 0 13vw 5vw #000,inset 0 0 4vw #020518;background:linear-gradient(180deg,#0007 0,transparent 18%,transparent 78%,#0009 100%)}.intro-grain{position:absolute;inset:-50%;opacity:.09;background-image:repeating-radial-gradient(circle at 37% 43%,#fff 0 .5px,transparent .7px 3px);background-size:7px 9px;animation:intro-grain .23s steps(2) infinite}.intro-particles{position:absolute;inset:0;width:100%;height:100%;mix-blend-mode:screen;pointer-events:none}.intro-loading-mark{position:absolute;left:50%;bottom:max(3.3vh,env(safe-area-inset-bottom));transform:translateX(-50%);margin:0;font:500 9px/1 ui-monospace,SFMono-Regular,Consolas,monospace;letter-spacing:.42em;color:#b8c7ff88;animation:intro-mark 2.1s ease both}
@keyframes intro-stage-in{0%{opacity:0;filter:blur(20px) brightness(.4)}28%{opacity:1;filter:blur(0) brightness(1)}100%{opacity:1}}@keyframes intro-cinematic-push{0%{transform:scale(1.08)}100%{transform:scale(1.025)}}@keyframes intro-pulse{to{opacity:.54;transform:scale(1.06)}}@keyframes intro-sweep{0%{transform:translateX(-60%);opacity:0}24%{opacity:1}100%{transform:translateX(58%);opacity:0}}@keyframes intro-grain{0%{transform:translate(1%,-1%)}50%{transform:translate(-1%,1%)}100%{transform:translate(.5%,.5%)}}@keyframes intro-mark{0%{opacity:0}25%,78%{opacity:.8}100%{opacity:0}}
@media(max-aspect-ratio:4/5){.intro-vignette{box-shadow:inset 0 0 22vw 8vw #000}}@media(prefers-reduced-motion:reduce){.intro-stage,.intro-art,.intro-light-sweep,.intro-grain,.intro-loading-mark{animation:none!important}.intro-splash{transition:opacity .25s ease!important}}

/* ---------- responsive ---------- */
@media (max-width:1100px){
  .launch{grid-template-columns:1fr;align-content:start}.launch-left{border-right:0;border-bottom:1px solid var(--line)}
  .row,.fm-row{grid-template-columns:44px minmax(0,1fr) 96px 44px}.fm-time{display:none}
}
/* 登录页只在真正接近平板/手机宽度时改为上下布局。原来的 1100px 断点会让普通桌面窗口
   仅缩窄几十像素就整页跳变；900px 以下再切换，宽屏窗口的结构保持稳定。 */
@media (max-width:900px){
  .login{grid-template-columns:1fr}.login-left{padding:40px 32px 32px;border-right:0;border-bottom:1px solid var(--line)}.login-right{padding:40px 24px 56px}
}
@media (max-width:760px){
  .ws{grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr) auto}
  /* 手机：左栏变为底部标签栏，一行放五个功能和紧凑用量组件（三根竖条），下面一行是版本；同样不滚动。 */
  .rail{grid-row:2;flex-direction:row;flex-wrap:wrap;align-items:stretch;justify-content:space-around;gap:0;padding:0 4px max(4px,env(safe-area-inset-bottom));overflow:hidden;border-top:1px solid var(--line);border-right:0}.rail>*{flex-shrink:1}
  .rail>.mark,.rail-gap,.account{display:none}
  .rail>.build{flex:0 0 100%;flex-direction:row;justify-content:center;gap:0 .5em;margin:0;padding:0 0 2px;font-size:9px;line-height:12px;letter-spacing:0}
  .rail>.build span+span::before{content:"·";margin-right:.5em}
  .usage-ring{flex:0 0 auto;align-self:center;gap:2px;width:auto;padding:5px 6px 3px;font-size:10px}
  .usage-ring-dial{width:30px}.ring-peak{font-size:8px}
  .quota-entry{flex:0 0 auto;align-self:center;gap:3px;width:auto;padding:5px 4px 3px;font-size:10px}.quota-lines{gap:3px}.quota-line{gap:4px;font-size:10px}.quota-line b{min-width:3.6ch}.quota-dot{width:6px;height:6px}
  /* 有额度入口时功能项的起始宽度更小，额度入口、用量圆环与七个功能仍排在同一行（版本号另起一行）。 */
  .rail:has(.quota-entry) .nav-item{flex-basis:24px}
  /* 非零基准宽度：保证占满一行的版本标签总是换到下一行（未启用用量组件时也一样），标签不会被挤成 0 宽。 */
  .nav-item{flex:1 1 40px;min-width:0;width:auto;min-height:52px;padding:7px 0 5px;font-size:11px}
  .nav-badge.alert{right:calc(50% - 22px)}.nav-badge.run{left:calc(50% - 22px)}
  .nav-item[aria-selected=true]::before{left:30%;right:30%;top:-1px;bottom:auto;width:auto;height:2px;border-radius:0 0 2px 2px}
  .head{align-items:center;padding:14px 12px 12px 16px}.title{font-size:22px}.eyebrow{margin-bottom:2px}
  .head-mobile{display:flex}
  /* 手机标题栏改为网格：标题 | 双 IP | 主题、退出（任务入口在底部标签栏）。head-meta 用 display:contents 让其子元素直接参与网格，
     每一项都显式指定格子，避免自动排布把某一项挤到别处。IPv4 与标题同一行；地址较长（IPv6，ip-route--long）
     或屏幕很窄时，双 IP 移到第二行右侧，保持自身宽度、每个地址尽量一行放下。删除授权倒计时只在需要时出现，
     放在下方单独一行靠左，不挤占标题；与第二行的双 IP 同时出现时再下移一行。
     标题栏变高只压缩面板内部，不产生整页滚动。 */
  .head{display:grid;grid-template-columns:minmax(0,1fr) auto auto;column-gap:8px;row-gap:10px}
  .head>div:first-child{grid-column:1;grid-row:1;min-width:0}
  .head-meta{display:contents}
  .head-meta>.grant{grid-column:1/-1;grid-row:2;justify-self:start}
  .head:has(.ip-route--long) .head-meta>.grant{grid-row:3}
  .head-meta>.ip-route{grid-column:2;grid-row:1;justify-self:end}
  .head-meta>.head-mobile{grid-column:3;grid-row:1}
  .head-meta>.server-clock{display:none}
  .head [data-page-eyebrow]{display:none}
  .head-clock{display:block;white-space:nowrap;letter-spacing:.06em;text-transform:none}
  .ip-route{--ip-pad-r:5px;padding:5px var(--ip-pad-r) 5px 7px;border-radius:10px}
  .ip-route--long{grid-column:1/-1!important;grid-row:2!important;justify-self:end!important}
  .ip-user{font-size:clamp(10px,2.75vw,11.5px)}
  .ip-server{font-size:clamp(10.5px,3.05vw,13px)}
  .term-bar{flex-wrap:wrap;padding:6px 12px 0}.term-tools>[data-term-action=copy],.term-tools>[data-term-action=reconnect]{display:none}.term-tools .btn{min-height:34px;padding:0 10px}.term-modes .btn{min-height:30px;padding:0 7px;font-size:11px}
  .term-tab{padding-left:10px}.term-tab-new .long{display:none}.term-tab-new .short{display:inline}
  .term-keys{padding:8px 12px}.term-cmds{left:12px;right:12px;grid-template-columns:minmax(0,1fr);max-height:55vh}.term-keys-sep{display:none}.statusline{padding:8px 12px}.term-note{display:none}.term-note.flash-note{display:block;margin-left:0}
  .fbar{padding:10px 12px}.ftools{gap:2px}.ftools .btn:not(.primary),.ftools .toggle{padding:0 10px}.ftools .btn-label{display:none}
  .table{padding:0 0 max(92px,calc(var(--fm-bar,0px) + 24px))}.row,.fm-row{grid-template-columns:44px minmax(0,1fr) 44px;padding:0 12px}.fm-size{display:none}.fm-meta{display:block}.headrow{display:none}
  .fm-status{left:12px;max-width:calc(100% - 24px)}.fm-transfers{margin:0 12px 10px}
  /* 手机上收起时只留统计与当前任务两行；操作按钮在展开后使用。 */
  .fm-transfers.collapsed .fm-transfers-head>button:not(.t-toggle){display:none}
  .fm-transfers.collapsed.peeking .t-now{flex-basis:100%;padding:0 0 2px 23px}.fm.has-transfers .fm-status{max-width:calc(100% - 24px);margin:0 12px 8px}
  /* 选中一个文件夹时按钮最多（含“重命名”）：窄屏上换行显示，不再被裁掉。 */
  .selbar{left:10px;right:10px;bottom:calc(10px + var(--fm-dock,0px));flex-wrap:wrap;justify-content:flex-end;gap:2px;padding:4px 4px 4px 12px;transform:none}
  .selbar-count{margin-right:auto}.selbar .btn{min-height:40px;padding:0 10px}.selbar .sep{display:none}
  .launch-left,.launch-right{padding:20px 16px}.big-time{font-size:44px}.devices{gap:8px}.device{min-height:150px;padding:16px 6px 12px}
  .ws>.main,.usage-panel{grid-area:1/1}
  .quota-panel .usage-panel-head{flex-wrap:wrap;row-gap:6px}.quota-actions{flex:1 1 auto}.quota-status{flex:1 1 auto;text-align:right}
  .quota-board{flex:none;grid-template-columns:minmax(0,1fr);grid-template-rows:none;--gap:8px}.quota-card{overflow:visible;padding:14px 14px 12px;gap:12px}
  /* 手机：仍是同一张卡片与同一网格，空间不足时只在面板主体内部滚动，页面本身不滚动。 */
  .usage-panel-head{padding:12px 12px 8px 16px}.usage-panel-head h2{font-size:19px}
  .usage-panel-body{padding:2px 12px 14px;overflow:auto;overscroll-behavior:contain}
  .usage-board{flex:none;grid-template-rows:auto auto auto;--gap:8px}
  .space-map:has(>.treemap[hidden])>.space-loading{min-height:140px}
  .treemap{flex:none;height:clamp(220px,55vh,420px);min-height:0}
  /* 手机上浮动提示放在顶部：放在底部会盖住底部导航栏（测试中发现提示显示期间无法切换页面）。 */
  .flash-toast{top:max(10px,env(safe-area-inset-top));left:12px;right:12px;bottom:auto;max-width:none}
  .login-left{gap:22px;padding:28px 20px 22px}.headline{font-size:34px}.lede,.features{display:none}
  .login-right{align-items:flex-start;padding:28px 20px 40px}.form .sub{margin-bottom:22px}
}
/* ---------- Agent SSH 授权（“授权”面板）---------- */
/* 桌面左右两栏（左：授权链接、待确认、已授权；右：权限说明、连接信息、使用说明），手机单栏；面板内部滚动，整页不滚动。 */
.az{flex:1;min-height:0;overflow:auto;display:grid;grid-template-columns:minmax(0,1.2fr) minmax(300px,1fr);align-content:start}
.az-main{display:flex;flex-direction:column;gap:22px;min-width:0;padding:28px 36px;border-right:1px solid var(--line)}
.az-side{display:flex;flex-direction:column;gap:14px;min-width:0;padding:28px 36px}
.az .kicker{margin-bottom:10px}
.az-note{margin:8px 0 0;font-size:12.5px;color:var(--text3)}
.az-off{margin:0;padding:10px 14px;border:1px solid var(--danger-line);border-radius:8px;background:var(--danger-tint2);color:var(--danger-warn);font-size:13px}
.az-list{display:flex;flex-direction:column;gap:10px}
.az-empty{margin:0;padding:14px 0;color:var(--text3);font-size:13px}
.az-card{padding:14px 16px;border:1px solid var(--line);border-radius:10px;background:var(--panel)}
.az-card.pending{border-color:var(--signal-line);background:var(--signal-tint2)}
.az-card-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:8px}
.az-card-head b{min-width:0;overflow:hidden;font-size:14px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}
.az-card-buttons{display:flex;flex:none;align-items:center;gap:6px}
.az-card-buttons .btn{min-height:34px;padding:0 10px}
.az-tag{flex:none;font-family:var(--mono);font-size:11px;color:var(--signal-ink)}
.az-meta{display:grid;grid-template-columns:auto minmax(0,1fr);gap:3px 14px;margin:0;font-size:12.5px}
.az-meta dt{color:var(--text3)}
.az-meta dd{min-width:0;margin:0;overflow-wrap:anywhere;color:var(--text2)}
.az-meta dd.mono{font-family:var(--mono);font-size:12px}
.az-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}
.az-card .az-revoke{min-height:30px;padding:0 12px;font-size:12px}
.az-status{min-height:20px;margin:0;font-size:13px;color:var(--text2)}
.az-status[data-kind=error]{color:var(--danger-warn)}.az-status[data-kind=ok]{color:var(--ok-ink)}
.az-warn{padding:12px 14px;border:1px solid var(--signal-line);border-radius:10px;background:var(--signal-tint)}
.az-warn b{display:block;margin-bottom:4px;font-size:13.5px}
.az-warn p{margin:0;font-size:12.5px;line-height:1.65;color:var(--text2)}
.az-warn code,.az-howto code{font-family:var(--mono);font-size:12px;overflow-wrap:anywhere}
.az-facts{gap:6px 18px}
.az-facts code{font-size:13px;letter-spacing:0;overflow-wrap:anywhere}
.az-facts dd{min-width:0}
.az-keys{flex-direction:column;align-items:flex-start!important;gap:2px!important}
.az-keys span{display:flex;gap:6px;min-width:0;max-width:100%}
.az-keys small{flex:none;width:58px;color:var(--text3);font-size:10.5px;line-height:20px}
.az-keys code{font-size:11.5px!important}
.az-howto{border-top:1px solid var(--line);padding-top:10px;font-size:12.5px;color:var(--text2)}
.az-howto summary{cursor:pointer;color:var(--text);font-weight:500}
.az-howto ol{margin:10px 0 6px;padding-left:18px;line-height:1.7}
.az-howto li+li{margin-top:4px}
.az-howto p{margin:6px 0 0}
.az-dlg-warn{color:var(--text)}
/* 授权链接（主流程）：创建按钮、链接卡片（完整地址、复制、倒计时、状态、作废）。长地址在卡片内换行，不撑宽页面。 */
.az-link-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.az-link-head .kicker{margin-bottom:0}
.az-link .az-note{margin-top:6px}
.az-link-card{display:flex;flex-direction:column;gap:8px;min-width:0;margin-top:12px;padding:14px 16px;border:1px solid var(--line);border-radius:10px;background:var(--panel)}
.az-link-card[data-state=waiting],.az-link-card[data-state=pending]{border-color:var(--signal-line);background:var(--signal-tint2)}
.az-link-state{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap}
.az-pill{display:inline-flex;align-items:center;min-height:22px;padding:0 9px;border:1px solid var(--line2);border-radius:999px;font-size:12px;font-weight:600;color:var(--text2)}
.az-pill[data-state=waiting],.az-pill[data-state=pending],.az-pill[data-state=approved]{border-color:var(--signal-line);color:var(--signal-ink)}
.az-pill[data-state=completed]{border-color:var(--ok-halo);color:var(--ok-ink)}
.az-pill[data-state=denied],.az-pill[data-state=revoked],.az-pill[data-state=failed]{border-color:var(--danger-line);color:var(--danger-warn)}
.az-link-card[data-state=failed]{border-color:var(--danger-line)}
.az-link-card[data-state=failed] .az-link-help{color:var(--danger-warn)}
.az-link-help,.az-card-note{margin:0;font-size:12.5px;line-height:1.6;color:var(--text2)}
.az-card-note{margin:0 0 6px}
.az-url{display:block;min-width:0;max-width:100%;padding:8px 10px;border:1px solid var(--line2);border-radius:8px;background:var(--input-bg);font-family:var(--mono);font-size:12px;line-height:1.5;overflow-wrap:anywhere;word-break:break-all;user-select:all}
.az-link-card .az-actions{margin-top:0;flex-wrap:wrap}
@media (max-width:900px){
  .az{grid-template-columns:minmax(0,1fr)}
  .az-main{padding:18px 16px;border-right:0;border-bottom:1px solid var(--line)}
  .az-side{padding:18px 16px 24px}
}

/* ---------- 版本标签（仅登录后）：桌面在左栏底部两行；手机在底部标签栏下方一行。---------- */
.build{display:flex;flex-direction:column;align-items:center;gap:0;width:100%;margin:8px 0 0;padding:0 2px;font-family:var(--mono);font-size:9px;line-height:1.35;letter-spacing:-.02em;color:var(--text3);opacity:.85;white-space:nowrap;user-select:text}

@media (max-width:420px){.head{padding-left:14px;column-gap:6px}.head .title{font-size:20px}.head-mobile .icon-btn{width:36px}}
/* 400px 以下手机：标题列只剩约 90px。标题字号略缩以免“远程浏览器”折行，按钮与间距收紧（按钮高度仍为 44px）；
   时钟行去掉秒数并收紧字距（如“00:44 UTC+5:30”），完整时间在悬停提示里。 */
@media (max-width:400px){.head-clock .clock-sec{display:none}.head-clock{letter-spacing:0}.head .title{font-size:18px}.head{column-gap:4px}.head-mobile .icon-btn{width:32px}}
@media (max-width:360px){.head-meta>.ip-route{grid-column:1/-1;grid-row:2}.head-meta>.grant{grid-row:3}}
@media (max-width:360px){.rail:has(.quota-entry) .nav-item{font-size:10px}.rail:has(.quota-entry) .nav-item svg{width:20px;height:20px}}
/* 桌面布局在窗口较矮时逐级压缩左栏与标题栏；左栏不滚动，所以每一级都要保证全部内容放得下：
   ≤790 收紧间距、隐藏头像；≤650 缩小图标与字号；≤579 再压低功能入口（文字仍显示）；≤559 只显示图标（文字保留为读屏名称，
   悬停有提示）；≤400 再隐藏标识与单字标签。Agent 额度入口（v1.5.37）让左栏多了一项，前几级因此比原来的 760 / 620 / 500 提前开始。 */
@media (max-height:790px) and (min-width:761px){.rail{gap:2px;padding:12px 0 10px}.rail>.mark{width:34px;height:34px;margin-bottom:8px}.nav-item{min-height:50px;padding:6px 0 5px;gap:4px}.usage-ring{padding:6px 0 5px}.usage-ring-dial{width:clamp(34px,5.5vh,40px)}.quota-entry{gap:3px;padding:5px 0 4px}.quota-lines{gap:3px}.account{margin-top:4px;padding-top:6px}.account .avatar{display:none}}
@media (max-height:650px) and (min-width:761px){.rail>.mark{width:30px;height:30px;margin-bottom:6px}.nav-item{min-height:44px;padding:5px 0 4px;gap:3px;font-size:11px}.nav-item svg{width:20px;height:20px}.nav-badge{top:1px}.usage-ring-dial{width:34px}.quota-line{font-size:10.5px}.account .icon-btn{width:34px;height:34px}.build{margin-top:4px}}
@media (max-height:579px) and (min-width:761px){.nav-item{min-height:41px;padding:4px 0 3px}.quota-entry{gap:2px;padding:4px 0 3px}}
@media (max-height:559px) and (min-width:761px){.rail{padding:8px 0 6px}.nav-item{min-height:38px;padding:4px 0}.nav-item .nav-label{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}.nav-item[aria-selected=true]::before{top:9px;bottom:9px}.usage-ring-dial{width:32px}.usage-ring{gap:2px;padding:4px 0}.usage-ring-label{display:none}.quota-entry{padding:4px 0}.quota-entry-label{display:none}.account{gap:4px;padding-top:4px}.account .icon-btn{width:32px;height:32px}}
@media (max-height:400px) and (min-width:761px){.rail{gap:0;padding:1px 0}.rail>.mark{display:none}.nav-item{min-height:30px;padding:0}.nav-item svg{width:18px;height:18px}.usage-ring{padding:0}.usage-ring-dial{width:26px}.quota-entry{padding:1px 0}.quota-lines{gap:2px}.quota-line{font-size:10px}.account{padding-top:0}.account .icon-btn{width:30px;height:30px}.build{margin-top:0;line-height:1}}
/* 手机竖屏的矮窗口（例如键盘弹出或横屏小手机）：底部标签栏只显示图标。 */
@media (max-width:760px) and (max-height:480px){.nav-item{min-height:42px;padding:4px 0}.nav-item .nav-label{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}.usage-ring-label,.quota-entry-label{display:none}}
/* 矮窗口的任务页：汇总行只在有异常时显示（筛选按钮已带数量），工具栏保持一行。 */
@media (max-height:500px){.task-summary:not([data-issues]){display:none}.tk-bar{padding-top:6px;padding-bottom:6px}.task-foot{padding-top:3px;padding-bottom:4px}}
@media (max-height:560px) and (min-width:761px){.ip-route{--ip-gap:2px;--ip-pad-r:6px;padding:4px var(--ip-pad-r) 4px 8px}.head{padding:12px 28px 10px}.title{font-size:22px}.eyebrow{display:none}}
@media (prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important;scroll-behavior:auto!important}}
/* 账户使用情况：较窄的桌面保持圆环所在的列不窄于 --dial-min；低矮窗口依次压缩留白、字号和次要信息，
   始终保留三项数据、空间分析操作与树图，网格结构不变。圆环不小于 --dial-min（232px），弧形名称不小于 10px、已用 / 总量约 9px。
   手机宽度（<540px）改为单列：圆环、补充信息、空间分析、树图依次排列。 */
@media (max-width:539px){.usage-board{grid-template-columns:minmax(0,1fr);grid-template-rows:none;grid-template-areas:"dial" "meta" "space" "map"}
  .dial-tile{container-type:normal;padding:12px}.dial{width:min(100%,300px)}
  .usage-meta{padding:6px 14px}}
@media (max-width:760px) and (min-width:540px){.usage-board{--side:clamp(252px,34%,280px);--tile-pad:10px}.usage-meta{padding:6px 12px}}
/* 手机横屏：圆环格不小于 --dial-min，树图加高后仍是最大的格子；超出部分在面板内部滚动。 */
@media (max-width:760px) and (min-width:540px) and (orientation:landscape){.space-map{min-height:360px}}
@media (max-width:760px) and (min-width:540px) and (max-height:480px){.usage-panel-head{padding:6px 10px 4px 16px}.usage-panel-head h2{font-size:17px}}
@media (min-width:761px) and (max-width:1100px){.quota-card{padding:14px 16px}.quota-status{max-width:30vw}.usage-panel-head{padding:16px 22px 10px 24px}.usage-panel-body{padding:2px 22px 18px}.usage-board{--side:clamp(252px,min(30%,50cqh),300px);--gap:8px;--tile-pad:10px}.usage-meta{padding:6px 12px 8px}.space-breakdown{padding:8px 12px}}
@media (min-width:1500px) and (min-height:900px){.usage-panel-body{padding:4px 40px 26px}.usage-board{--side:clamp(262px,min(26%,42cqh),420px);--gap:12px;--tile-pad:18px}.usage-panel-head{padding:22px 34px 14px 40px}.usage-meta{padding:12px 20px}.usage-meta dd{font-size:14px}.space-breakdown{padding:14px 18px}.space-map{padding:12px 18px}}
@media (max-height:700px) and (min-width:761px){.quota-board{--gap:8px}.quota-card{gap:12px;padding:12px 16px}.quota-windows{gap:12px}.quota-used b{font-size:22px}.usage-panel-head{padding:10px 22px 6px 28px}.usage-panel-head h2{font-size:18px}.usage-panel-body{padding-bottom:12px}.usage-board{--gap:8px;--tile-pad:10px}.usage-meta{gap:6px;padding:6px 14px 8px}.usage-meta dl div{padding:3px 0}.space-breakdown{padding:10px 14px}.space-map{padding-top:8px;padding-bottom:8px}}
@media (max-height:560px) and (min-width:761px){.quota-board{--gap:6px;border-radius:14px}.quota-card{gap:8px;padding:8px 12px;border-radius:9px}.quota-windows{gap:8px}.quota-window{gap:4px 10px}.quota-used b{font-size:19px}.quota-bar{height:6px}.quota-msg{font-size:12px;line-height:1.45}.quota-note{font-size:11px;line-height:1.4}.quota-actions .btn{min-height:30px}.usage-panel-head{padding:8px 18px 4px 28px}.usage-panel-head h2{font-size:17px}.usage-panel-body{padding-bottom:10px}.usage-board{--gap:6px;--tile-pad:8px;border-radius:14px}.board-tile{border-radius:9px}.usage-meta{gap:4px;padding:4px 12px 6px}.usage-meta dl div{padding:2px 0}.usage-meta dd{font-size:12px}.space-summary{padding-top:5px}.space-breakdown{padding:6px 12px}.space-map{gap:6px;padding:6px 12px}.space-actions .btn{min-height:30px}.space-total{margin-bottom:3px}.space-stack{height:6px;margin-bottom:3px}.space-row{min-height:16px;font-size:11px}.space-summary .space-row{min-height:14px;line-height:14px}.space-loading.space-hint{display:none}}
/* 很矮的桌面：分类汇总的逐项占用改为两列、只留名称与百分比（数值在分类条的悬停提示里），补充信息更紧凑。 */
@media (max-height:520px) and (min-width:761px){.usage-meta{gap:3px}.usage-meta dl div{padding:1px 0}.usage-meta dt,.usage-meta dd{font-size:11.5px}
  .space-summary{padding-top:4px}.space-total{margin-bottom:2px;font-size:11px}.space-stack{height:5px;margin-bottom:2px}
  .space-summary .space-legend{grid-template-columns:repeat(3,minmax(0,auto));justify-content:start;gap:0 10px}.space-summary .space-row{min-height:14px;line-height:14px;font-size:10.5px}
  .space-summary .space-value{display:none}.space-summary .space-percent{min-width:0}.treemap{min-height:70px}}
/* 竖屏平板：树图改占下方整宽，圆环跨两行，空间分析与补充信息在它右侧上下错开，避免又窄又高的圆环格。 */
@media (min-width:540px) and (max-width:1100px) and (orientation:portrait){.usage-board{grid-template-columns:minmax(252px,.9fr) minmax(0,1fr);grid-template-rows:auto auto minmax(0,1fr);grid-template-areas:"dial space" "dial meta" "map map"}.usage-meta{align-content:end}}
