@polderlabs/bizar 2.4.0 → 2.6.1

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.
Files changed (43) hide show
  1. package/cli/bin.mjs +73 -0
  2. package/cli/copy.mjs +39 -34
  3. package/cli/dashboard/api.mjs +473 -0
  4. package/cli/dashboard/browser.mjs +40 -0
  5. package/cli/dashboard/server.mjs +366 -0
  6. package/cli/dashboard/state.mjs +438 -0
  7. package/cli/dashboard/tasks-store.mjs +203 -0
  8. package/cli/dashboard/watcher.mjs +81 -0
  9. package/cli/dashboard.mjs +97 -0
  10. package/config/commands/bizar.md +13 -39
  11. package/dist/assets/index-BVvY22Gt.css +1 -0
  12. package/dist/assets/index-CO3c8O32.js +285 -0
  13. package/dist/assets/index-CO3c8O32.js.map +1 -0
  14. package/dist/index.html +18 -0
  15. package/package.json +26 -2
  16. package/src/App.tsx +233 -0
  17. package/src/components/Button.tsx +55 -0
  18. package/src/components/Card.tsx +40 -0
  19. package/src/components/EmptyState.tsx +30 -0
  20. package/src/components/Modal.tsx +137 -0
  21. package/src/components/Spinner.tsx +19 -0
  22. package/src/components/StatusBadge.tsx +25 -0
  23. package/src/components/Tag.tsx +28 -0
  24. package/src/components/Toast.tsx +142 -0
  25. package/src/components/Topbar.tsx +88 -0
  26. package/src/index.html +17 -0
  27. package/src/lib/api.ts +71 -0
  28. package/src/lib/markdown.tsx +59 -0
  29. package/src/lib/types.ts +200 -0
  30. package/src/lib/utils.ts +79 -0
  31. package/src/lib/ws.ts +132 -0
  32. package/src/main.tsx +12 -0
  33. package/src/styles/main.css +2324 -0
  34. package/src/views/Agents.tsx +199 -0
  35. package/src/views/Chat.tsx +255 -0
  36. package/src/views/Config.tsx +250 -0
  37. package/src/views/Overview.tsx +267 -0
  38. package/src/views/Plans.tsx +667 -0
  39. package/src/views/Projects.tsx +155 -0
  40. package/src/views/Settings.tsx +253 -0
  41. package/src/views/Tasks.tsx +567 -0
  42. package/tsconfig.json +23 -0
  43. package/vite.config.ts +24 -0
