cicy-desktop 2.1.118 → 2.1.120
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/windows-exe-release.yml +21 -0
- package/bin/cicy-desktop +73 -23
- package/package.json +6 -6
- package/src/backends/homepage-preload.js +5 -1
- package/src/backends/homepage-react/assets/NotoMonoSC-Regular-CYHoGOBB.woff2 +0 -0
- package/src/backends/homepage-react/assets/index-CKhSx1lp.css +1 -0
- package/src/backends/homepage-react/assets/index-Cmmw3-Yx.js +377 -0
- package/src/backends/homepage-react/index.html +2 -2
- package/src/backends/ipc.js +19 -0
- package/src/backends/local-teams.js +11 -0
- package/src/backends/sidecar-ipc.js +97 -16
- package/src/chrome/chrome-launcher.js +6 -0
- package/src/cloud/cloud-client.js +42 -4
- package/src/sidecar/colima-docker.js +419 -0
- package/src/sidecar/docker.js +22 -4
- package/src/sidecar/wsl-docker.js +61 -17
- package/src/tools/tab-browser-tools.js +58 -1
- package/workers/render/src/App.css +58 -17
- package/workers/render/src/App.jsx +209 -84
- package/workers/render/src/fonts/NotoMonoSC-Regular.woff2 +0 -0
- package/workers/render/src/mdLite.js +109 -0
- package/workers/render/src/termsText.js +17 -0
- package/src/backends/homepage-react/assets/index-8WruuO1i.js +0 -365
- package/src/backends/homepage-react/assets/index-BcVFakIC.css +0 -1
|
@@ -95,6 +95,27 @@ jobs:
|
|
|
95
95
|
path: dist/*.exe
|
|
96
96
|
if-no-files-found: error
|
|
97
97
|
|
|
98
|
+
# 把最新的安装 exe 推到 OSS 的**单一固定 key**(主人:latest 只发一个)。
|
|
99
|
+
# 每次发版覆盖同一个文件,永远只有一个 latest,URL 不变:
|
|
100
|
+
# https://cicy-1372193042-cn.oss-cn-shanghai.aliyuncs.com/releases/cicy-desktop-latest.exe
|
|
101
|
+
- name: Upload latest EXE to OSS (single 'latest' file, overwritten)
|
|
102
|
+
shell: pwsh
|
|
103
|
+
env:
|
|
104
|
+
OSS_AK: ${{ secrets.OSS_ACCESS_KEY_ID }}
|
|
105
|
+
OSS_SK: ${{ secrets.OSS_ACCESS_KEY_SECRET }}
|
|
106
|
+
run: |
|
|
107
|
+
Invoke-WebRequest -Uri "https://gosspublic.alicdn.com/ossutil/1.7.18/ossutil-v1.7.18-windows-amd64.zip" -OutFile ossutil.zip
|
|
108
|
+
Expand-Archive -LiteralPath ossutil.zip -DestinationPath ossutil-dir -Force
|
|
109
|
+
$oss = "ossutil-dir\ossutil-v1.7.18-windows-amd64\ossutil.exe"
|
|
110
|
+
& $oss config -e oss-cn-shanghai.aliyuncs.com -i "$env:OSS_AK" -k "$env:OSS_SK"
|
|
111
|
+
$exe = Get-ChildItem dist\*.exe | Where-Object { $_.Name -match 'Setup' } | Select-Object -First 1
|
|
112
|
+
if (-not $exe) { $exe = Get-ChildItem dist\*.exe | Select-Object -First 1 }
|
|
113
|
+
if (-not $exe) { Write-Error "no exe found in dist"; exit 1 }
|
|
114
|
+
Write-Host "Uploading $($exe.Name) -> oss://cicy-1372193042-cn/releases/cicy-desktop-latest.exe"
|
|
115
|
+
& $oss cp "$($exe.FullName)" "oss://cicy-1372193042-cn/releases/cicy-desktop-latest.exe" -f --acl public-read
|
|
116
|
+
if ($LASTEXITCODE -ne 0) { Write-Error "ossutil upload failed"; exit 1 }
|
|
117
|
+
Write-Host "Latest EXE: https://cicy-1372193042-cn.oss-cn-shanghai.aliyuncs.com/releases/cicy-desktop-latest.exe"
|
|
118
|
+
|
|
98
119
|
- name: Publish release (drop draft, mark latest)
|
|
99
120
|
# Only promote AFTER all assets uploaded successfully. autoUpdater on
|
|
100
121
|
# existing clients will pick up the new version on its next poll.
|
package/bin/cicy-desktop
CHANGED
|
@@ -13,13 +13,13 @@ const GLOBAL_CONFIG_FILE = path.join(HOME, "global.json");
|
|
|
13
13
|
const STATE_FILE = path.join(HOME, ".cicy-cluster.json");
|
|
14
14
|
const LOGS_DIR = path.join(HOME, "logs");
|
|
15
15
|
const PACKAGE_ROOT = path.join(__dirname, "..");
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
const
|
|
16
|
+
// Electron 二进制来源:**不用用户设任何变量**,自动判断网络。
|
|
17
|
+
// CN(或探测不通,兜底)→ 我们的 Aliyun OSS 镜像(CN-fast,三平台 zip 镜像在
|
|
18
|
+
// <OSS>electron/v<version>/electron-v<version>-<platform>.zip,正是 @electron/get 的布局)。
|
|
19
|
+
// 海外 → electron 官方 GitHub release(不压我们 OSS,海外更快)。
|
|
20
|
+
// 仍可用 ELECTRON_MIRROR 显式覆盖(power user / CI)。下载只在首次(无缓存)发生。
|
|
21
|
+
const OSS_ELECTRON_MIRROR = "https://cicy-1372193042-cn.oss-cn-shanghai.aliyuncs.com/electron/";
|
|
22
|
+
const GH_ELECTRON_BASE = "https://github.com/electron/electron/releases/download/";
|
|
23
23
|
const NPM_REGISTRY = process.env.CICY_NPM_REGISTRY || process.env.npm_config_registry || "https://registry.npmmirror.com";
|
|
24
24
|
const MASTER_ENTRY = path.join(PACKAGE_ROOT, "src", "master", "master-main.js");
|
|
25
25
|
|
|
@@ -89,30 +89,80 @@ function electronArtifact() {
|
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
// 同步探测是否 CN 网络:curl HEAD google(2s 超时)。通 → 海外;不通(CN/被墙/离线)
|
|
93
|
+
// → 当 CN,用 OSS 兜底。裸 node 可跑(不依赖 electron-log/net-detect.js)。只在真正要下
|
|
94
|
+
// electron 时调一次(已有二进制就 return,不探不下),所以不拖慢日常启动。
|
|
95
|
+
function isCNNetwork() {
|
|
96
|
+
if (process.env.CICY_FORCE_CN === "1") return true;
|
|
97
|
+
if (process.env.CICY_FORCE_GLOBAL === "1") return false;
|
|
98
|
+
const curl = isWindows ? "curl.exe" : "curl";
|
|
99
|
+
const nul = isWindows ? "NUL" : "/dev/null";
|
|
100
|
+
try {
|
|
101
|
+
execFileSync(curl, ["-sI", "--max-time", "2", "-o", nul, "https://www.google.com/generate_204"], { stdio: "ignore" });
|
|
102
|
+
return false; // google 可达 → 海外,走官方
|
|
103
|
+
} catch { return true; } // google 不可达 → CN/兜底,走 OSS
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// 决定 electron zip 的下载地址(不用用户设变量):ELECTRON_MIRROR 显式覆盖 > CN→OSS > 海外→官方 GitHub。
|
|
107
|
+
function electronZipUrl() {
|
|
108
|
+
const { zip } = electronArtifact();
|
|
109
|
+
if (process.env.ELECTRON_MIRROR) return { url: `${process.env.ELECTRON_MIRROR}v${ELECTRON_VERSION}/${zip}`, src: "ELECTRON_MIRROR" };
|
|
110
|
+
if (isCNNetwork()) return { url: `${OSS_ELECTRON_MIRROR}v${ELECTRON_VERSION}/${zip}`, src: "OSS(CN)" };
|
|
111
|
+
return { url: `${GH_ELECTRON_BASE}v${ELECTRON_VERSION}/${zip}`, src: "GitHub(海外)" };
|
|
112
|
+
}
|
|
113
|
+
|
|
92
114
|
// Provision the Electron binary INTO the bundled npx copy ourselves: download the
|
|
93
|
-
// platform zip
|
|
94
|
-
//
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
//
|
|
98
|
-
//
|
|
115
|
+
// platform zip with curl (实时进度条 -#), extract with the OS's own unzip, then
|
|
116
|
+
// write path.txt. We deliberately do NOT use electron's install.js / @electron/get:
|
|
117
|
+
// on Windows its bundled extract-zip only PARTIALLY unpacks electron 41 (leaves no
|
|
118
|
+
// path.txt → "Electron failed to install correctly") even though the downloaded zip
|
|
119
|
+
// is valid. curl + Expand-Archive/unzip is reliable and writes a complete dist/.
|
|
120
|
+
// 远端文件大小(取最终响应的 content-length,跟随重定向)。失败返回 0。
|
|
121
|
+
function remoteContentLength(curl, url) {
|
|
122
|
+
try {
|
|
123
|
+
const out = execFileSync(curl, ["-sIL", "--max-time", "15", url], { encoding: "utf8" });
|
|
124
|
+
const all = [...out.matchAll(/content-length:\s*(\d+)/ig)].map((m) => Number(m[1]));
|
|
125
|
+
return all.length ? all[all.length - 1] : 0;
|
|
126
|
+
} catch { return 0; }
|
|
127
|
+
}
|
|
128
|
+
|
|
99
129
|
function provisionElectronFromMirror(bundledDir) {
|
|
100
130
|
const { zip, exe } = electronArtifact();
|
|
101
|
-
const url =
|
|
102
|
-
const tmpZip = path.join(os.tmpdir(), `cicy-${zip}`);
|
|
131
|
+
const { url, src } = electronZipUrl();
|
|
103
132
|
const curl = isWindows ? "curl.exe" : "curl";
|
|
104
|
-
|
|
133
|
+
// 缓存到 ~/Downloads(主人:下到 Downloads,下过就别再下,最好断点续传):
|
|
134
|
+
// • 已完整(大小==远端)→ 直接复用,不再下;
|
|
135
|
+
// • 没下全(部分)→ curl -C - 断点续传;
|
|
136
|
+
// • 没有 → 全新下载。下完保留 zip,不删,下次免下。
|
|
137
|
+
const dlDir = path.join(os.homedir(), "Downloads");
|
|
138
|
+
try { fs.mkdirSync(dlDir, { recursive: true }); } catch {}
|
|
139
|
+
const dest = path.join(dlDir, zip);
|
|
140
|
+
const expected = remoteContentLength(curl, url);
|
|
141
|
+
let localSz = 0; try { localSz = fs.statSync(dest).size; } catch {}
|
|
142
|
+
const complete = localSz >= 50 * 1024 * 1024 && (!expected || localSz === expected);
|
|
143
|
+
if (complete) {
|
|
144
|
+
console.log(`✓ 复用已下载的 Electron:${dest}`);
|
|
145
|
+
} else {
|
|
146
|
+
const resuming = localSz > 0;
|
|
147
|
+
console.log(`⬇️ 下载 Electron ${ELECTRON_VERSION}(来源:${src}${resuming ? ",断点续传" : ""})→ ${dest}`);
|
|
148
|
+
// -C - 断点续传(部分则 206 续,缺则 200 全下);-# 进度条;inherit 让进度条画到终端。
|
|
149
|
+
execFileSync(curl, ["-fL", "-#", "-C", "-", "--retry", "5", "--retry-delay", "2", "--connect-timeout", "20", "-o", dest, url], { stdio: "inherit" });
|
|
150
|
+
try { localSz = fs.statSync(dest).size; } catch {}
|
|
151
|
+
if (localSz < 50 * 1024 * 1024 || (expected && localSz !== expected)) {
|
|
152
|
+
throw new Error(`Electron zip 下载不完整(${localSz}/${expected || "?"} 字节,${dest})—— 重跑会从断点续传`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
105
155
|
const distDir = path.join(bundledDir, "dist");
|
|
106
156
|
fs.rmSync(distDir, { recursive: true, force: true });
|
|
107
157
|
fs.mkdirSync(distDir, { recursive: true });
|
|
108
158
|
if (isWindows) {
|
|
109
|
-
execFileSync("powershell", ["-NoProfile", "-Command", `Expand-Archive -LiteralPath "${
|
|
159
|
+
execFileSync("powershell", ["-NoProfile", "-Command", `Expand-Archive -LiteralPath "${dest}" -DestinationPath "${distDir}" -Force`], { stdio: "inherit" });
|
|
110
160
|
} else {
|
|
111
|
-
execFileSync("unzip", ["-o", "-q",
|
|
161
|
+
execFileSync("unzip", ["-o", "-q", dest, "-d", distDir], { stdio: "inherit" });
|
|
112
162
|
try { fs.chmodSync(path.join(distDir, exe), 0o755); } catch {}
|
|
113
163
|
}
|
|
114
164
|
fs.writeFileSync(path.join(bundledDir, "path.txt"), exe);
|
|
115
|
-
|
|
165
|
+
// 不删 dest:留在 ~/Downloads 缓存,下次免下(主人:下过就别再下)。
|
|
116
166
|
}
|
|
117
167
|
|
|
118
168
|
// Make sure a USABLE electron exists before spawning the worker. A pre-existing
|
|
@@ -528,11 +578,11 @@ function ensureMacDesktopApp() {
|
|
|
528
578
|
: "cicy-desktop";
|
|
529
579
|
// do shell script needs node + the global bin on PATH (GUI launch has a
|
|
530
580
|
// minimal PATH); trailing & + nohup + </dev/null lets the shell return so the
|
|
531
|
-
// applet quits.
|
|
532
|
-
// (
|
|
581
|
+
// applet quits. 不再 export ELECTRON_MIRROR —— bin 自己按网络自动选(CN→OSS / 海外→GitHub)。
|
|
582
|
+
// npm_config_registry(npmmirror)留着给 cicy-code 子包下载用。
|
|
533
583
|
const ascript =
|
|
534
584
|
`do shell script "export PATH=\\"${nodeDir}:${gbin}:/usr/local/bin:/opt/homebrew/bin:$PATH\\" ; ` +
|
|
535
|
-
`export
|
|
585
|
+
`export npm_config_registry=\\"${NPM_REGISTRY}\\" ; ` +
|
|
536
586
|
`nohup '${cicyBin}' > /tmp/cicy-desktop.log 2>&1 < /dev/null &"`;
|
|
537
587
|
const tmp = path.join(os.tmpdir(), `cicy-launch-${process.pid}.applescript`);
|
|
538
588
|
fs.writeFileSync(tmp, ascript);
|
|
@@ -559,7 +609,7 @@ function ensureLinuxDesktopEntry() {
|
|
|
559
609
|
`[Desktop Entry]
|
|
560
610
|
Type=Application
|
|
561
611
|
Name=CiCy Desktop
|
|
562
|
-
Exec=sh -c 'export PATH="${nodeBinDir()}:$PATH"; export
|
|
612
|
+
Exec=sh -c 'export PATH="${nodeBinDir()}:$PATH"; export npm_config_registry="${NPM_REGISTRY}"; exec npx -y cicy-desktop'
|
|
563
613
|
Icon=${icon}
|
|
564
614
|
Terminal=false
|
|
565
615
|
Categories=Development;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cicy-desktop",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.120",
|
|
4
4
|
"description": "CiCy - AI-powered operating system browser",
|
|
5
5
|
"main": "src/main.js",
|
|
6
6
|
"bin": {
|
|
@@ -133,11 +133,11 @@
|
|
|
133
133
|
"//optionalDependencies": "Runtime Bundle v1 (主人指令): platform binaries delivered by `npm i -g cicy-desktop` itself — npm installs only the current-platform subpackage (os/cpu pinned in each), so first start seeds the runtime store with ZERO network, ZERO npx. Windows packages are named *-windows-* (npm spam filter 403s new names containing win32). cicy-msys2 added once published.",
|
|
134
134
|
"optionalDependencies": {
|
|
135
135
|
"electron": "41.0.3",
|
|
136
|
-
"cicy-code-darwin-x64": "2.3.
|
|
137
|
-
"cicy-code-darwin-arm64": "2.3.
|
|
138
|
-
"cicy-code-linux-x64": "2.3.
|
|
139
|
-
"cicy-code-linux-arm64": "2.3.
|
|
140
|
-
"cicy-code-windows-x64": "2.3.
|
|
136
|
+
"cicy-code-darwin-x64": "2.3.19",
|
|
137
|
+
"cicy-code-darwin-arm64": "2.3.19",
|
|
138
|
+
"cicy-code-linux-x64": "2.3.19",
|
|
139
|
+
"cicy-code-linux-arm64": "2.3.19",
|
|
140
|
+
"cicy-code-windows-x64": "2.3.19",
|
|
141
141
|
"cicy-mihomo-darwin-x64": "1.10.4",
|
|
142
142
|
"cicy-mihomo-darwin-arm64": "1.10.4",
|
|
143
143
|
"cicy-mihomo-linux-x64": "1.10.4",
|
|
@@ -161,7 +161,9 @@ contextBridge.exposeInMainWorld("cicy", {
|
|
|
161
161
|
// streaming phase/progress on 'docker:app-progress'.
|
|
162
162
|
appStatus: () => logInvoke("docker:app-status"),
|
|
163
163
|
appBootstrap: () => logInvoke("docker:app-bootstrap"),
|
|
164
|
-
appRestart: () => logInvoke("docker:app-restart"),
|
|
164
|
+
appRestart: () => logInvoke("docker:app-restart"), // supervisorctl 重启 cicy-code
|
|
165
|
+
appDockerRestart: () => logInvoke("docker:app-docker-restart"), // docker restart 整个容器
|
|
166
|
+
appRecreate: () => logInvoke("docker:app-recreate"), // 删容器+重建(换 key,需 confirm)
|
|
165
167
|
appUpdate: () => logInvoke("docker:app-update"),
|
|
166
168
|
appStop: () => logInvoke("docker:app-stop"),
|
|
167
169
|
appUpgrade: () => logInvoke("docker:app-upgrade"),
|
|
@@ -203,6 +205,8 @@ contextBridge.exposeInMainWorld("cicy", {
|
|
|
203
205
|
tabs: {
|
|
204
206
|
open: (url, title) => logInvoke("tabs:open", { url, title }),
|
|
205
207
|
reload: (url, title) => logInvoke("tabs:reload", { url, title }),
|
|
208
|
+
reloadIfOpen: (url, title) => logInvoke("tabs:reloadIfOpen", { url, title }),
|
|
209
|
+
activateIfOpen: (url) => logInvoke("tabs:activateIfOpen", { url }),
|
|
206
210
|
},
|
|
207
211
|
|
|
208
212
|
// ------- new bridges (last rebuild!) -------
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@font-face{font-family:Noto Sans Mono CJK SC;src:url(./NotoMonoSC-Regular-CYHoGOBB.woff2) format("woff2");font-weight:400;font-style:normal;font-display:swap}:root{--mono: "Noto Sans Mono CJK SC", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace}:root{--accent: #5b8df7;--accent-soft: rgba(91,141,247,.16);--accent-line: rgba(91,141,247,.32);--accent-text: #a5c4ff;--ok: #4ade80;--danger: #f7a3a3;--text: #e5e7eb;--text-dim: #9da7b3;--text-mute: #6b7280;--line: rgba(255,255,255,.08)}*{box-sizing:border-box}html,body,#root{margin:0;height:100%}html,body{overflow:hidden}body{font-family:-apple-system,BlinkMacSystemFont,PingFang SC,Segoe UI,Roboto,Helvetica Neue,sans-serif;background:#07080c;color:#e5e7eb;-webkit-font-smoothing:antialiased}.shell{position:relative;min-height:100vh;display:flex;align-items:center;justify-content:center;overflow:hidden;-webkit-app-region:drag}.shell--app{align-items:stretch;justify-content:stretch;flex-direction:row;background:linear-gradient(180deg,#0b0d13,#07080c);overflow:hidden;-webkit-app-region:no-drag}.shell__left{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;overflow:hidden}.helper-aside{flex:0 0 auto;position:relative;background:#0f1115;border-left:1px solid rgba(255,255,255,.06);display:flex;flex-direction:column;min-width:320px;z-index:1}.helper-aside,.helper-aside *,.shell--app .main{-webkit-app-region:no-drag}.shell--app .topbar{-webkit-app-region:drag}.shell--app .topbar .user-chip,.shell--app .topbar .user-chip *,.shell--app .topbar .btn-ghost{-webkit-app-region:no-drag}.glow{position:absolute;top:-40%;right:-40%;bottom:-40%;left:-40%;z-index:0;pointer-events:none;background:radial-gradient(closest-side,rgba(91,141,247,.2),transparent 60%),radial-gradient(closest-side at 30% 70%,rgba(167,139,250,.13),transparent 65%);filter:blur(30px)}.card{-webkit-app-region:no-drag;position:relative;z-index:1;width:380px;padding:36px 36px 28px;background:linear-gradient(180deg,#141820d9,#0d1016d9);border:1px solid rgba(255,255,255,.06);border-radius:16px;box-shadow:0 1px #ffffff0a inset,0 30px 60px #0006;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);display:flex;flex-direction:column;align-items:center;gap:18px}.brand{display:flex;align-items:center;gap:12px;align-self:stretch}.brand-mark{width:40px;height:40px;border-radius:12px;display:grid;place-items:center;background:linear-gradient(135deg,#5b8df7,#a78bfa);box-shadow:0 8px 20px #5b8df759}.brand-mark.sm{width:28px;height:28px;border-radius:8px;box-shadow:none}.brand-mark.sm svg{width:16px;height:16px}.brand-text{line-height:1.2}.brand-name{font-weight:600;font-size:15px}.brand-sub{font-size:12px;color:#9ca3af;margin-top:2px}.tagline{margin:4px 0 0;color:#c7cdd6;font-size:13.5px;text-align:center;line-height:1.55}.btn-primary{-webkit-app-region:no-drag;margin-top:4px;-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;height:42px;display:inline-flex;align-items:center;justify-content:center;gap:8px;background:linear-gradient(180deg,#5b8df7,#4570d8);color:#fff;border:0;border-radius:10px;font-size:14px;font-weight:500;letter-spacing:.2px;cursor:pointer;box-shadow:0 1px #ffffff2e inset,0 -1px #0000002e inset,0 10px 22px #5b8df747;transition:transform 80ms ease,filter .12s ease}.btn-primary:hover{filter:brightness(1.08)}.btn-primary:active{transform:translateY(1px)}.btn-primary:disabled{filter:grayscale(.4) brightness(.7);cursor:default}.btn-ghost{-webkit-app-region:no-drag;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;color:#9ca3af;border:1px solid rgba(255,255,255,.08);border-radius:8px;padding:6px 14px;font-size:12.5px;cursor:pointer;transition:color .12s ease,border-color .12s ease,background .12s ease}.btn-ghost.sm{padding:4px 10px;font-size:11.5px}.btn-ghost:hover{color:#e5e7eb;background:#ffffff0a;border-color:#ffffff24}.btn-ghost:disabled{opacity:.4;cursor:default}.hint{margin:0;font-size:11.5px;color:#6b7280}.spinner-row{display:inline-flex;align-items:center;gap:8px;color:#c7cdd6;font-size:13px}.spin{animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.error{width:100%;font-size:12px;color:#fca5a5;background:#ef444414;border:1px solid rgba(239,68,68,.18);padding:8px 12px;border-radius:8px;text-align:center;line-height:1.5}.topbar{-webkit-app-region:drag;position:relative;flex:0 0 auto;z-index:10;display:flex;align-items:center;justify-content:space-between;padding:14px 24px 12px;background:#08090e99;border-bottom:1px solid rgba(255,255,255,.05);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px)}[data-platform=darwin][data-fullscreen="0"] .topbar{padding-top:34px}.brand-mini{display:inline-flex;align-items:center;gap:10px}.brand-mini .brand-name{font-size:14px}.user-chip{-webkit-app-region:no-drag;display:inline-flex;align-items:center;gap:10px}.welcome{font-size:12px;color:var(--text-dim);padding:4px 10px;border-radius:999px;background:#ffffff0d;border:1px solid var(--line);animation:fadein .2s ease}@keyframes fadein{0%{opacity:0;transform:translateY(-2px)}to{opacity:1;transform:none}}.avatar{width:26px;height:26px;border-radius:50%;display:grid;place-items:center;background:linear-gradient(135deg,#5b8df7,#a78bfa);font-size:12px;font-weight:600;color:#fff}.user-name{font-size:13px;color:#c7cdd6}.user-chip{position:relative}.user-chip__trigger{-webkit-app-region:no-drag;display:inline-flex;align-items:center;gap:8px;border:1px solid transparent;background:transparent;border-radius:999px;padding:3px 8px 3px 3px;cursor:pointer;transition:.12s}.user-chip__trigger:hover,.user-chip__trigger.is-open{background:#ffffff0f;border-color:#ffffff1f}.user-chip__caret{font-size:10px;color:#8a93a3;transition:transform .12s}.user-chip__trigger.is-open .user-chip__caret{transform:rotate(180deg)}.user-chip__menu{position:absolute;top:38px;right:0;z-index:30;min-width:200px;padding:6px;background:#1b2027;border:1px solid rgba(255,255,255,.12);border-radius:12px;box-shadow:0 12px 34px #00000080;display:flex;flex-direction:column;gap:2px;animation:fadein .14s ease}.user-chip__menu-item{text-align:left;width:100%;border:none;background:transparent;color:#d1d5db;border-radius:8px;padding:9px 11px;font-size:13px;cursor:pointer;transition:.12s}.user-chip__menu-item:hover{background:#ffffff12;color:#fff}.user-chip__menu-item.is-danger{color:#f7a3a3}.user-chip__menu-item.is-danger:hover{background:#ef444429;color:#fff}.user-chip__menu-sep{height:1px;margin:4px 2px;background:#ffffff14}.user-chip__menu-version{margin-top:4px;padding:8px 11px 4px;font-size:11px;color:#6b7280;text-align:center;font-variant-numeric:tabular-nums;-webkit-user-select:text;user-select:text;border-top:1px solid rgba(255,255,255,.06)}.user-chip__mitm-row{display:flex;align-items:center;justify-content:space-between;gap:10px;cursor:default}.user-chip__mitm-row:hover{background:transparent}.user-chip__mitm-label{font-size:13px;color:var(--text)}.mini-switch{-webkit-app-region:no-drag;position:relative;flex:0 0 auto;width:36px;height:20px;padding:0;border-radius:999px;border:1px solid var(--line);background:#ffffff14;cursor:pointer;transition:background .16s ease,border-color .16s ease}.mini-switch.is-on{background:var(--accent);border-color:var(--accent)}.mini-switch.is-busy{opacity:.6;cursor:default}.mini-switch:disabled{cursor:default}.mini-switch__knob{position:absolute;top:1px;left:1px;width:16px;height:16px;border-radius:50%;background:#fff;box-shadow:0 1px 2px #00000073;transition:transform .16s ease}.mini-switch.is-on .mini-switch__knob{transform:translate(16px)}.mini-switch.is-busy .mini-switch__knob{animation:spin 1s linear infinite}.user-chip__mitm-note{margin:0 4px;padding:2px 4px 6px;font-size:11px;color:var(--text-mute)}.user-chip__mitm-err{margin:2px 4px 6px;padding:5px 8px;font-size:11px;color:var(--danger);background:#ef44441a;border-radius:6px;line-height:1.4}.bcard__top-right{display:inline-flex;align-items:center;gap:6px}.bcard__billing-btn{-webkit-app-region:no-drag;border:1px solid var(--line);background:transparent;color:var(--text-dim);border-radius:7px;padding:3px 9px;font-size:11px;cursor:pointer;transition:color .12s,border-color .12s,background .12s}.bcard__billing-btn:hover{color:var(--accent-text);border-color:var(--accent-line);background:var(--accent-soft)}.glow--app{inset:-10% -10% auto -10%;height:50vh;background:radial-gradient(closest-side at 75% 0%,rgba(91,141,247,.18),transparent 65%),radial-gradient(closest-side at 20% 10%,rgba(167,139,250,.1),transparent 60%);filter:blur(40px)}.main{position:relative;z-index:1;padding:22px 32px 48px;width:100%;display:flex;flex-direction:column;gap:16px;flex:1 1 auto;min-height:0;overflow-y:auto}.main::-webkit-scrollbar{width:8px}.main::-webkit-scrollbar-track{background:transparent}.main::-webkit-scrollbar-thumb{background:#7d87964d;border-radius:999px;border:2px solid transparent;background-clip:padding-box}.main::-webkit-scrollbar-thumb:hover{background-color:#7d87968c}.app__tabs{display:inline-flex;align-items:center;gap:4px;padding:4px;background:#1418208c;border:1px solid rgba(255,255,255,.06);border-radius:10px;align-self:flex-start;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.app__tab{-webkit-app-region:no-drag;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;color:#9ca3af;border:0;border-radius:7px;padding:6px 14px;font-size:12.5px;font-weight:500;letter-spacing:.15px;cursor:pointer;display:inline-flex;align-items:center;gap:6px;transition:color .12s ease,background .12s ease}.app__tab:hover{color:#e5e7eb;background:#ffffff0a}.app__tab.is-active{color:#fff;background:#5b8df72e;box-shadow:0 0 0 1px #5b8df74d inset}.app__tab-count{font-size:10.5px;color:#9ca3af;background:#ffffff0f;padding:1px 6px;border-radius:999px;min-width:18px;text-align:center}.app__tab.is-active .app__tab-count{background:#5b8df74d;color:#fff}.app__tabsrow{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%}.app__add-team{-webkit-app-region:no-drag;-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer;flex:none;color:#5b8df7;font-weight:600;font-size:12.5px;background:#5b8df71a;border:1px solid rgba(91,141,247,.35);border-radius:9px;padding:7px 14px;transition:color .12s ease,background .12s ease,border-color .12s ease}.app__add-team:hover{color:#fff;background:#5b8df738;border-color:#5b8df7a6}.app__grid{display:grid;grid-template-columns:repeat(auto-fill,200px);gap:14px}.add-card{-webkit-app-region:no-drag;-webkit-appearance:none;-moz-appearance:none;appearance:none;width:200px;height:200px;background:transparent;border:1.5px dashed rgba(255,255,255,.12);border-radius:14px;color:#9ca3af;cursor:pointer;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;transition:border-color .16s ease,color .16s ease,background .16s ease}.add-card:hover{border-color:#5b8df780;color:#e5e7eb;background:#5b8df70d}.add-card__plus{width:36px;height:36px;border-radius:50%;display:grid;place-items:center;background:#ffffff0a;font-size:22px;font-weight:300;color:inherit}.add-card__label{font-size:13px;font-weight:500}.bcard--helper{background:linear-gradient(160deg,#5b8df729,#a78bfa24 60%,#1418208c);border-color:#a78bfa40}.bcard--helper .bcard__accent{background:linear-gradient(90deg,#5b8df7,#a78bfa);opacity:1}.bcard--helper:hover{border-color:#a78bfa73}.bcard__pill--helper{background:#a78bfa2e;border-color:#a78bfa4d;color:#c4b5fd;font-size:11px;font-weight:600;letter-spacing:.2px}.bcard__helper-icon{font-size:12px;filter:grayscale(.2)}.bcard__badge--free{background:#34d39926;color:#34d399;border:1px solid rgba(52,211,153,.3)}.bcard__badge--trial{background:#ffffff0f;color:var(--text-dim);border:1px solid var(--line);font-size:9.5px;letter-spacing:.3px;padding:2px 7px}.bcard__badge--local{background:#5b8df72e;color:#a5c4ff;border:1px solid rgba(91,141,247,.35);font-size:9.5px;letter-spacing:.3px;padding:2px 7px}.bcard--helper .bcard__name{color:#f3f4f6}.bcard__desc{margin:4px 0 0;font-size:11.5px;line-height:1.5;color:#c7cdd6;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.bcard__fineprint{margin:4px 0 0;font-size:10.5px;color:#9ca3af;opacity:.8}.bcard__cta--helper{background:#ffffff0d;box-shadow:none}.bcard__cta--helper:hover{background:var(--accent-soft)}.helper-aside__top{display:flex;align-items:center;justify-content:space-between;padding:12px 14px 10px;border-bottom:1px solid rgba(255,255,255,.05)}.helper-aside__title{font-size:12.5px;font-weight:600;color:#c7cdd6}.helper-aside__close{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:0;color:#6b7280;font-size:20px;line-height:1;width:26px;height:26px;border-radius:6px;cursor:pointer;transition:color .12s ease,background .12s ease}.helper-aside__close:hover{color:#e5e7eb;background:#ffffff0f}.helper-modal__backdrop{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;align-items:center;justify-content:center;background:transparent;z-index:20;animation:fadein .14s ease;padding:16px;pointer-events:auto}.helper-modal{width:min(360px,100%);background:linear-gradient(180deg,#1f2733,#1a2029);border:1px solid rgba(255,255,255,.1);border-radius:12px;padding:20px 22px 16px;color:#e5e7eb;box-shadow:0 24px 48px -12px #0009,0 1px #ffffff14 inset;animation:fadein .18s ease}.helper-modal__title{font-size:14px;font-weight:600;color:#f3f4f6;margin-bottom:8px}.helper-modal__desc{font-size:12.5px;line-height:1.6;color:#b6bcc6;margin-bottom:18px}.helper-modal__desc code{font-family:var(--mono);font-size:11.5px;padding:1px 6px;background:#ffffff14;border:1px solid rgba(255,255,255,.08);border-radius:4px;color:#e7eaef}.helper-modal__actions{display:flex;align-items:center;justify-content:flex-end;gap:8px}.helper-modal__btn{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#ffffff0f;color:#d2d6dd;border:1px solid rgba(255,255,255,.1);border-radius:7px;padding:7px 14px;font-size:12.5px;font-weight:500;cursor:pointer;transition:background .12s ease,color .12s ease,transform 80ms ease}.helper-modal__btn:hover{background:#ffffff1a;color:#fff}.helper-modal__btn:active{transform:translateY(1px)}.helper-modal__btn--ghost{background:transparent;border-color:transparent;color:#ffffff8c;margin-right:auto;padding-left:4px;padding-right:4px}.helper-modal__btn--ghost:hover{background:transparent;color:#ffffffd9}.helper-modal__btn--primary{background:linear-gradient(180deg,#5b8df7,#4570d8);border-color:#ffffff2e;color:#fff}.helper-modal__btn--primary:hover{background:linear-gradient(180deg,#6c9af9,#5a82e0)}.helper-modal__btn:disabled{filter:grayscale(.4) brightness(.7);cursor:default}.helper-placeholder{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:32px 40px;text-align:center;color:#9ca3af}.helper-placeholder__mark{font-size:48px;line-height:1;filter:grayscale(.2);opacity:.85}.helper-placeholder__title{margin:0;font-size:16px;font-weight:600;color:#e5e7eb}.helper-placeholder__sub{margin:0;font-size:12.5px;line-height:1.6;color:#9ca3af;max-width:320px}.helper-placeholder__note{margin-top:8px;font-size:11px;color:#6b7280;padding:4px 10px;background:#ffffff08;border:1px solid rgba(255,255,255,.06);border-radius:999px}.helper-placeholder__note code{font-family:var(--mono);font-size:11px;color:#c7cdd6}.section{background:linear-gradient(180deg,#141820b8,#0d1016b8);border:1px solid rgba(255,255,255,.06);border-radius:14px;box-shadow:0 1px #ffffff0a inset,0 14px 30px #00000052;-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);padding:18px 18px 16px}.section-head{display:flex;align-items:center;gap:8px;padding:0 4px 14px;border-bottom:1px solid rgba(255,255,255,.04);margin-bottom:14px}.section-icon{font-size:14px;opacity:.8}.section-head h2{margin:0;font-size:13.5px;font-weight:600;color:#e5e7eb;letter-spacing:.2px}.section-sub{font-size:12px;color:#6b7280}.section-body{display:flex;flex-direction:column;gap:10px}.grid{display:grid;grid-template-columns:repeat(auto-fill,200px);gap:14px}.bcard{position:relative;width:200px;height:200px;background:#1418208c;border:1px solid rgba(255,255,255,.07);border-radius:14px;padding:16px;display:flex;flex-direction:column;overflow:hidden;transition:transform .18s ease,border-color .18s ease,box-shadow .18s ease;--brand: #5b8df7;--accent-cloud: #f59e0b;--accent-custom: #8b5cf6}.bcard:hover{transform:translateY(-2px);border-color:#ffffff24;box-shadow:0 12px 32px -10px #00000073,0 1px #ffffff0a inset}.bcard__accent{position:absolute;top:0;left:0;right:0;height:3px;background:var(--brand);opacity:.9}.bcard--cloud .bcard__accent{background:var(--accent-cloud)}.bcard--custom .bcard__accent{background:var(--accent-custom)}.bcard--online:before{content:"";position:absolute;bottom:-40%;right:-20%;width:140%;height:100%;background:radial-gradient(circle at center,rgba(91,141,247,.22) 0%,transparent 60%);pointer-events:none;opacity:.55}.bcard--cloud.bcard--online:before{background:radial-gradient(circle at center,rgba(245,158,11,.22) 0%,transparent 60%)}.bcard--custom.bcard--online:before{background:radial-gradient(circle at center,rgba(139,92,246,.22) 0%,transparent 60%)}.bcard__top{display:flex;align-items:center;justify-content:space-between;position:relative;z-index:5}.bcard__pill{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;background:#08090eb3;border:1px solid rgba(255,255,255,.07);border-radius:999px;color:#9ca3af}.bcard__pill svg{display:block}.bcard__dot{width:7px;height:7px;border-radius:50%;background:#6b7280;flex-shrink:0}.bcard__dot[data-tone=ok]{background:#34d399;box-shadow:0 0 0 2px #34d39940}.bcard__dot[data-tone=off]{background:#6b7280}.bcard__dot[data-tone=warn]{background:#fbbf24;box-shadow:0 0 0 2px #fbbf2440}.bcard__dot[data-tone=err]{background:#f87171;box-shadow:0 0 0 2px #f8717140}.bcard__badge{display:inline-flex;align-items:center;padding:2px 8px;border-radius:999px;background:var(--accent-soft);color:var(--accent-text);font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px}.bcard__body{flex:1;display:flex;flex-direction:column;gap:4px;padding-top:12px;padding-bottom:12px;position:relative;z-index:1;min-width:0}.bcard__name{margin:0;font-size:17px;font-weight:700;color:#e5e7eb;letter-spacing:-.015em;line-height:1.25;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.bcard__host{font-family:var(--mono);font-size:11px;color:#9ca3af;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.bcard__meta{display:flex;flex-wrap:wrap;gap:4px;margin-top:4px}.bcard__chip{font-size:10.5px;color:#9ca3af;background:#ffffff08;border:1px solid rgba(255,255,255,.06);padding:2px 7px;border-radius:999px}.bcard__cta{position:relative;z-index:1;display:inline-flex;align-items:center;justify-content:center;gap:8px;width:100%;height:38px;border:1px solid var(--line);border-radius:9px;background:#ffffff0d;color:var(--text);font-size:13px;font-weight:600;letter-spacing:.1px;cursor:pointer;transition:transform 80ms ease,background .14s ease,border-color .14s ease,color .14s ease;box-shadow:none}.bcard--cloud .bcard__cta,.bcard--custom .bcard__cta{background:#ffffff0d;box-shadow:none}.bcard__cta:hover{background:var(--accent-soft);border-color:var(--accent-line);color:var(--accent-text)}.bcard__cta:active{transform:translateY(1px)}.bcard__cta:disabled{background:#ffffff08;color:#6b7280;cursor:not-allowed;box-shadow:none;border:1px solid rgba(255,255,255,.06)}.empty{font-size:12.5px;color:#6b7280;padding:14px 16px;background:#ffffff05;border:1px dashed rgba(255,255,255,.08);border-radius:10px}.bcard__menuwrap{position:relative}.bcard__kebab{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:1px solid transparent;border-radius:8px;background:transparent;color:#8b949e;cursor:pointer;transition:.15s}.bcard__kebab:hover:not(:disabled){color:#e6edf3;background:#ffffff0f;border-color:#ffffff1f}.bcard__kebab:disabled{opacity:.5;cursor:default}.bcard__kebab.has-dot{color:#e6edf3}.bcard__kebab.has-dot:after{content:"";position:absolute;top:3px;right:3px;width:7px;height:7px;border-radius:50%;background:#f59e0b;box-shadow:0 0 0 2px #0f1115}.bcard__menu{position:absolute;top:32px;right:0;z-index:20;min-width:150px;padding:5px;background:#1b2027;border:1px solid rgba(255,255,255,.12);border-radius:10px;box-shadow:0 10px 30px #00000073;display:flex;flex-direction:column;gap:2px}.bcard__menu-item{text-align:left;width:100%;border:none;background:transparent;color:#d1d5db;border-radius:7px;padding:7px 10px;font-size:12.5px;cursor:pointer;transition:.12s}.bcard__menu-item:hover{background:#ffffff12;color:#fff}.bcard__menu-item.is-accent{color:var(--accent-text);font-weight:600}.bcard__menu-item.is-accent:hover{background:var(--accent-soft);color:#c7dbff}.bcard__menu-item.is-danger{color:#f7a3a3}.bcard__menu-item.is-danger:hover{background:#ef444429;color:#fff}.bcard__menu--portal{z-index:9990}.bcard__menu--portal .bcard__menu-item{white-space:normal;word-break:break-word}.docker-setup{margin-bottom:14px;padding:14px 16px;background:linear-gradient(180deg,#5b8df714,#14182080);border:1px solid rgba(91,141,247,.22);border-radius:12px}.docker-setup__head{display:flex;flex-direction:column;gap:3px;margin-bottom:12px}.docker-setup__title{font-size:13.5px;font-weight:600;color:#e6edf3}.docker-setup__sub{font-size:11.5px;color:#9ca3af;line-height:1.5}.docker-setup__steps{display:flex;flex-direction:column;gap:6px;margin-bottom:12px}.docker-step{display:flex;align-items:center;gap:8px;font-size:12px;color:#9ca3af}.docker-step__dot{width:8px;height:8px;border-radius:50%;flex:none;background:#3a4150;transition:.2s}.docker-step__label{color:#c7cdd6;min-width:96px}.docker-step__msg{color:#8b949e;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.docker-step__pct{margin-left:auto;font-variant-numeric:tabular-nums;color:#5b8df7;flex:none}.docker-step.is-running .docker-step__dot{background:#5b8df7;box-shadow:0 0 0 3px #5b8df72e;animation:dpulse 1.2s ease-in-out infinite}.docker-step.is-running .docker-step__label{color:#e6edf3}.docker-step.is-done .docker-step__dot,.docker-step.is-skip .docker-step__dot{background:#10b981}.docker-step.is-skip{opacity:.7}.docker-step.is-retry .docker-step__dot{background:#f59e0b}.docker-step.is-error .docker-step__dot{background:#ef4444;box-shadow:0 0 0 3px #ef444426}.docker-step.is-error .docker-step__msg{color:#f7a3a3}@keyframes dpulse{0%,to{opacity:1}50%{opacity:.45}}.docker-setup__actions{display:flex;gap:8px;align-items:center}.docker-setup__actions .btn-primary{width:auto;padding:7px 16px;font-size:12.5px}.bcard__ver{font-size:11px;color:#8b949e;font-variant-numeric:tabular-nums}.bcard__chip--new{color:var(--accent-text);background:var(--accent-soft);border-color:var(--accent-line)}.bcard__opmsg{display:flex;align-items:center;gap:6px;margin-top:9px;font-size:11.5px;color:#9ca3af;word-break:break-word}.toast-host{position:fixed;right:16px;bottom:16px;z-index:9999;display:flex;flex-direction:column;gap:8px;max-width:min(360px,calc(100vw - 32px));pointer-events:none}.toast{pointer-events:auto;position:relative;display:flex;flex-direction:column;gap:6px;padding:10px 30px 10px 12px;font-size:12.5px;line-height:1.4;color:var(--text, #e6eaf0);background:#161a21f5;border:1px solid rgba(125,135,150,.22);border-left:3px solid var(--accent, #3b82f6);border-radius:10px;box-shadow:0 8px 28px #0000006b;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);animation:toast-in .18s ease}@keyframes toast-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}.toast[data-status=error]{border-left-color:#f87171}.toast[data-status=error] .toast__msg{color:#f87171}.toast[data-status=done]{border-left-color:#4ade80}.toast[data-status=done] .toast__msg{color:#4ade80}.toast__msg{word-break:break-word}.toast__x{position:absolute;top:6px;right:8px;background:none;border:none;cursor:pointer;padding:0;font-size:15px;line-height:1;color:var(--text-dim, #9da7b3)}.toast__x:hover{color:var(--text, #e6eaf0)}.toast__bar{display:block;height:4px;border-radius:2px;background:#7d879640;overflow:hidden}.toast__bar>span{display:block;height:100%;border-radius:2px;background:var(--accent, #3b82f6);transition:width .25s ease}.drawer-scrim{position:fixed;top:0;right:0;bottom:0;left:0;z-index:10000;display:flex;align-items:flex-end;justify-content:center;background:#06080c80;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:drawer-fade .18s ease}@keyframes drawer-fade{0%{opacity:0}to{opacity:1}}.drawer{width:min(560px,calc(100vw - 24px));max-height:76vh;display:flex;flex-direction:column;margin-bottom:12px;background:#14181ffa;border:1px solid rgba(125,135,150,.2);border-radius:16px 16px 12px 12px;box-shadow:0 -10px 44px #00000080;overflow:hidden;animation:drawer-up .24s cubic-bezier(.22,1,.36,1)}@keyframes drawer-up{0%{opacity:0;transform:translateY(28px)}to{opacity:1;transform:none}}.drawer__head{display:flex;align-items:center;justify-content:space-between;padding:14px 14px 12px 16px;border-bottom:1px solid rgba(125,135,150,.14)}.drawer__title{display:flex;align-items:center;gap:11px}.drawer__spark{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;border-radius:8px;font-size:14px;font-weight:700;background:#5b8df729;color:var(--brand, #5b8df7)}.drawer__spark--done{background:#4ade8029;color:#4ade80}.drawer__spark--error{background:#f8717129;color:#f87171}.drawer__h{font-size:13.5px;font-weight:650;color:var(--text, #e6eaf0)}.drawer__sub{font-size:11.5px;color:var(--text-dim, #9da7b3);margin-top:1px}.drawer__x{background:none;border:none;cursor:pointer;padding:2px 6px;font-size:19px;line-height:1;color:var(--text-dim, #9da7b3);border-radius:6px}.drawer__x:hover:not(:disabled){color:var(--text, #e6eaf0);background:#7d87961f}.drawer__x:disabled{opacity:.35;cursor:default}.drawer__steps{display:flex;align-items:center;gap:0;padding:14px 18px 4px}.drawer__step{display:flex;align-items:center;gap:7px;color:var(--text-dim, #9da7b3);font-size:12px}.drawer__step-dot{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:50%;font-size:11px;font-weight:700;border:1.5px solid rgba(125,135,150,.35);color:var(--text-dim, #9da7b3);background:transparent;flex:none}.drawer__step-bar{width:30px;height:1.5px;background:#7d879640;margin:0 8px}.drawer__step.is-active .drawer__step-dot{border-color:var(--brand, #5b8df7);color:var(--brand, #5b8df7);box-shadow:0 0 0 3px #5b8df72e}.drawer__step.is-active .drawer__step-label{color:var(--text, #e6eaf0)}.drawer__step.is-done .drawer__step-dot{border-color:#4ade80;color:#06210f;background:#4ade80}.drawer__step.is-done .drawer__step-bar{background:#4ade8080}.drawer__step.is-error .drawer__step-dot{border-color:#f87171;color:#f87171}.drawer__log{flex:1;min-height:96px;overflow-y:auto;margin:10px 14px;padding:10px 12px;background:#0a0c10b3;border:1px solid rgba(125,135,150,.12);border-radius:10px;font-family:var(--mono);font-size:11.5px;line-height:1.7}.drawer__log--scroll{max-height:168px;scrollbar-width:thin;scrollbar-color:rgba(125,135,150,.4) transparent}.drawer__log--scroll::-webkit-scrollbar{width:7px}.drawer__log--scroll::-webkit-scrollbar-track{background:transparent;margin:4px 0}.drawer__log--scroll::-webkit-scrollbar-thumb{background:#7d879652;border-radius:6px;border:1.5px solid transparent;background-clip:padding-box}.drawer__log--scroll::-webkit-scrollbar-thumb:hover{background:#7d87968c;background-clip:padding-box}.drawer__now{display:flex;align-items:center;gap:9px;margin:12px 14px 2px;padding:9px 12px;background:#5b8df714;border:1px solid rgba(91,141,247,.2);border-radius:10px;font-size:12.5px;color:var(--text, #e6eaf0)}.drawer__now span{flex:1;min-width:0}.drawer__dlbars{display:flex;flex-direction:column;gap:10px;margin:12px 14px 2px}.dlbar{padding:10px 12px;border-radius:10px;background:#0a0c108c;border:1px solid rgba(125,135,150,.14)}.dlbar__head{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin-bottom:7px}.dlbar__name{font-size:12.5px;font-weight:600;color:var(--text, #e6eaf0)}.dlbar__pct{font-size:11px;color:var(--text-dim, #9da7b3);font-variant-numeric:tabular-nums}.dlbar__track{height:6px;border-radius:4px;background:#7d879629;overflow:hidden}.dlbar__fill{height:100%;border-radius:4px;background:linear-gradient(90deg,#5b8df7,#2496ed);transition:width .2s ease}.dlbar__fill.is-done{background:#4ade80}.dlbar__url{margin-top:6px;font-size:10.5px;color:#6b7686;font-family:var(--mono);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dlbar__urlk{display:inline-block;min-width:16px;text-align:center;margin-right:5px;padding:0 4px;border-radius:4px;font-family:inherit;font-size:9.5px;color:#8fb0f5;background:#5b8df729}.drawer__headbtns{display:flex;align-items:center;gap:2px}.drawer-min{position:fixed;right:20px;bottom:20px;z-index:2001;display:inline-flex;align-items:center;gap:9px;padding:10px 15px;border-radius:999px;cursor:pointer;background:#16181d;border:1px solid rgba(125,135,150,.22);box-shadow:0 10px 30px #00000080;color:var(--text, #e6eaf0);font-size:12.5px;font-weight:550;animation:drawer-min-in .18s cubic-bezier(.2,.8,.2,1)}.drawer-min:hover{border-color:#7d879666;background:#1b1e24}@keyframes drawer-min-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}.drawer-min__spark{display:inline-flex;width:16px;height:16px;align-items:center;justify-content:center;font-weight:700}.drawer-min--done .drawer-min__spark{color:#4ade80}.drawer-min--error .drawer-min__spark{color:#f87171}.drawer-min__label{font-variant-numeric:tabular-nums}.drawer__log-empty{color:var(--text-dim, #9da7b3)}.drawer__line{display:flex;align-items:baseline;gap:8px;padding:1px 0}.drawer__t{color:#6b7686;flex:none;font-variant-numeric:tabular-nums}.drawer__badge{flex:none;padding:0 6px;border-radius:4px;font-size:10px;font-weight:600;background:#5b8df729;color:#8fb0f5}.drawer__badge--swap{background:#f59e0b29;color:#f5b342}.drawer__badge--done{background:#4ade8029;color:#6ee79b}.drawer__linemsg{color:var(--text, #e6eaf0);word-break:break-word}.drawer__line[data-status=error] .drawer__linemsg{color:#f87171}.drawer__line[data-status=done] .drawer__linemsg{color:#6ee79b}.drawer__line[data-status=skip] .drawer__linemsg{color:var(--text-dim, #9da7b3)}.drawer__hint{margin:0 14px 8px;padding:8px 12px;background:#f59e0b1a;border:1px solid rgba(245,158,11,.28);border-radius:8px;color:#f5b342;font-size:11.5px;line-height:1.5}.drawer__foot{display:flex;align-items:center;gap:8px;padding:12px 14px;border-top:1px solid rgba(125,135,150,.14)}.drawer__foot-status{font-size:12.5px;color:var(--text-dim, #9da7b3);margin-right:auto}.drawer__foot-status.is-error{color:#f87171}.drawer__foot-status.is-done{color:#4ade80}.drawer__foot-status.is-reboot,.drawer__spark--reboot,.drawer-min--reboot .drawer-min__spark{color:#f5b342}.drawer__btn{padding:7px 16px;border-radius:8px;cursor:pointer;font-size:12.5px;font-weight:550;background:#7d879624;border:1px solid rgba(125,135,150,.2);color:var(--text, #e6eaf0)}.drawer__btn:hover{background:#7d879638}.drawer__btn.is-accent{background:var(--brand, #5b8df7);border-color:var(--brand, #5b8df7);color:#fff}.drawer__btn.is-accent:hover{filter:brightness(1.08)}.mitm-card{border:1px solid rgba(125,135,150,.22);border-radius:12px;padding:14px 16px;margin-bottom:14px;background:#1e242e66}.mitm-card--on{border-color:#4ade8059;background:#16281e66}.mitm-pill{position:fixed;top:64px;right:16px;z-index:9998;-webkit-app-region:no-drag;display:inline-flex;align-items:center;gap:8px;padding:4px 6px 4px 11px;border-radius:999px;width:fit-content;max-width:calc(100vw - 32px);background:#141e18d9;border:1px solid rgba(74,222,128,.3);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);box-shadow:0 4px 14px #0000004d;font-size:12px;line-height:1}.mitm-pill__dot{width:7px;height:7px;border-radius:50%;flex:none;background:#4ade80;box-shadow:0 0 0 3px #4ade8029}.mitm-pill__dot[data-busy="1"]{background:#9da7b3;box-shadow:0 0 0 3px #9da7b329}.mitm-pill__text{color:var(--text-dim, #9da7b3);white-space:nowrap}.mitm-pill__off{background:none;border:none;cursor:pointer;color:#6b7686;font-size:11.5px;padding:3px 7px;border-radius:999px}.mitm-pill__off:hover{color:#f87171;background:#f871711a}.mitm-card__head{display:flex;align-items:center;gap:8px;margin-bottom:6px}.mitm-card__dot{width:8px;height:8px;border-radius:50%;background:#9da7b3;flex:0 0 auto}.mitm-card__dot[data-state=on]{background:#4ade80;box-shadow:0 0 6px #4ade8099}.mitm-card__dot[data-state=warn]{background:#fbbf24}.mitm-card__dot[data-state=off]{background:#60a5fa}.mitm-card__title{font-size:14px;font-weight:600;color:var(--text, #e6edf3)}.mitm-card__desc{font-size:12.5px;line-height:1.5;color:var(--text-dim, #9da7b3);margin:0 0 10px}.mitm-card__note{color:#fbbf24}.mitm-card__error{font-size:12px;color:#f87171;margin-bottom:8px}.mitm-card__actions{display:flex;gap:8px}.mitm-card__btn{font-size:13px;padding:7px 16px;border-radius:8px;border:none;cursor:pointer;background:var(--accent, #3b82f6);color:#fff;font-weight:500}.mitm-card__btn:disabled{opacity:.6;cursor:default}.mitm-card__btn--ghost{background:transparent;border:1px solid rgba(125,135,150,.35);color:var(--text-dim, #9da7b3)}.mitm-card__sub{color:var(--text-dim, #9da7b3);opacity:.8;font-size:11.5px}.terms-gate{display:flex;align-items:center;justify-content:center;padding:24px}.terms-gate__panel,.terms-gate__panel *{-webkit-app-region:no-drag}.terms-gate__panel{position:relative;z-index:1;width:min(680px,94vw);max-height:90vh;display:flex;flex-direction:column;background:#141921eb;border:1px solid rgba(125,135,150,.22);border-radius:16px;padding:28px 30px;box-shadow:0 24px 60px #00000080}.terms-gate__title{font-size:20px;font-weight:700;margin:0 0 4px;color:var(--text, #e6edf3)}.terms-gate__subtitle{font-size:13px;color:var(--text-dim, #9da7b3);margin:0 0 16px}.terms-gate__body{overflow-y:auto;flex:1 1 auto;min-height:0;padding-right:10px;border-top:1px solid rgba(125,135,150,.15);border-bottom:1px solid rgba(125,135,150,.15);padding-top:14px;padding-bottom:14px;overscroll-behavior:contain}.terms-gate__body{scrollbar-width:thin;scrollbar-color:rgba(125,135,150,.35) transparent}.terms-gate__body::-webkit-scrollbar{width:8px}.terms-gate__body::-webkit-scrollbar-track{background:transparent}.terms-gate__body::-webkit-scrollbar-thumb{background:#7d87964d;border-radius:8px;border:2px solid transparent;background-clip:padding-box}.terms-gate__body::-webkit-scrollbar-thumb:hover{background:#7d87968c;background-clip:padding-box;border:2px solid transparent}.terms-gate--review{padding:24px}.terms-gate--review .glow{display:none}.terms-gate--review .terms-gate__panel{width:min(640px,92vw);max-height:min(82vh,760px);background:#12161efa;box-shadow:0 28px 80px #0009;animation:terms-pop .16s ease}@keyframes terms-pop{0%{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:none}}.terms-md{font-size:13px;line-height:1.65;color:var(--text-dim, #c2cbd6);word-break:break-word}.terms-md>:first-child{margin-top:0}.terms-md h1{font-size:17px;font-weight:700;color:var(--text, #e6edf3);margin:0 0 6px}.terms-md h2{font-size:15px;font-weight:700;color:var(--text, #e6edf3);margin:22px 0 8px;padding-top:14px;border-top:1px solid rgba(125,135,150,.12)}.terms-md h3{font-size:13.5px;font-weight:600;color:var(--text, #e6edf3);margin:16px 0 6px}.terms-md p{margin:8px 0}.terms-md strong{color:var(--text, #e6edf3);font-weight:600}.terms-md code{font-family:var(--mono);font-size:12px;background:#7d879629;padding:1px 5px;border-radius:4px;color:#d7dee8}.terms-md ul,.terms-md ol{margin:8px 0;padding-left:22px}.terms-md li{margin:4px 0}.terms-md hr{border:none;border-top:1px solid rgba(125,135,150,.14);margin:18px 0}.terms-md blockquote{margin:10px 0;padding:8px 14px;border-left:3px solid rgba(91,141,247,.55);background:#5b8df712;border-radius:0 8px 8px 0;color:var(--text-dim, #b9c2cf)}.terms-md table{width:100%;border-collapse:collapse;margin:10px 0;font-size:12px;display:block;overflow-x:auto}.terms-md th,.terms-md td{border:1px solid rgba(125,135,150,.18);padding:7px 10px;text-align:left;vertical-align:top}.terms-md th{background:#7d87961a;color:var(--text, #e6edf3);font-weight:600;white-space:nowrap}.terms-gate__scrollhint{font-size:12px;color:#fbbf24;text-align:center;margin:12px 0 0}.terms-gate__actions{display:flex;gap:12px;justify-content:flex-end;margin-top:18px}.terms-gate__btn{font-size:14px;padding:10px 22px;border-radius:9px;border:none;cursor:pointer;background:var(--accent, #3b82f6);color:#fff;font-weight:600}.terms-gate__btn:disabled{opacity:.45;cursor:not-allowed}.terms-gate__btn--ghost{background:transparent;border:1px solid rgba(125,135,150,.35);color:var(--text-dim, #9da7b3);font-weight:500}
|