@@ -0,0 +1,81 @@
1
+ /**
2
+ * cli/dashboard/watcher.mjs
3
+ *
4
+ * chokidar-backed file watcher. Translates low-level fs events into the
5
+ * shape the dashboard's WebSocket layer expects.
6
+ *
7
+ * The watcher ignores initial add events (the UI doesn't need a "you just
8
+ * started, here are 200 files that already existed" flood on connect).
9
+ */
10
+ import chokidar from 'chokidar';
11
+
12
+ /**
13
+ * @param {object} opts
14
+ * @param {string[]} opts.paths - files or directories to watch
15
+ * @param {(event: 'add'|'change'|'unlink', path: string) => void} opts.onChange
16
+ * @param {object} [opts.options] - extra chokidar options
17
+ */
18
+ export function createWatcher({ paths, onChange, options = {} }) {
19
+ if (!Array.isArray(paths) || paths.length === 0) {
20
+ throw new Error('createWatcher requires a non-empty paths array');
21
+ }
22
+ if (typeof onChange !== 'function') {
23
+ throw new Error('createWatcher requires an onChange callback');
24
+ }
25
+
26
+ const watcher = chokidar.watch(paths, {
27
+ ignoreInitial: true,
28
+ persistent: true,
29
+ awaitWriteFinish: { stabilityThreshold: 100, pollInterval: 50 },
30
+ // Ignore: any path segment named `node_modules` (anywhere), and any
31
+ // file/dir whose IMMEDIATE basename starts with `.` (covers .DS_Store,
32
+ // .swp, .bak, etc.). We must NOT walk the whole path — the watched
33
+ // root `~/.config/opencode/agents` contains the segment `.config`
34
+ // which would otherwise match and silently disable the watch.
35
+ ignored: (p) => {
36
+ const s = String(p);
37
+ const parts = s.split(/[\\/]/);
38
+ // Walk all segments — `node_modules` is fine to match anywhere.
39
+ if (parts.includes('node_modules')) return true;
40
+ // Last segment is the basename — check that ONLY, so `.config`
41
+ // in parent dirs doesn't disqualify the watched root.
42
+ const basename = parts[parts.length - 1] || '';
43
+ return basename.startsWith('.');
44
+ },
45
+ ...options,
46
+ });
47
+
48
+ const safe = (event, p) => {
49
+ try {
50
+ onChange(event, p);
51
+ } catch (err) {
52
+ // A faulty onChange must not crash the watcher
53
+ console.error('[dashboard watcher] onChange error:', err);
54
+ }
55
+ };
56
+
57
+ watcher.on('add', (p) => safe('add', p));
58
+ watcher.on('change', (p) => safe('change', p));
59
+ watcher.on('unlink', (p) => safe('unlink', p));
60
+ watcher.on('error', (err) => {
61
+ console.error('[dashboard watcher] chokidar error:', err);
62
+ });
63
+
64
+ return {
65
+ /** @returns {chokidar.FSWatcher} */
66
+ start() {
67
+ return watcher;
68
+ },
69
+ async stop() {
70
+ try {
71
+ await watcher.close();
72
+ } catch {
73
+ /* ignore */
74
+ }
75
+ },
76
+ /** Force a synthetic broadcast — useful after a self-mutation. */
77
+ poke(event = 'change', path = '<synthetic>') {
78
+ safe(event, path);
79
+ },
80
+ };
81
+ }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * cli/dashboard.mjs
3
+ *
4
+ * v2.5.0 — Dashboard launcher.
5
+ *
6
+ * Picks a free port (preferred: 4321), starts an Express + WebSocket server,
7
+ * writes port + PID files under ~/.config/bizar/, and opens the user's
8
+ * default browser. The server is created and returned; the caller decides
9
+ * whether to keep the process alive.
10
+ *
11
+ * Returns: { url, port, close }
12
+ */
13
+ import { createServer } from './dashboard/server.mjs';
14
+ import { launchBrowser } from './dashboard/browser.mjs';
15
+ import { writeFileSync, mkdirSync } from 'node:fs';
16
+ import { join } from 'node:path';
17
+ import { homedir } from 'node:os';
18
+ import net from 'node:net';
19
+
20
+ const DEFAULT_PORT = 4321;
21
+ const BIZAR_HOME = join(homedir(), '.config', 'bizar');
22
+ const PORT_FILE = join(BIZAR_HOME, 'dashboard.port');
23
+ const PID_FILE = join(BIZAR_HOME, 'dashboard.pid');
24
+
25
+ export async function launchDashboard(options = {}) {
26
+ // 1. Find a free port
27
+ const port = await findFreePort(options.port || DEFAULT_PORT);
28
+
29
+ // 2. Create the server (does not listen yet)
30
+ const { server, wss, close } = createServer({
31
+ port,
32
+ projectRoot: options.projectRoot || process.cwd(),
33
+ opencodeConfigDir:
34
+ options.opencodeConfigDir || join(homedir(), '.config', 'opencode'),
35
+ bizarRoot: options.bizarRoot || new URL('../..', import.meta.url).pathname,
36
+ });
37
+
38
+ // 3. Start listening on loopback only
39
+ await new Promise((resolve, reject) => {
40
+ server.once('error', reject);
41
+ server.listen(port, '127.0.0.1', () => {
42
+ server.off('error', reject);
43
+ resolve();
44
+ });
45
+ });
46
+
47
+ // 4. Persist port + PID so the CLI subcommand can find/stop us
48
+ mkdirSync(BIZAR_HOME, { recursive: true });
49
+ writeFileSync(PORT_FILE, String(port), 'utf8');
50
+ writeFileSync(PID_FILE, String(process.pid), 'utf8');
51
+
52
+ // 5. Open the browser (best effort — non-fatal)
53
+ const url = `http://localhost:${port}/`;
54
+ await launchBrowser(url);
55
+
56
+ // 6. Friendly log
57
+ console.log(`Bizar dashboard: ${url}`);
58
+
59
+ return {
60
+ url,
61
+ port,
62
+ close,
63
+ wss,
64
+ };
65
+ }
66
+
67
+ /**
68
+ * Try the preferred port first, then walk upward up to 100 slots. If still
69
+ * no luck, surface an error so the caller can decide what to do.
70
+ */
71
+ async function findFreePort(preferred) {
72
+ for (let p = preferred; p < preferred + 100; p++) {
73
+ if (await isPortFree(p)) return p;
74
+ }
75
+ throw new Error(
76
+ `No free port found in range ${preferred}..${preferred + 99}`,
77
+ );
78
+ }
79
+
80
+ function isPortFree(port) {
81
+ return new Promise((resolve) => {
82
+ const server = net.createServer();
83
+ let settled = false;
84
+ const finish = (ok) => {
85
+ if (settled) return;
86
+ settled = true;
87
+ resolve(ok);
88
+ };
89
+ server.once('error', () => finish(false));
90
+ server.once('listening', () => server.close(() => finish(true)));
91
+ // Defensive timeout — don't hang on a wedged port
92
+ const timer = setTimeout(() => finish(false), 1000);
93
+ server.listen(port, '127.0.0.1', () => clearTimeout(timer));
94
+ });
95
+ }
96
+
97
+ export { PORT_FILE, PID_FILE, DEFAULT_PORT };
@@ -1,44 +1,18 @@
1
- # Bizar Plugin Menu
1
+ # Bizar Dashboard
2
2
 
3
- You are @odin, the routing agent. The user invoked /bizar. They wrote: $ARGUMENTS
3
+ The `/bizar` command launches the Bizar dashboard in your browser — a fully integrated workspace with Overview, Chat, Agents, Plans, Projects, Config, and Settings panels. The dashboard binds to `127.0.0.1` only and runs as a local Express + WebSocket server on a free port (preferred: 4321).
4
4
 
5
- Based on their request, route them to the right Bizar action.
5
+ If the user invoked `/bizar` with arguments, treat them as a request and route appropriately:
6
6
 
7
- ## Available commands
7
+ - "explain X" → invoke `/explain X`
8
+ - "plan Y" → invoke `/visual-plan on` and then `/plan new <slug>` with the user's intent as the slug
9
+ - "review PR" → invoke `/pr-review`
10
+ - "audit" → invoke `/audit`
11
+ - "learn" → invoke `/learn`
12
+ - "init" → invoke `/init`
13
+ - "dashboard" or "open dashboard" → `/bizar` (no args, will launch the dashboard)
14
+ - Otherwise: ask one clarifying question
8
15
 
9
- - `/visual-plan on|off|status` Toggle the Bizar visual plan canvas
10
- - `/plan new <slug> [template]` — Create a new visual plan
11
- - `/plan list` — List existing plans
12
- - `/plan open <slug>` — Open a plan
13
- - `/plan get <slug>` — Get plan content
14
- - `/plan add <slug> --title "..."` — Add element to plan
15
- - `/plan update <slug> <id> ...` — Update element
16
- - `/plan delete <slug> <id>` — Delete element
17
- - `/plan comment <slug> [id] "..."` — Add comment
18
- - `/plan comments <slug> [id]` — List comments
19
- - `/plan status <slug> <status>` — Set plan status
20
- - `/plan wait <slug>` — Wait for plan feedback
21
- - `/audit` — Run a security audit
22
- - `/explain <question>` — Read-only Q&A (routes to @frigg)
23
- - `/init` — Initialize Bizar in the current project
24
- - `/learn` — Extract patterns from the session (routes to @heimdall)
25
- - `/pr-review` — Run a PR review with @mimir + @forseti (routes to @hermod)
26
- - `/tailscale-serve` — Set up Tailscale Serve
16
+ If the user invoked `/bizar` with no arguments, the dashboard is launching in the background. Visit `http://localhost:<port>/` to access it. The plugin's `chat.message` hook spawns `bizar dashboard start` as a detached child process and surfaces the live URL in its response.
27
17
 
28
- ## Routing rules
29
-
30
- 1. If the user wants to read code or understand something without changes → invoke `/explain` or answer as @frigg
31
- 2. If the user wants to plan work visually → `/visual-plan on` then `/plan new <slug>`
32
- 3. If the user wants to do a security audit → `/audit`
33
- 4. If the user wants to review a PR → `/pr-review`
34
- 5. If the user wants to learn patterns from a session → `/learn`
35
- 6. If the user wants to initialize Bizar → `/init`
36
- 7. Otherwise, ask a clarifying question and route to the appropriate sub-agent
37
-
38
- ## Response format
39
-
40
- Briefly explain what you'll do, then either:
41
- - Run the appropriate slash command, OR
42
- - Ask one clarifying question if the request is ambiguous
43
-
44
- Never make changes to the codebase. You are a router, not an executor.
18
+ Common ports: 4321 is preferred; if it's taken, the launcher walks upward and picks the next free port. The PID and port are recorded under `~/.config/bizar/dashboard.{pid,port}` so `bizar dashboard stop` and `bizar dashboard status` can find the running instance.
@@ -0,0 +1 @@
1
+ *,*:before,*:after{box-sizing:border-box}html,body,#root{margin:0;padding:0;height:100%}body{font-family:Inter var,Inter,system-ui,-apple-system,Segoe UI,Roboto,Helvetica Neue,sans-serif;font-feature-settings:"cv02","cv03","cv04","cv11";font-size:14px;line-height:1.5;background:var(--bg);color:var(--text);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}button,input,textarea,select{font-family:inherit;font-size:inherit;color:inherit}a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline}code,pre,.mono{font-family:var(--mono)}::selection{background:var(--accent-bg);color:var(--accent-2)}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--border);border-radius:6px;border:2px solid var(--bg)}::-webkit-scrollbar-thumb:hover{background:var(--border-strong)}:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:4px}:root{--bg: #0b0e14;--bg-elev: #12161f;--bg-elev-2: #1a1f2b;--bg-elev-3: #232a39;--border: #232a39;--border-strong: #2d3648;--text: #c9d1d9;--text-dim: #8b95a8;--text-strong: #f0f6fc;--accent: #8b5cf6;--accent-2: #a78bfa;--accent-3: #c4b5fd;--accent-bg: rgba(139, 92, 246, .12);--accent-border: rgba(139, 92, 246, .4);--success: #34d399;--warning: #fbbf24;--error: #f87171;--info: #60a5fa;--syntax-key: #79c0ff;--syntax-string: #a5d6ff;--syntax-number: #ffa657;--syntax-boolean: #ff7b72;--syntax-null: #ff7b72;--font-mono: "JetBrains Mono", "Fira Code", "SF Mono", "Cascadia Code", Consolas, monospace;--font-sans: "Inter var", "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;--space-1: 4px;--space-2: 8px;--space-3: 12px;--space-4: 16px;--space-5: 20px;--space-6: 24px;--space-8: 32px;--space-10: 40px;--space-12: 48px;--radius-sm: 4px;--radius: 8px;--radius-md: 10px;--radius-lg: 12px;--radius-xl: 16px;--shadow-1: 0 1px 2px rgba(0, 0, 0, .4);--shadow-2: 0 4px 12px rgba(0, 0, 0, .45);--shadow-3: 0 12px 32px rgba(0, 0, 0, .55);--shadow-glow: 0 0 0 1px var(--accent-border), 0 8px 32px rgba(139, 92, 246, .15);--motion-fast: .12s;--motion-base: .18s;--motion-slow: .28s;--ease: cubic-bezier(.4, 0, .2, 1);color-scheme:dark}[data-theme=light]{--bg: #f7f8fa;--bg-elev: #ffffff;--bg-elev-2: #f0f3f8;--bg-elev-3: #e6ebf2;--border: #e2e8f0;--border-strong: #cbd5e1;--text: #1f2937;--text-dim: #64748b;--text-strong: #0f172a;--accent: #7c3aed;--accent-2: #6d28d9;--accent-3: #5b21b6;--accent-bg: rgba(124, 58, 237, .08);--accent-border: rgba(124, 58, 237, .3);--success: #059669;--warning: #d97706;--error: #dc2626;--info: #2563eb;--syntax-key: #0969da;--syntax-string: #0a3069;--syntax-number: #953800;--syntax-boolean: #cf222e;--syntax-null: #cf222e;--shadow-1: 0 1px 2px rgba(15, 23, 42, .06);--shadow-2: 0 4px 12px rgba(15, 23, 42, .08);--shadow-3: 0 12px 32px rgba(15, 23, 42, .12);color-scheme:light}.app{display:flex;flex-direction:column;height:100vh;background:radial-gradient(circle at 0% 0%,var(--accent-bg),transparent 50%),var(--bg);background-attachment:fixed}.content{flex:1;overflow:auto;padding:var(--space-6);position:relative}.view{max-width:1400px;margin:0 auto;display:flex;flex-direction:column;gap:var(--space-5);animation:view-in var(--motion-slow) var(--ease)}@keyframes view-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}.view-loading{display:flex;flex-direction:column;gap:var(--space-3);align-items:center;justify-content:center;min-height:60vh;color:var(--text-dim)}.loading{display:flex;flex-direction:column;gap:var(--space-3);align-items:center;justify-content:center;min-height:100vh;color:var(--text-dim)}.boot-error{max-width:560px;margin:var(--space-12) auto;padding:var(--space-6);background:var(--bg-elev);border:1px solid var(--error);border-radius:var(--radius-lg);box-shadow:var(--shadow-2)}.boot-error h2{margin:0 0 var(--space-3);color:var(--error)}.boot-error code{background:var(--bg);padding:2px 6px;border-radius:var(--radius-sm);font-size:12px}.topbar{display:flex;align-items:center;height:56px;flex-shrink:0;background:color-mix(in srgb,var(--bg-elev) 92%,transparent);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-bottom:1px solid var(--border);padding:0 var(--space-5);gap:var(--space-5);position:sticky;top:0;z-index:10}.brand{display:flex;align-items:center;gap:var(--space-2);-webkit-user-select:none;user-select:none}.brand-logo{font-size:22px;line-height:1;filter:drop-shadow(0 0 12px rgba(139,92,246,.4))}.brand-title{font-weight:600;font-size:15px;letter-spacing:-.01em;color:var(--text-strong)}.brand-version{font-family:var(--font-mono);font-size:10px;color:var(--text-dim);padding:2px 7px;background:var(--bg-elev-2);border:1px solid var(--border);border-radius:999px;font-weight:500}.tabs{display:flex;gap:2px;flex:1;overflow-x:auto;scrollbar-width:none}.tabs::-webkit-scrollbar{display:none}.tab{display:inline-flex;align-items:center;gap:6px;background:transparent;border:1px solid transparent;color:var(--text-dim);padding:6px 12px;border-radius:999px;cursor:pointer;font-size:13px;font-weight:500;white-space:nowrap;transition:background var(--motion-base) var(--ease),color var(--motion-base) var(--ease),border-color var(--motion-base) var(--ease),transform var(--motion-fast) var(--ease)}.tab:hover{color:var(--text);background:var(--bg-elev-2)}.tab:active{transform:scale(.98)}.tab-active{color:var(--accent-3);background:var(--accent-bg);border-color:var(--accent-border)}.tab-icon{flex-shrink:0}.topbar-right{display:flex;align-items:center;gap:var(--space-3)}.ws-status{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-family:var(--font-mono);color:var(--text-dim);padding:4px 10px;border-radius:999px;background:var(--bg-elev-2);border:1px solid var(--border);text-transform:capitalize}.ws-dot{width:8px;height:8px;border-radius:50%;background:var(--text-dim);position:relative}.ws-connected .ws-dot{background:var(--success);box-shadow:0 0 0 3px #34d39926}.ws-connecting .ws-dot{background:var(--warning);animation:pulse 1.4s ease-in-out infinite}.ws-disconnected .ws-dot{background:var(--error)}@keyframes pulse{0%,to{opacity:1}50%{opacity:.4}}.view-header{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-4);flex-wrap:wrap}.view-header-text{display:flex;flex-direction:column;gap:4px;min-width:0}.view-title{display:inline-flex;align-items:center;gap:var(--space-2);font-size:22px;font-weight:700;letter-spacing:-.01em;color:var(--text-strong);margin:0}.view-subtitle{font-size:13px;color:var(--text-dim);margin:0}.view-actions{display:inline-flex;align-items:center;gap:var(--space-2);flex-wrap:wrap}.card{background:var(--bg-elev);border:1px solid var(--border);border-radius:var(--radius-lg);padding:var(--space-4) var(--space-5);display:flex;flex-direction:column;gap:var(--space-3);transition:border-color var(--motion-base) var(--ease),transform var(--motion-base) var(--ease),box-shadow var(--motion-base) var(--ease)}.card-elevated{background:var(--bg-elev)}.card-outlined{background:transparent}.card-filled{background:var(--bg-elev-2);border-color:var(--border-strong)}.card-interactive{cursor:pointer}.card-interactive:hover{border-color:var(--border-strong);transform:translateY(-1px);box-shadow:var(--shadow-2)}.card-title{display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:600;color:var(--text-strong);margin:0;letter-spacing:-.005em}.card-meta{font-size:12px;color:var(--text-dim)}.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;border-radius:var(--radius);cursor:pointer;font-weight:500;white-space:nowrap;transition:background var(--motion-fast) var(--ease),border-color var(--motion-fast) var(--ease),color var(--motion-fast) var(--ease),transform var(--motion-fast) var(--ease),box-shadow var(--motion-fast) var(--ease)}.btn:active:not(:disabled){transform:scale(.97)}.btn:disabled{opacity:.55;cursor:not-allowed}.btn-size-sm{padding:4px 10px;font-size:12px}.btn-size-md{padding:7px 14px;font-size:13px}.btn-size-lg{padding:10px 18px;font-size:14px}.btn-icon{padding:6px;width:30px;height:30px}.btn-primary{background:var(--accent);color:#fff;border:1px solid var(--accent)}.btn-primary:hover:not(:disabled){background:var(--accent-2);border-color:var(--accent-2)}.btn-accent{background:var(--accent-bg);color:var(--accent-2);border:1px solid var(--accent-border)}.btn-secondary{background:var(--bg-elev-2);color:var(--text);border:1px solid var(--border)}.btn-secondary:hover:not(:disabled){border-color:var(--border-strong);background:var(--bg-elev-3)}.btn-ghost{background:transparent;color:var(--text-dim);border:1px solid transparent}.btn-ghost:hover:not(:disabled){background:var(--bg-elev-2);color:var(--text)}.btn-danger{background:transparent;color:var(--error);border:1px solid var(--error)}.btn-danger:hover:not(:disabled){background:#f871711f}.btn-loading{pointer-events:none}.btn-spinner{width:12px;height:12px;border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:spin .7s linear infinite}.hint-key{opacity:.7;margin-left:2px}.icon-btn{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;border-radius:var(--radius-sm);background:transparent;color:var(--text-dim);border:1px solid transparent;cursor:pointer;transition:all var(--motion-fast) var(--ease)}.icon-btn:hover{background:var(--bg-elev-2);color:var(--text);border-color:var(--border)}.icon-btn-danger:hover{background:#f871711f;color:var(--error);border-color:var(--error)}.w-full{width:100%}.input,.textarea,.select{background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:var(--radius);padding:7px 12px;width:100%;font-size:13px;transition:border-color var(--motion-fast) var(--ease),box-shadow var(--motion-fast) var(--ease)}.textarea{resize:vertical;min-height:80px;font-family:var(--font-mono);font-size:12px;line-height:1.55}.select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'><path fill='%238b95a8' d='M2 4l4 4 4-4z'/></svg>");background-repeat:no-repeat;background-position:right 10px center;padding-right:30px}[data-theme=light] .select{background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'><path fill='%2364748b' d='M2 4l4 4 4-4z'/></svg>")}.select-sm{padding:4px 28px 4px 10px;font-size:12px;height:30px}.input:focus,.textarea:focus,.select:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-bg)}.textarea.invalid{border-color:var(--error)}.field{display:flex;flex-direction:column;gap:var(--space-2);margin-bottom:var(--space-4)}.field-label{font-size:12px;font-weight:500;color:var(--text-dim);letter-spacing:.01em}.field-help{font-size:11px;color:var(--text-dim)}.checkbox-row{display:flex;align-items:center;gap:var(--space-2);padding:6px 0;font-size:13px;cursor:pointer;color:var(--text)}.checkbox-row input{width:auto;cursor:pointer;accent-color:var(--accent)}.radio-row{display:flex;gap:var(--space-3)}.radio-label{display:inline-flex;align-items:center;gap:4px;font-size:13px;cursor:pointer}.radio-label input{width:auto;accent-color:var(--accent)}.capitalize{text-transform:capitalize}.tabular-nums{font-variant-numeric:tabular-nums}.text-error{color:var(--error)}.muted{color:var(--text-dim)}.text-sm{font-size:12px}.ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.badge{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:999px;font-size:10px;font-family:var(--font-mono);font-weight:500;background:var(--bg-elev-2);color:var(--text-dim);border:1px solid var(--border);text-transform:uppercase;letter-spacing:.04em}.badge-dot:before{content:"";display:inline-block;width:6px;height:6px;border-radius:50%;background:currentColor}.badge-success{color:var(--success);border-color:#34d39966}.badge-warning{color:var(--warning);border-color:#fbbf2466}.badge-error{color:var(--error);border-color:#f8717166}.badge-info{color:var(--info);border-color:#60a5fa66}.badge-accent{color:var(--accent-2);border-color:var(--accent-border)}.badge-neutral{color:var(--text-dim)}.tag{display:inline-flex;align-items:center;gap:4px;padding:1px 8px;border-radius:999px;font-size:10px;font-family:var(--font-mono);background:var(--accent-bg);color:var(--accent-2);border:1px solid var(--accent-border)}.tag-remove{background:transparent;border:none;color:inherit;cursor:pointer;padding:0 0 0 2px;font-size:12px;line-height:1;opacity:.7}.tag-remove:hover{opacity:1}.spinner{display:inline-block;border:2px solid var(--border);border-top-color:var(--accent);border-radius:50%;animation:spin .7s linear infinite}.spinner-sm{width:12px;height:12px}.spinner-md{width:18px;height:18px}.spinner-lg{width:32px;height:32px;border-width:3px}@keyframes spin{to{transform:rotate(360deg)}}.stat-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--space-4)}@media (max-width: 1100px){.stat-grid{grid-template-columns:repeat(2,1fr)}}@media (max-width: 600px){.stat-grid{grid-template-columns:1fr}}.stat-card{flex-direction:row;align-items:center;gap:var(--space-4);padding:var(--space-4) var(--space-5)}.stat-card-icon{width:40px;height:40px;border-radius:var(--radius);background:var(--accent-bg);color:var(--accent-2);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.stat-card-body{flex:1;display:flex;flex-direction:column;gap:2px;min-width:0}.stat-card-value{font-size:26px;font-weight:700;color:var(--text-strong);letter-spacing:-.02em;line-height:1.05}.stat-card-label{font-size:11px;color:var(--text-dim);text-transform:uppercase;letter-spacing:.06em}.stat-card-arrow{color:var(--text-dim);font-size:18px;transition:transform var(--motion-base) var(--ease)}.stat-card:hover .stat-card-arrow{transform:translate(2px);color:var(--accent-2)}.quick-actions{gap:var(--space-3)}.quick-actions-row{display:flex;flex-wrap:wrap;gap:var(--space-2)}.overview-cols{display:grid;grid-template-columns:1.4fr 1fr;gap:var(--space-4)}@media (max-width: 1000px){.overview-cols{grid-template-columns:1fr}}.activity-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px;max-height:360px;overflow-y:auto}.activity-item{display:grid;grid-template-columns:60px 130px 1fr;gap:var(--space-3);padding:8px var(--space-2);font-size:12px;border-radius:var(--radius-sm);font-family:var(--font-mono);border-left:2px solid var(--border);align-items:baseline}.activity-item:hover{background:var(--bg-elev-2)}.activity-ts{color:var(--text-dim);white-space:nowrap}.activity-kind{color:var(--accent-2)}.activity-msg{color:var(--text);word-break:break-word;overflow:hidden;text-overflow:ellipsis}.env-table,.about-table{display:grid;grid-template-columns:max-content 1fr;gap:6px var(--space-4);margin:0;font-size:13px}.env-table dt,.about-table dt{color:var(--text-dim);font-size:12px}.env-table dd,.about-table dd{margin:0;color:var(--text)}.overview-footer{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--text-dim);padding-top:var(--space-3);border-top:1px solid var(--border)}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-2);padding:var(--space-8) var(--space-4);text-align:center;color:var(--text-dim)}.empty-icon{color:var(--text-dim);opacity:.7}.empty-title{font-weight:600;color:var(--text);font-size:15px;margin-top:var(--space-2)}.empty-message{font-size:13px;max-width:420px}.empty-action{margin-top:var(--space-3)}.chat-container{display:flex;flex-direction:column;gap:var(--space-3);flex:1;min-height:0}.chat-list{flex:1;min-height:400px;max-height:calc(100vh - 280px);overflow-y:auto;padding:var(--space-3);background:var(--bg-elev);border:1px solid var(--border);border-radius:var(--radius-lg);display:flex;flex-direction:column;gap:var(--space-3)}.chat-msg{background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-3) var(--space-4);max-width:85%;animation:msg-in var(--motion-base) var(--ease)}@keyframes msg-in{0%{opacity:0;transform:translateY(2px)}to{opacity:1;transform:none}}.chat-msg-user{align-self:flex-end;background:var(--accent-bg);border-color:var(--accent-border)}.chat-msg-assistant{align-self:flex-start}.chat-msg-system{align-self:center;max-width:100%;font-size:12px;color:var(--text-dim);border-style:dashed}.chat-msg-meta{display:flex;align-items:baseline;gap:var(--space-2);margin-bottom:6px;font-size:11px;font-family:var(--font-mono);color:var(--text-dim)}.chat-msg-role{text-transform:uppercase;font-weight:600;color:var(--accent-2);letter-spacing:.04em}.chat-msg-agent{color:var(--info)}.chat-msg-ts{margin-left:auto}.chat-msg-body{font-size:13px;line-height:1.6;word-break:break-word}.chat-msg-body p{margin:0 0 var(--space-2)}.chat-msg-body p:last-child{margin-bottom:0}.chat-msg-body code{font-family:var(--font-mono);background:var(--bg);padding:1px 6px;border-radius:var(--radius-sm);font-size:12px;border:1px solid var(--border)}.chat-msg-body pre{background:var(--bg);padding:var(--space-3);border-radius:var(--radius);overflow-x:auto;border:1px solid var(--border);font-size:12px}.chat-msg-body pre code{background:transparent;border:none;padding:0}.chat-msg-body a{color:var(--accent-2)}.chat-msg-body ul,.chat-msg-body ol{margin:0 0 var(--space-2);padding-left:var(--space-5)}.chat-msg-body blockquote{border-left:3px solid var(--accent-border);padding-left:var(--space-3);color:var(--text-dim);margin:0 0 var(--space-2)}.chat-composer{display:flex;flex-direction:column;gap:var(--space-2)}.chat-composer-row{display:flex;gap:var(--space-2);align-items:flex-end}.chat-composer-row .chat-input{flex:1;min-height:60px;max-height:200px}.chat-suggestions{display:flex;flex-direction:column;gap:2px;padding:var(--space-2);background:var(--bg-elev);border:1px solid var(--border);border-radius:var(--radius);max-height:200px;overflow-y:auto}.chat-suggestion{display:flex;align-items:baseline;gap:var(--space-2);background:transparent;border:1px solid transparent;color:var(--text);padding:6px var(--space-2);border-radius:var(--radius-sm);text-align:left;cursor:pointer;font-size:12px;transition:background var(--motion-fast) var(--ease)}.chat-suggestion:hover{background:var(--bg-elev-2)}.chat-suggestion-desc{color:var(--text-dim);font-size:11px}.agent-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-4)}@media (max-width: 1100px){.agent-grid{grid-template-columns:repeat(2,1fr)}}@media (max-width: 700px){.agent-grid{grid-template-columns:1fr}}.agent-card{gap:var(--space-2)}.agent-card-head{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2)}.agent-card-name{font-weight:600;font-family:var(--font-mono);color:var(--accent-2);font-size:15px}.agent-card-desc{font-size:12px;color:var(--text-dim);line-height:1.5;min-height:36px}.agent-card-meta{display:flex;justify-content:space-between;font-size:11px;font-family:var(--font-mono);color:var(--text-dim)}.agent-card-actions{display:flex;gap:var(--space-2);margin-top:var(--space-2)}.invoke-form{display:flex;flex-direction:column;gap:var(--space-3)}.invoke-form-meta{font-size:11px}.invoke-form-desc{margin:0;font-size:13px;color:var(--text-dim)}.new-plan-form{display:flex;gap:var(--space-2);align-items:center;flex-wrap:wrap}.new-plan-form .input{flex:1;min-width:200px}.plans-layout{display:grid;grid-template-columns:340px 1fr;gap:var(--space-4);min-height:500px}@media (max-width: 1000px){.plans-layout{grid-template-columns:1fr}}.plans-list-col{display:flex;flex-direction:column;gap:var(--space-3);max-height:calc(100vh - 280px);overflow-y:auto;padding-right:4px}.plans-canvas-col{display:flex;flex-direction:column;background:var(--bg-elev);border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden;min-height:500px}.plan-card{gap:var(--space-2)}.plan-card-selected{border-color:var(--accent);box-shadow:var(--shadow-glow)}.plan-card-head{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2)}.plan-card-title{font-weight:600;color:var(--text-strong);font-size:14px}.plan-card-slug,.plan-card-meta{font-size:11px;color:var(--text-dim)}.plan-card-actions{display:flex;gap:var(--space-2)}.plan-canvas{display:flex;flex-direction:column;flex:1;min-height:0}.plan-canvas-header{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--border);background:var(--bg-elev-2)}.plan-canvas-title{font-weight:600;font-size:14px;color:var(--text-strong)}.plan-canvas-meta{font-size:11px;color:var(--text-dim);margin-top:2px;font-family:var(--font-mono)}.plan-canvas-actions{display:flex;gap:var(--space-2)}.plan-canvas-area{flex:1;position:relative;overflow:hidden;background:var(--bg);min-height:360px}.canvas-root{position:absolute;top:0;right:0;bottom:0;left:0;cursor:grab;overflow:hidden}.canvas-grid-bg{position:absolute;top:-2000px;right:-2000px;bottom:-2000px;left:-2000px;background-image:radial-gradient(circle,var(--border) 1px,transparent 1px);background-size:24px 24px;background-position:2000px 2000px;opacity:.5;pointer-events:none}.canvas-inner{position:absolute;top:0;left:0;transform-origin:0 0}.canvas-element{position:absolute;background:var(--bg-elev);border:1px solid var(--border);border-radius:var(--radius);padding:var(--space-3);cursor:pointer;transition:border-color var(--motion-base) var(--ease),box-shadow var(--motion-base) var(--ease),transform var(--motion-fast) var(--ease);min-width:140px}.canvas-element:hover{border-color:var(--accent-border);transform:translateY(-1px);box-shadow:var(--shadow-2)}.canvas-element-selected{border-color:var(--accent);box-shadow:var(--shadow-glow)}.canvas-element-type{font-family:var(--font-mono);font-size:10px;color:var(--accent-2);text-transform:uppercase;letter-spacing:.05em;margin-bottom:4px}.canvas-element-title{font-weight:600;font-size:13px;color:var(--text-strong);margin-bottom:4px}.canvas-element-content{font-size:11px;color:var(--text-dim);line-height:1.5;white-space:pre-wrap;word-break:break-word}.canvas-connections{position:absolute;pointer-events:none;overflow:visible}.canvas-hint{position:absolute;bottom:var(--space-3);right:var(--space-3);font-size:11px;color:var(--text-dim);background:var(--bg-elev);border:1px solid var(--border);border-radius:var(--radius);padding:4px 8px;pointer-events:none}.plan-canvas-empty{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;align-items:center;justify-content:center;font-size:13px;color:var(--text-dim);text-align:center;padding:var(--space-6)}.plan-canvas-comments{border-top:1px solid var(--border);padding:var(--space-3) var(--space-4);background:var(--bg-elev-2);max-height:220px;overflow-y:auto}.plan-canvas-comments-title{display:flex;align-items:center;gap:6px;font-size:12px;font-weight:600;color:var(--text);margin:0 0 var(--space-2)}.comment-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--space-3)}.comment-item{padding:var(--space-2) var(--space-3);background:var(--bg-elev);border:1px solid var(--border);border-radius:var(--radius)}.comment-head{display:flex;align-items:baseline;gap:var(--space-2);margin-bottom:4px}.comment-author{font-size:11px;font-weight:600;color:var(--accent-2)}.comment-time{font-size:11px}.comment-text{font-size:12px;color:var(--text);line-height:1.5}.comment-thread{margin-top:var(--space-2);padding-left:var(--space-3);border-left:2px solid var(--border);display:flex;flex-direction:column;gap:4px}.comment-reply{display:flex;gap:var(--space-2);font-size:11px;align-items:baseline}.comment-reply-text{color:var(--text-dim)}.project-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--space-4)}@media (max-width: 900px){.project-grid{grid-template-columns:1fr}}.project-card{gap:var(--space-2)}.project-card-active{border-color:var(--accent);box-shadow:var(--shadow-glow)}.project-card-head{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2)}.project-card-path{font-size:11px;color:var(--text-dim);word-break:break-all}.project-card-actions{display:flex;gap:var(--space-2);margin-top:var(--space-2)}.search-input{position:relative;display:inline-flex;align-items:center}.search-input>svg{position:absolute;left:10px;color:var(--text-dim)}.search-input .input{padding-left:32px;width:220px}.search-input>.icon-btn{position:absolute;right:4px;width:20px;height:20px}.kanban{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-4);align-items:start}@media (max-width: 900px){.kanban{grid-template-columns:1fr}}.kanban-column{background:var(--bg-elev);border:1px solid var(--border);border-radius:var(--radius-lg);display:flex;flex-direction:column;max-height:calc(100vh - 240px);transition:border-color var(--motion-base) var(--ease),background var(--motion-base) var(--ease)}.kanban-column-drop{border-color:var(--accent);background:var(--accent-bg)}.kanban-col-header{display:flex;align-items:center;justify-content:space-between;padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--border);flex-shrink:0}.kanban-col-count{font-size:11px;color:var(--text-dim);background:var(--bg);padding:2px 8px;border-radius:999px;border:1px solid var(--border);font-family:var(--font-mono)}.kanban-col-body{flex:1;overflow-y:auto;padding:var(--space-3);display:flex;flex-direction:column;gap:var(--space-2);min-height:120px}.kanban-empty{text-align:center;color:var(--text-dim);font-size:12px;padding:var(--space-5) 0}.kanban-col-footer{padding:var(--space-2) var(--space-3);border-top:1px solid var(--border);flex-shrink:0}.task-card{background:var(--bg);border:1px solid var(--border);border-radius:var(--radius);padding:var(--space-3);cursor:pointer;border-left:3px solid transparent;transition:border-color var(--motion-base) var(--ease),box-shadow var(--motion-base) var(--ease),transform var(--motion-fast) var(--ease),background var(--motion-base) var(--ease)}.task-card:hover{border-color:var(--border-strong);transform:translateY(-1px);box-shadow:var(--shadow-2)}.task-card-focused{outline:2px solid var(--accent);outline-offset:-2px}.task-card.priority-high{border-left-color:var(--error)}.task-card.priority-low{border-left-color:var(--text-dim)}.task-card.priority-normal{border-left-color:var(--info)}.task-card-head{display:flex;align-items:flex-start;gap:var(--space-2);margin-bottom:6px}.priority-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0;margin-top:6px}.task-card-title{font-weight:600;font-size:13px;color:var(--text-strong);flex:1;word-break:break-word;line-height:1.4}.task-card-desc{font-size:12px;color:var(--text-dim);line-height:1.5;margin-bottom:var(--space-2);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.task-card-tags{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:var(--space-2)}.task-card-footer{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2)}.task-card-time{font-size:10px;font-family:var(--font-mono)}.task-card-actions{display:inline-flex;gap:2px}.task-form{display:flex;flex-direction:column;gap:var(--space-2)}.task-form-row{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-3)}.task-form-field{display:flex;flex-direction:column;gap:var(--space-2)}@keyframes task-move{0%{background:var(--accent-bg)}to{background:transparent}}.config-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-4)}@media (max-width: 1000px){.config-grid{grid-template-columns:1fr}}.config-textarea{min-height:360px;font-family:var(--font-mono);font-size:12px;line-height:1.55;width:100%;white-space:pre}.config-textarea.invalid{border-color:var(--error)}.json-tree{font-family:var(--font-mono);font-size:12px;line-height:1.6;white-space:pre;overflow-x:auto;max-height:380px;overflow-y:auto;padding:var(--space-3);background:var(--bg);border:1px solid var(--border);border-radius:var(--radius)}.diff-card{gap:var(--space-2)}.diff-view{font-size:11px;line-height:1.5;max-height:300px;overflow-y:auto;padding:var(--space-3);background:var(--bg);border:1px solid var(--border);border-radius:var(--radius)}.diff-line{padding:0 var(--space-2);white-space:pre}.diff-line-removed{color:var(--error);background:#f8717114}.diff-line-added{color:var(--success);background:#34d39914}.settings-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-4)}@media (max-width: 900px){.settings-grid{grid-template-columns:1fr}}.theme-row{display:flex;gap:var(--space-2);flex-wrap:wrap}.theme-card{flex:1;min-width:100px;display:flex;flex-direction:column;align-items:center;gap:var(--space-2);padding:var(--space-3);background:var(--bg);border:1px solid var(--border);border-radius:var(--radius);cursor:pointer;color:var(--text-dim);transition:border-color var(--motion-base) var(--ease),background var(--motion-base) var(--ease),color var(--motion-base) var(--ease)}.theme-card:hover{border-color:var(--border-strong);color:var(--text)}.theme-card-active{border-color:var(--accent);background:var(--accent-bg);color:var(--accent-2)}.theme-card-label{font-size:12px;font-weight:500}.theme-card-swatch{width:100%;height:24px;border-radius:var(--radius-sm);border:1px solid var(--border)}.theme-card-swatch-dark{background:linear-gradient(135deg,#0b0e14,#1a1f2b)}.theme-card-swatch-light{background:linear-gradient(135deg,#f7f8fa,#e6ebf2)}.theme-card-swatch-system{background:linear-gradient(135deg,#0b0e14,#0b0e14 50%,#f7f8fa 50%,#f7f8fa)}.toast-stack{position:fixed;bottom:var(--space-5);right:var(--space-5);display:flex;flex-direction:column;gap:var(--space-2);z-index:1000;pointer-events:none;max-width:420px}.toast{display:inline-flex;align-items:center;gap:var(--space-2);background:var(--bg-elev);border:1px solid var(--border);border-left:3px solid var(--accent);border-radius:var(--radius);padding:10px 14px;box-shadow:var(--shadow-3);font-size:13px;pointer-events:auto;animation:toast-in var(--motion-slow) var(--ease);min-width:240px;color:var(--text)}.toast-icon{flex-shrink:0}.toast-message{flex:1;word-break:break-word}.toast-close{background:transparent;border:none;color:var(--text-dim);cursor:pointer;padding:2px;display:inline-flex}.toast-close:hover{color:var(--text)}.toast-success{border-left-color:var(--success)}.toast-success .toast-icon{color:var(--success)}.toast-error{border-left-color:var(--error)}.toast-error .toast-icon{color:var(--error)}.toast-warning{border-left-color:var(--warning)}.toast-warning .toast-icon{color:var(--warning)}.toast-info .toast-icon{color:var(--info)}@keyframes toast-in{0%{transform:translate(110%);opacity:0}to{transform:translate(0);opacity:1}}.modal-stack{position:fixed;top:0;right:0;bottom:0;left:0;z-index:999;pointer-events:none}.modal-backdrop{position:absolute;top:0;right:0;bottom:0;left:0;background:#0009;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;padding:var(--space-4);pointer-events:auto;animation:fade-in var(--motion-base) var(--ease)}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.modal{background:var(--bg-elev);border:1px solid var(--border);border-radius:var(--radius-lg);width:min(560px,100%);max-height:80vh;display:flex;flex-direction:column;box-shadow:var(--shadow-3);animation:modal-in var(--motion-slow) var(--ease);overflow:hidden}@keyframes modal-in{0%{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:none}}.modal-header{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);padding:var(--space-4) var(--space-5);border-bottom:1px solid var(--border)}.modal-title{font-size:16px;font-weight:600;margin:0;color:var(--text-strong)}.modal-body{flex:1;overflow-y:auto;padding:var(--space-5);font-size:13px;line-height:1.55}.modal-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-2);padding:var(--space-3) var(--space-5);border-top:1px solid var(--border);background:var(--bg-elev-2)}.modal-footer-actions{display:flex;gap:var(--space-2);justify-content:flex-end;width:100%}.code-block{background:var(--bg);padding:var(--space-3);border-radius:var(--radius);border:1px solid var(--border);font-size:12px;margin:var(--space-2) 0 0;overflow-x:auto}kbd{display:inline-flex;align-items:center;padding:1px 6px;border-radius:var(--radius-sm);background:var(--bg-elev-2);border:1px solid var(--border);border-bottom-width:2px;font-family:var(--font-mono);font-size:10px;color:var(--text-dim)}@media (max-width: 800px){.topbar{padding:0 var(--space-3);gap:var(--space-3)}.brand-version,.tab-label{display:none}.content{padding:var(--space-4)}.ws-status .ws-label{display:none}}