codebay 0.10.1 → 0.11.0

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 (101) hide show
  1. package/.mochi/manifest.json +199 -173
  2. package/.mochi/svelte-client/HydratableIsland-dammyce5.js +1 -0
  3. package/.mochi/svelte-client/_hydrate-AppShell_2rtnxn6pgp2rh-v65ctd99.js +2 -0
  4. package/.mochi/svelte-client/_hydrate-AvatarsView_257s9yq1wwr4f-htjfv8q9.js +14 -0
  5. package/.mochi/svelte-client/_hydrate-InstanceView_2ma45l9bybfhl-v07seqge.js +1 -0
  6. package/.mochi/svelte-client/_hydrate-SettingsView_8hmarwmf8onq-hj9yvqc4.js +38 -0
  7. package/.mochi/svelte-client/chunk-0zkdsrth.js +2 -0
  8. package/.mochi/svelte-client/{chunk-bn731rda.js → chunk-566rqq4c.js} +2 -2
  9. package/.mochi/svelte-client/chunk-79aj59e0.js +2 -0
  10. package/.mochi/svelte-client/{chunk-wvtkwfsh.js → chunk-czkxd74n.js} +1 -1
  11. package/.mochi/svelte-client/{chunk-p20tkpde.js → chunk-hxydjtda.js} +1 -1
  12. package/.mochi/svelte-client/chunk-qx1defbm.js +2 -0
  13. package/.mochi/svelte-client/chunk-r3wxmmc0.js +2 -0
  14. package/.mochi/svelte-client/{chunk-j72r8pkk.js → chunk-vs6pd2b4.js} +2 -2
  15. package/.mochi/svelte-client/{chunk-t0ap7q89.js → chunk-wjagstre.js} +1 -1
  16. package/.mochi/svelte-client/{chunk-0fjx3z3r.js → chunk-y9yy1004.js} +1 -1
  17. package/.mochi/svelte-compile/{App-59cdj86f.server.js → App-mzn3dqjm.server.js} +182 -72
  18. package/.mochi/svelte-compile/{Avatars-fmagfyj2.server.js → Avatars-c0k5jx8q.server.js} +3 -6
  19. package/.mochi/svelte-compile/{Instance-s1gqwzmx.server.js → Instance-hj76qnha.server.js} +4 -4
  20. package/.mochi/svelte-compile/{Settings-k447mt0x.server.js → Settings-tvc5yp08.server.js} +39 -28
  21. package/.mochi/svelte-compile/chunk-ed46m58e.js +22 -0
  22. package/.mochi/svelte-compile/{chunk-th2dbqvc.js → chunk-gz6hv1h5.js} +5 -1
  23. package/.mochi/svelte-compile/chunk-zd49axkf.js +65 -0
  24. package/.mochi/svelte-css/{AppBar-3bxinv4pabv8l.css → AppBar-1gtu2me3fni8e.css} +1 -1
  25. package/.mochi/svelte-css/AvatarEditor-1mjvec6bwdkv8.css +1 -0
  26. package/.mochi/svelte-css/{AvatarsView-2llo48w0wt0xn.css → AvatarsView-26ya4ep5n1ze7.css} +1 -1
  27. package/.mochi/svelte-css/Button-208u50wkms8ya.css +1 -0
  28. package/.mochi/svelte-css/CoinButton-2727devjtsn10.css +1 -0
  29. package/.mochi/svelte-css/CredMenu-7qowd1oxujet.css +1 -0
  30. package/.mochi/svelte-css/DashboardView-17a0b8epjurhb.css +1 -0
  31. package/.mochi/svelte-css/FolderBrowser-i0uj58dph27f.css +1 -0
  32. package/.mochi/svelte-css/HealthBox-r0giuhjn2wj4.css +1 -0
  33. package/.mochi/svelte-css/IdeBar-1mtgemqfuvqzi.css +1 -0
  34. package/.mochi/svelte-css/InstanceCard-25z7nas7y98zk.css +1 -0
  35. package/.mochi/svelte-css/InstanceFilter-2vglmyy0yrbbc.css +1 -0
  36. package/.mochi/svelte-css/InstanceView-oozmmctp8m3p.css +1 -0
  37. package/.mochi/svelte-css/SettingsCog-1jdeprd3ilczz.css +1 -0
  38. package/.mochi/svelte-css/{SettingsView-n3oy75uonzp2.css → SettingsView-bccw34agd2bj.css} +1 -1
  39. package/.mochi/svelte-css/StatusBadge-2eisdtnrsnfdc.css +1 -0
  40. package/.mochi/svelte-css/TerminalPane-2ywc86rhtmr9l.css +1 -0
  41. package/.mochi/svelte-css/ThemePicker-3fw4synubier0.css +1 -0
  42. package/migrations/0008_config_migrated.sql +1 -0
  43. package/package.json +8 -8
  44. package/src/components/AppBar.svelte +2 -2
  45. package/src/components/AppShell.svelte +71 -7
  46. package/src/components/AvatarEditor.svelte +10 -10
  47. package/src/components/AvatarsView.svelte +0 -0
  48. package/src/components/Button.svelte +13 -9
  49. package/src/components/CoinButton.svelte +2 -2
  50. package/src/components/CredMenu.svelte +8 -6
  51. package/src/components/DashboardView.svelte +2 -2
  52. package/src/components/FolderBrowser.svelte +39 -36
  53. package/src/components/HealthBox.svelte +5 -4
  54. package/src/components/IdeBar.svelte +286 -112
  55. package/src/components/InstanceCard.svelte +7 -7
  56. package/src/components/InstanceFilter.svelte +6 -6
  57. package/src/components/InstanceView.svelte +27 -21
  58. package/src/components/SettingsCog.svelte +4 -3
  59. package/src/components/SettingsView.svelte +7 -11
  60. package/src/components/StatusBadge.svelte +8 -6
  61. package/src/components/TerminalPane.svelte +19 -7
  62. package/src/components/ThemePicker.svelte +150 -8
  63. package/src/components/TopBar.svelte +1 -1
  64. package/src/components/UiShowcase.svelte +300 -64
  65. package/src/lib/db.server.ts +7 -3
  66. package/src/lib/devcontainer.server.ts +181 -33
  67. package/src/lib/docker.server.ts +10 -0
  68. package/src/lib/git.server.ts +28 -0
  69. package/src/lib/instances.server.ts +47 -6
  70. package/src/lib/tab-nav.ts +30 -0
  71. package/src/routes.ts +12 -0
  72. package/src/shell.html +56 -23
  73. package/src/theme.ts +8 -1
  74. package/src/toast.ts +9 -0
  75. package/src/types.ts +7 -0
  76. package/.mochi/svelte-client/HydratableIsland-aebn1fa1.js +0 -1
  77. package/.mochi/svelte-client/_hydrate-AppShell_2rtnxn6pgp2rh-rx6arrv5.js +0 -2
  78. package/.mochi/svelte-client/_hydrate-AvatarsView_257s9yq1wwr4f-jpjdmgpe.js +0 -14
  79. package/.mochi/svelte-client/_hydrate-InstanceView_2ma45l9bybfhl-c9y47dat.js +0 -1
  80. package/.mochi/svelte-client/_hydrate-SettingsView_8hmarwmf8onq-d61feq89.js +0 -38
  81. package/.mochi/svelte-client/chunk-8xvr02wh.js +0 -2
  82. package/.mochi/svelte-client/chunk-9143wy3j.js +0 -2
  83. package/.mochi/svelte-client/chunk-k37wj1jm.js +0 -2
  84. package/.mochi/svelte-client/chunk-pc0fm37c.js +0 -2
  85. package/.mochi/svelte-compile/chunk-3t7v4hk0.js +0 -52
  86. package/.mochi/svelte-compile/chunk-gkjgybb2.js +0 -15
  87. package/.mochi/svelte-css/AvatarEditor-2mdq8ss346drw.css +0 -1
  88. package/.mochi/svelte-css/Button-oharop2xz6am.css +0 -1
  89. package/.mochi/svelte-css/CoinButton-1rej3sh3tkjud.css +0 -1
  90. package/.mochi/svelte-css/CredMenu-9hwgeptp7crb.css +0 -1
  91. package/.mochi/svelte-css/DashboardView-1cy4xpqhja9sx.css +0 -1
  92. package/.mochi/svelte-css/FolderBrowser-2pxp9z1o7zixk.css +0 -1
  93. package/.mochi/svelte-css/HealthBox-er2her0jukwl.css +0 -1
  94. package/.mochi/svelte-css/IdeBar-3bgr3m5z0lpeg.css +0 -1
  95. package/.mochi/svelte-css/InstanceCard-3vnltxnbxkvay.css +0 -1
  96. package/.mochi/svelte-css/InstanceFilter-3q6x0jt0hcgpz.css +0 -1
  97. package/.mochi/svelte-css/InstanceView-1pd7j16bd2b16.css +0 -1
  98. package/.mochi/svelte-css/SettingsCog-jftyadvo64qo.css +0 -1
  99. package/.mochi/svelte-css/StatusBadge-3mq0j7z6aq4j.css +0 -1
  100. package/.mochi/svelte-css/TerminalPane-3bwgk6ulzq6b3.css +0 -1
  101. package/.mochi/svelte-css/ThemePicker-1ir8jyocm8mvi.css +0 -1
@@ -10,8 +10,12 @@ import {
10
10
  } from "./chunk-bpqwf1nw.js";
11
11
  import {
12
12
  CLAUDE_EFFORT_LEVELS,
13
- CLAUDE_PERMISSION_MODES
14
- } from "./chunk-gkjgybb2.js";
13
+ CLAUDE_PERMISSION_MODES,
14
+ apiPost,
15
+ applyTheme,
16
+ getTheme,
17
+ setTheme
18
+ } from "./chunk-zd49axkf.js";
15
19
  import {
16
20
  Rotate_ccw
17
21
  } from "./chunk-jx6h1xzp.js";
@@ -19,15 +23,15 @@ import {
19
23
  AppBar,
20
24
  Avatar,
21
25
  Button,
26
+ TOAST_OPTIONS,
22
27
  Toaster,
23
28
  avatars,
24
29
  findAvatar
25
- } from "./chunk-th2dbqvc.js";
30
+ } from "./chunk-gz6hv1h5.js";
26
31
  import {
27
32
  HydratableBoundary,
28
33
  Icon,
29
34
  X,
30
- cookies,
31
35
  emitIslandProps
32
36
  } from "./chunk-60mpagr9.js";
33
37
  import"./chunk-xpt1a7jm.js";
@@ -176,35 +180,36 @@ function Monitor($$renderer, $$props) {
176
180
  ];
177
181
  Icon($$renderer, $8.spread_props([{ name: "monitor" }, props, { iconNode }]));
178
182
  }
179
- // src/theme.ts
180
- var THEME_KEY = "theme";
181
- function getTheme() {
182
- const value = cookies.get(THEME_KEY);
183
- return value === "dark" || value === "light" ? value : "auto";
184
- }
185
- function setTheme(theme) {
186
- cookies.set(THEME_KEY, theme, { expires: 400, path: "/" });
187
- }
188
- function applyTheme(theme) {
189
- if (theme === "auto")
190
- delete document.documentElement.dataset.theme;
191
- else
192
- document.documentElement.dataset.theme = theme;
193
- }
194
-
195
183
  // src/components/ThemePicker.svelte
196
184
  function ThemePicker($$renderer, $$props) {
197
185
  $$renderer.component(($$renderer2) => {
198
186
  let theme = getTheme();
187
+ let phase = null;
188
+ const COLLAPSE_MS = 320;
189
+ const RESTORE_MS = 380;
199
190
  const options = [
200
191
  { value: "auto", label: "Auto", icon: Monitor },
201
192
  { value: "light", label: "Light", icon: Sun },
202
193
  { value: "dark", label: "Dark", icon: Moon }
203
194
  ];
204
- function select(value) {
205
- theme = value;
195
+ const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
196
+ async function select(value) {
197
+ if (value === theme || phase)
198
+ return;
206
199
  setTheme(value);
200
+ apiPost("/api/settings/theme", { value }).catch(() => {});
201
+ if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
202
+ theme = value;
203
+ applyTheme(value);
204
+ return;
205
+ }
206
+ phase = "collapse";
207
+ await wait(COLLAPSE_MS);
208
+ theme = value;
207
209
  applyTheme(value);
210
+ phase = "restore";
211
+ await wait(RESTORE_MS);
212
+ phase = null;
208
213
  }
209
214
  $$renderer2.push(`<div class="picker svelte-3gcwuj" role="radiogroup" aria-label="Theme"><!--[-->`);
210
215
  const each_array = $9.ensure_array_like(options);
@@ -221,7 +226,17 @@ function ThemePicker($$renderer, $$props) {
221
226
  }
222
227
  $$renderer2.push(` ${$9.escape(label)}</button>`);
223
228
  }
224
- $$renderer2.push(`<!--]--></div>`);
229
+ $$renderer2.push(`<!--]--></div> `);
230
+ if (phase) {
231
+ $$renderer2.push("<!--[0-->");
232
+ $$renderer2.push(`<div${$9.attr_class("crt svelte-3gcwuj", undefined, {
233
+ collapse: phase === "collapse",
234
+ restore: phase === "restore"
235
+ })}><span class="bar top svelte-3gcwuj"></span> <span class="bar bottom svelte-3gcwuj"></span> <span class="line svelte-3gcwuj"></span></div>`);
236
+ } else {
237
+ $$renderer2.push("<!--[-1-->");
238
+ }
239
+ $$renderer2.push(`<!--]-->`);
225
240
  });
226
241
  }
227
242
 
@@ -1787,11 +1802,7 @@ function SettingsView($$renderer, $$props) {
1787
1802
  $$renderer2.push(`<!--]--></form></section> `);
1788
1803
  CoinButton($$renderer2, {});
1789
1804
  $$renderer2.push(`<!----> <div class="version svelte-1n6ht58">Codebay v${$26.escape(version)}</div></main></div> `);
1790
- Toaster($$renderer2, {
1791
- toastOptions: {
1792
- style: "border:1px solid var(--ink); background:var(--bg-card); color:var(--ink); box-shadow:4px 4px 0 var(--ink); font-family:var(--font-mono); font-size:13px;"
1793
- }
1794
- });
1805
+ Toaster($$renderer2, { toastOptions: TOAST_OPTIONS });
1795
1806
  $$renderer2.push(`<!---->`);
1796
1807
  });
1797
1808
  }
@@ -0,0 +1,22 @@
1
+ // @bun
2
+ // src/lib/links.ts
3
+ function forwardedPortUrl(hostPort) {
4
+ const host = typeof window === "undefined" ? "localhost" : window.location.hostname;
5
+ return `http://${host}:${hostPort}`;
6
+ }
7
+
8
+ // src/components/StatusBadge.svelte
9
+ import"svelte/internal/flags/async";
10
+ import * as $ from "svelte/internal/server";
11
+ function StatusBadge($$renderer, $$props) {
12
+ let { status } = $$props;
13
+ const label = {
14
+ creating: "Booting\u2026",
15
+ running: "Running",
16
+ stopped: "Stopped",
17
+ error: "Error"
18
+ };
19
+ $$renderer.push(`<span${$.attr_class(`status ${$.stringify(status)}`, "svelte-1hqr9xd")}>${$.escape(label[status])}</span>`);
20
+ }
21
+
22
+ export { forwardedPortUrl, StatusBadge };
@@ -1858,4 +1858,8 @@ function AppBar($$renderer, $$props) {
1858
1858
  $$renderer.push(`<!----></header>`);
1859
1859
  }
1860
1860
 
1861
- export { OFF, ON, GRAY, ROWS, COLS, decode, avatars, findAvatar, Avatar, Button, Toaster, dist_default, AppBar };
1861
+ // src/toast.ts
1862
+ var TOAST_STYLE = "border:1px solid var(--edge); background:var(--bg-card); color:var(--ink); box-shadow:4px 4px 0 var(--shadow); font-family:var(--font-mono); font-size:13px;";
1863
+ var TOAST_OPTIONS = { style: TOAST_STYLE };
1864
+
1865
+ export { OFF, ON, GRAY, ROWS, COLS, decode, avatars, findAvatar, Avatar, Button, Toaster, dist_default, AppBar, TOAST_OPTIONS };
@@ -0,0 +1,65 @@
1
+ // @bun
2
+ import {
3
+ cookies
4
+ } from "./chunk-60mpagr9.js";
5
+
6
+ // src/types.ts
7
+ var CLAUDE_PERMISSION_MODES = [
8
+ "default",
9
+ "manual",
10
+ "auto",
11
+ "plan"
12
+ ];
13
+ var CLAUDE_EFFORT_LEVELS = ["low", "medium", "high", "xhigh", "max"];
14
+ function ideUrl(instance) {
15
+ const base = `/p/${instance.id}/`;
16
+ return instance.remote_workspace_folder ? `${base}?folder=${encodeURIComponent(instance.remote_workspace_folder)}` : base;
17
+ }
18
+
19
+ // src/api.ts
20
+ var APP_REQUEST_HEADER = "X-Codebay-Request";
21
+ async function apiFetch(url, init, fallbackMessage = "Request failed") {
22
+ const res = await fetch(url, {
23
+ ...init,
24
+ headers: {
25
+ ...init?.headers,
26
+ [APP_REQUEST_HEADER]: "1"
27
+ }
28
+ });
29
+ if (!res.ok) {
30
+ const data = await res.json().catch(() => null);
31
+ throw new Error(data?.error?.message ?? fallbackMessage);
32
+ }
33
+ return await res.json().catch(() => ({}));
34
+ }
35
+ function apiPost(url, body, fallbackMessage) {
36
+ return apiJson("POST", url, body, fallbackMessage);
37
+ }
38
+ function apiDelete(url, body, fallbackMessage) {
39
+ return apiJson("DELETE", url, body, fallbackMessage);
40
+ }
41
+ function apiJson(method, url, body, fallbackMessage) {
42
+ return apiFetch(url, body === undefined ? { method } : {
43
+ method,
44
+ headers: { "Content-Type": "application/json" },
45
+ body: JSON.stringify(body)
46
+ }, fallbackMessage);
47
+ }
48
+
49
+ // src/theme.ts
50
+ var THEME_KEY = "theme";
51
+ function getTheme() {
52
+ const value = cookies.get(THEME_KEY);
53
+ return value === "dark" || value === "light" ? value : "auto";
54
+ }
55
+ function setTheme(theme) {
56
+ cookies.set(THEME_KEY, theme, { expires: 400, path: "/" });
57
+ }
58
+ function applyTheme(theme) {
59
+ if (theme === "auto")
60
+ delete document.documentElement.dataset.theme;
61
+ else
62
+ document.documentElement.dataset.theme = theme;
63
+ }
64
+
65
+ export { CLAUDE_PERMISSION_MODES, CLAUDE_EFFORT_LEVELS, ideUrl, apiFetch, apiPost, apiDelete, getTheme, setTheme, applyTheme };
@@ -1 +1 @@
1
- .bar.svelte-fcv4i8{display:flex;border-bottom:1px solid var(--rule);background:var(--bg-card);align-items:stretch;gap:0;height:44px}.home.svelte-fcv4i8{display:inline-flex;color:var(--ink);border-right:1px solid var(--rule);flex:none;justify-content:center;align-items: center;width:48px}.home.svelte-fcv4i8:hover{background:var(--ink);color:var(--bg)}
1
+ .bar.svelte-fcv4i8{display:flex;border-bottom:1px solid var(--rule);background:var(--bg-card);align-items:stretch;gap:0;height:44px}.home.svelte-fcv4i8{display:inline-flex;color:var(--ink);border-right:1px solid var(--rule);flex:none;justify-content:center;align-items: center;width:48px}.home.svelte-fcv4i8:hover{background:var(--fill);color:var(--fill-ink)}
@@ -0,0 +1 @@
1
+ .editor.svelte-qu6vp4{display:flex;background:var(--bg-card);border:1px solid var(--rule);overflow:hidden;flex-direction:column;width:100%}.head.svelte-qu6vp4{display:flex;border-bottom:1px solid var(--fill);background:var(--fill);justify-content:space-between;align-items: center;gap:12px;padding:14px 18px}.head.svelte-qu6vp4 h2:where(.svelte-qu6vp4){font-family:var(--font-display);text-transform:uppercase;letter-spacing:.06em;color:var(--fill-ink);margin:0;font-size:17px;font-weight:700}.head-cancel.svelte-qu6vp4{display:inline-flex;border:1px solid var(--fill-ink);color:var(--fill-ink);font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.06em;cursor:pointer;background:0 0;flex:none;align-items: center;gap:6px;padding:5px 10px;font-size:11px}.head-cancel.svelte-qu6vp4:hover{background:var(--fill-ink);color:var(--fill)}.head-cancel.svelte-qu6vp4:focus-visible{outline:none;box-shadow:0 0 0 2px var(--rule-soft)}.body.svelte-qu6vp4{display:flex;flex-wrap:wrap;gap:18px;padding:18px}.grid-frame.svelte-qu6vp4{display:grid;grid-template-columns:repeat(10,40px);grid-template-rows:repeat(10,40px);border:1px solid var(--ink);background:var(--bg);flex:none;width:400px;height:400px}.ring-cell.svelte-qu6vp4{box-sizing:border-box;background-clip:content-box;background-color:var(--rule-soft);opacity:var(--dim);padding:0 1px 1px 0}.grid.svelte-qu6vp4{display:grid;grid-template-columns:repeat(8,1fr);grid-template-rows:repeat(8,1fr);grid-column:2/10;grid-row:2/10;cursor:crosshair;touch-action:none}.cell.svelte-qu6vp4{box-sizing:border-box;background-clip:content-box;background-color:var(--rule-soft);padding:0 1px 1px 0}.cell.gray.svelte-qu6vp4{background-color:var(--led-gray)}.cell.on.svelte-qu6vp4{background-color:var(--ink)}.side.svelte-qu6vp4{display:flex;flex-direction:column;flex:1;gap:16px;min-width:160px}.preview-label.svelte-qu6vp4{text-transform:uppercase;letter-spacing:.06em;color:var(--ink-faint);font-size:11px;font-family:var(--font-mono)}.preview-row.svelte-qu6vp4{display:flex;align-items: flex-end;gap:10px;margin-top:6px}.name-field.svelte-qu6vp4{display:flex;flex-direction:column;gap:6px}.name-field.svelte-qu6vp4 input:where(.svelte-qu6vp4){font-family:var(--font-mono);border:1px solid var(--ink);background:var(--bg);color:var(--ink);padding:8px 12px;font-size:13px}.name-field.svelte-qu6vp4 input:where(.svelte-qu6vp4)::placeholder{color:var(--ink-faint)}.name-field.svelte-qu6vp4 input[readonly]:where(.svelte-qu6vp4){color:var(--ink-soft);cursor:default}.name-field.svelte-qu6vp4 input:where(.svelte-qu6vp4):focus{outline:none;box-shadow:inset 3px 3px 0 var(--rule-soft)}.mode-field.svelte-qu6vp4{display:flex;flex-direction:column;gap:6px}.modes.svelte-qu6vp4{display:flex;border:1px solid var(--ink)}.mode.svelte-qu6vp4{border:none;border-right:1px solid var(--ink);background:var(--bg);color:var(--ink);font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.06em;cursor:pointer;flex:1;padding:7px 6px;font-size:11px}.mode.svelte-qu6vp4:last-child{border-right:none}.mode.active.svelte-qu6vp4{background:var(--fill);color:var(--fill-ink)}.mode.svelte-qu6vp4:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--rule-soft)}.tools.svelte-qu6vp4{display:flex;gap:8px}.foot.svelte-qu6vp4{display:flex;border-top:1px solid var(--ink);flex-wrap:wrap;justify-content:space-between;align-items: center;gap:12px;padding:14px 18px}.hint.svelte-qu6vp4{font-family:var(--font-mono);color:var(--ink-faint);flex:1;min-width:180px;font-size:12px}.actions.svelte-qu6vp4{display:flex;gap:8px}.actions.svelte-qu6vp4 .btn{white-space:nowrap}
@@ -1 +1 @@
1
- .page.svelte-fkq7sr{display:flex;flex-direction:column;min-height:100vh}.title.svelte-fkq7sr{display:inline-flex;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.08em;color:var(--ink-soft);align-items: center;padding:0 14px;font-size:12px}.content.svelte-fkq7sr{display:flex;flex-direction:column;flex:1;align-items: center;gap:24px;padding:32px 20px}.content.svelte-fkq7sr>*{width:100%;max-width:720px}.catalog.svelte-fkq7sr{background:var(--bg-card);border:1px solid var(--rule);padding:18px}.catalog.svelte-fkq7sr header:where(.svelte-fkq7sr){margin-bottom:20px}.catalog.svelte-fkq7sr h2:where(.svelte-fkq7sr){font-family:var(--font-display);text-transform:uppercase;letter-spacing:.06em;margin:0;font-size:17px;font-weight:700}.catalog.svelte-fkq7sr header:where(.svelte-fkq7sr) p:where(.svelte-fkq7sr){font-family:var(--font-mono);color:var(--ink-soft);margin:4px 0 0;font-size:12px}ul.svelte-fkq7sr{list-style:none;display:grid;grid-template-columns:repeat(auto-fill,minmax(110px,1fr));gap:20px;margin:0;padding:0}li.svelte-fkq7sr{display:flex;flex-direction:column;align-items: center;gap:8px}.label.svelte-fkq7sr{display:inline-flex;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.08em;color:var(--ink-soft);align-items: center;gap:4px;font-size:11px}.robot-mark.svelte-fkq7sr{display:inline-flex;color:var(--ink-faint)}.editor-slot.svelte-fkq7sr{display:flex}.editor-slot.svelte-fkq7sr>*{width:100%}.edit-btn.svelte-fkq7sr{display:inline-flex;border:1px solid var(--rule);background:var(--bg);color:var(--ink-soft);font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.08em;cursor:pointer;align-items: center;gap:4px;padding:4px 8px;font-size:10px}.edit-btn.svelte-fkq7sr:hover{border-color:var(--ink);color:var(--ink)}.edit-btn.active.svelte-fkq7sr{background:var(--ink);border-color:var(--ink);color:var(--bg)}.edit-btn.svelte-fkq7sr:focus-visible{outline:none;box-shadow:0 0 0 2px var(--rule-soft)}.edit-btn.svelte-fkq7sr:disabled{cursor:default}
1
+ .page.svelte-fkq7sr{display:flex;flex-direction:column;min-height:100vh}.title.svelte-fkq7sr{display:inline-flex;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.08em;color:var(--ink-soft);align-items: center;padding:0 14px;font-size:12px}.content.svelte-fkq7sr{display:flex;flex-direction:column;flex:1;align-items: center;gap:24px;padding:32px 20px}.content.svelte-fkq7sr>*{width:100%;max-width:720px}.catalog.svelte-fkq7sr{background:var(--bg-card);border:1px solid var(--rule);padding:18px}.catalog.svelte-fkq7sr header:where(.svelte-fkq7sr){margin-bottom:20px}.catalog.svelte-fkq7sr h2:where(.svelte-fkq7sr){font-family:var(--font-display);text-transform:uppercase;letter-spacing:.06em;margin:0;font-size:17px;font-weight:700}.catalog.svelte-fkq7sr header:where(.svelte-fkq7sr) p:where(.svelte-fkq7sr){font-family:var(--font-mono);color:var(--ink-soft);margin:4px 0 0;font-size:12px}ul.svelte-fkq7sr{list-style:none;display:grid;grid-template-columns:repeat(auto-fill,minmax(110px,1fr));gap:20px;margin:0;padding:0}li.svelte-fkq7sr{display:flex;flex-direction:column;align-items: center;gap:8px}.label.svelte-fkq7sr{display:inline-flex;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.08em;color:var(--ink-soft);align-items: center;gap:4px;font-size:11px}.robot-mark.svelte-fkq7sr{display:inline-flex;color:var(--ink-faint)}.editor-slot.svelte-fkq7sr{display:flex}.editor-slot.svelte-fkq7sr>*{width:100%}.edit-btn.svelte-fkq7sr{display:inline-flex;border:1px solid var(--rule);background:var(--bg);color:var(--ink-soft);font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.08em;cursor:pointer;align-items: center;gap:4px;padding:4px 8px;font-size:10px}.edit-btn.svelte-fkq7sr:hover{border-color:var(--ink);color:var(--ink)}.edit-btn.active.svelte-fkq7sr{background:var(--fill);border-color:var(--fill);color:var(--fill-ink)}.edit-btn.svelte-fkq7sr:focus-visible{outline:none;box-shadow:0 0 0 2px var(--rule-soft)}.edit-btn.svelte-fkq7sr:disabled{cursor:default}
@@ -0,0 +1 @@
1
+ .btn.svelte-1klcfz0{display:inline-flex;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.06em;border:1px solid var(--edge);background:var(--bg-card);color:var(--ink);cursor:pointer;text-decoration:none;justify-content:center;align-items: center;gap:7px;font-weight:600}.btn.svelte-1klcfz0:disabled{opacity:var(--dim);cursor:not-allowed}.btn[aria-disabled=true].svelte-1klcfz0{opacity:var(--dim);cursor:not-allowed;pointer-events:none}.btn.sm.svelte-1klcfz0{padding:7px 12px;font-size:12px}.btn.md.svelte-1klcfz0{padding:9px 16px;font-size:13px}.btn.lg.svelte-1klcfz0{padding:12px 22px;font-size:15px}.btn.square.svelte-1klcfz0{padding:0}.btn.square.sm.svelte-1klcfz0{width:30px;height:30px}.btn.square.md.svelte-1klcfz0{width:35px;height:35px}.btn.square.lg.svelte-1klcfz0{width:44px;height:44px}.btn.default.svelte-1klcfz0:hover:not(:disabled){background:var(--fill);border-color:var(--fill);color:var(--fill-ink)}.btn.primary.svelte-1klcfz0{background:var(--fill);border-color:var(--fill);color:var(--fill-ink);font-weight:700}.btn.primary.svelte-1klcfz0:hover:not(:disabled){background:var(--bg-card);border-color:var(--edge);color:var(--ink)}.btn.ghost.svelte-1klcfz0{background:0 0;border-style:dashed}.btn.ghost.svelte-1klcfz0:hover:not(:disabled){background:var(--fill);border-color:var(--fill);color:var(--fill-ink);border-style:solid}.btn.danger.svelte-1klcfz0{color:var(--danger);border-color:var(--danger)}.btn.danger.svelte-1klcfz0:hover:not(:disabled){color:var(--danger);background-color:var(--danger-soft);background-image:linear-gradient(90deg,var(--danger)50%,transparent 0),linear-gradient(90deg,var(--danger)50%,transparent 0),linear-gradient(0deg,var(--danger)50%,transparent 0),linear-gradient(0deg,var(--danger)50%,transparent 0);animation:svelte-1klcfz0-marching-ants 2s linear infinite;background-position:0 0,0 100%,0 0,100% 0;background-repeat:repeat-x,repeat-x,repeat-y,repeat-y;background-size:14px 2px,14px 2px,2px 14px,2px 14px;border-color:#0000}@keyframes svelte-1klcfz0-marching-ants{to{background-position:28px 0,-28px 100%,0 -28px,100% 28px}}
@@ -0,0 +1 @@
1
+ .coin-row.svelte-1ioj7vz{display:flex;align-items: center;gap:16px;width:100%;max-width:560px;padding:8px 0}.pixel-line.svelte-1ioj7vz{background:repeating-linear-gradient(90deg,var(--rule)0 2px,transparent 2px 6px);flex:1;height:2px}.coin-btn.svelte-1ioj7vz{display:flex;cursor:pointer;text-decoration:none;background:0 0;border:none;flex-direction:column;flex:none;align-items: center;gap:4px;padding:4px}.new.svelte-1ioj7vz{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.14em;color:var(--ink-soft);animation:svelte-1ioj7vz-coin-blink 2.6s steps(1,end)infinite;font-size:8px;font-weight:700}.coin.svelte-1ioj7vz{display:block;box-shadow:2px 2px 0 var(--shadow);animation:svelte-1ioj7vz-coin-spin 2.6s ease-in-out infinite}.coin-btn.svelte-1ioj7vz:hover .coin:where(.svelte-1ioj7vz){animation:none;box-shadow:1px 1px 0 var(--shadow);transform:translate(1px,1px)}.coin-btn.svelte-1ioj7vz:focus-visible{outline:2px solid var(--ink);outline-offset:2px}@keyframes svelte-1ioj7vz-coin-spin{0%,55%{transform:scaleX(1)}66%{transform:scaleX(.12)}78%{transform:scaleX(-1)}89%{transform:scaleX(.12)}to{transform:scaleX(1)}}@keyframes svelte-1ioj7vz-coin-blink{0%,55%,to{opacity:1}66%,89%{opacity:.25}}@media (prefers-reduced-motion:reduce){.coin.svelte-1ioj7vz,.new.svelte-1ioj7vz{animation:none}}
@@ -0,0 +1 @@
1
+ .cred-menu.svelte-vongf9{position:relative;display:inline-flex}.cred.svelte-vongf9{display:inline-flex;border:1px solid var(--fill);background:var(--fill);color:var(--fill-ink);cursor:pointer;justify-content:center;align-items: center;width:32px;height:32px;font-size:14px;line-height:1}.cred.svelte-vongf9:hover{background:var(--bg);border-color:var(--edge);color:var(--ink)}.cred.ok.svelte-vongf9{background:var(--ok-bg);border-color:var(--ok-line);color:var(--ok-ink)}.cred.ok.svelte-vongf9:hover{background:var(--ok-ink);border-color:var(--ok-ink);color:var(--ok-bg)}.cred.warn.svelte-vongf9{background:var(--warn-bg);border-color:var(--warn-line);color:var(--warn-ink)}.cred.warn.svelte-vongf9:hover{background:var(--warn-ink);border-color:var(--warn-ink);color:var(--warn-bg)}.cred.error.svelte-vongf9{background:var(--bg);border-color:var(--edge);color:var(--ink)}.cred-dropdown.svelte-vongf9{position:absolute;z-index:20;background:var(--bg-card);min-width:220px;padding:6px;top:calc(100% + 6px);right:0}.cred-row.svelte-vongf9{display:flex;color:var(--ink);text-align:left;font-family:var(--font-mono);cursor:pointer;background:0 0;border:0;align-items: center;gap:9px;width:100%;padding:7px 9px;font-size:12px}.cred-row.svelte-vongf9:hover{background:var(--fill);color:var(--fill-ink)}.cred-row.svelte-vongf9:hover .cred-state:where(.svelte-vongf9){color:var(--fill-ink)}.dot.svelte-vongf9{border:1px solid;flex:none;width:9px;height:9px}.dot.on.svelte-vongf9{background:currentColor}.dot.off.svelte-vongf9{background:0 0}.cred-state.svelte-vongf9{color:var(--ink-soft);margin-left:auto}
@@ -0,0 +1 @@
1
+ .stage.svelte-146pixd{max-width:1080px;margin:0 auto;padding:28px 24px 80px}.banner.svelte-146pixd{display:flex;font-family:var(--font-mono);flex-wrap:wrap;gap:8px;margin-bottom:20px;padding:12px 16px;font-size:13px}.banner.error.svelte-146pixd{background:var(--bg-card);color:var(--ink);border:2px solid var(--edge);box-shadow:4px 4px 0 var(--shadow)}.empty.svelte-146pixd{text-align:center;padding:80px 20px}.empty-title.svelte-146pixd{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.06em;margin:0 0 8px;font-size:26px;font-weight:700}.empty-sub.svelte-146pixd{color:var(--ink-soft);margin:0 0 22px}.grid.svelte-146pixd{list-style:none;display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:18px;margin:0;padding:0}
@@ -0,0 +1 @@
1
+ .overlay.svelte-oq97c4{position:fixed;background:var(--scrim);display:grid;z-index:50;place-items: center;padding:24px;inset:0}.modal.svelte-oq97c4{display:flex;background:var(--bg-card);overflow:hidden;box-shadow:8px 8px 0 var(--shadow);flex-direction:column;width:min(620px,100%);max-height:80vh}.head.svelte-oq97c4{display:flex;border-bottom:1px solid var(--fill);background:var(--fill);justify-content:space-between;align-items: center;padding:14px 18px}.head.svelte-oq97c4 h2:where(.svelte-oq97c4){font-family:var(--font-display);text-transform:uppercase;letter-spacing:.06em;color:var(--fill-ink);margin:0;font-size:17px;font-weight:700}.x.svelte-oq97c4{display:inline-flex;cursor:pointer;color:var(--fill-ink);background:0 0;border:none;align-items: center}.x.svelte-oq97c4:hover{opacity:.7}.mode.svelte-oq97c4{display:flex;border-bottom:1px solid var(--rule-soft);align-items: center;gap:12px;padding:12px 18px}.mode-label.svelte-oq97c4{text-transform:uppercase;letter-spacing:.06em;color:var(--ink-faint);font-size:11px}.mode-toggle.svelte-oq97c4{display:flex;border:1px solid var(--edge)}.mode-btn.svelte-oq97c4{display:inline-flex;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.05em;background:var(--bg);color:var(--ink);cursor:pointer;border:none;align-items: center;gap:6px;padding:7px 14px;font-size:12px;font-weight:700}.mode-btn.svelte-oq97c4+.mode-btn:where(.svelte-oq97c4){border-left:1px solid var(--edge)}.mode-btn.active.svelte-oq97c4{background:var(--fill);color:var(--fill-ink)}.clone.svelte-oq97c4{border-bottom:1px solid var(--rule-soft);padding:12px 18px}.clone-label.svelte-oq97c4{text-transform:uppercase;letter-spacing:.06em;color:var(--ink-faint);padding-bottom:6px;font-size:11px}.clone-row.svelte-oq97c4{display:flex;gap:8px}.clone-url.svelte-oq97c4,.clone-branch.svelte-oq97c4{font-family:var(--font-mono);border:1px solid var(--ink);background:var(--bg);color:var(--ink);padding:8px 12px;font-size:13px}.clone-url.svelte-oq97c4{flex:1;min-width:0}.clone-branch.svelte-oq97c4{flex:none;width:140px}.clone-url.svelte-oq97c4::placeholder,.clone-branch.svelte-oq97c4::placeholder{color:var(--ink-faint)}.clone-url.svelte-oq97c4:focus,.clone-branch.svelte-oq97c4:focus{outline:none;box-shadow:inset 3px 3px 0 var(--rule-soft)}.clone-btn.svelte-oq97c4{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.05em;border:1px solid var(--fill);background:var(--fill);color:var(--fill-ink);cursor:pointer;white-space:nowrap;padding:8px 14px;font-size:12px;font-weight:700}.clone-btn.svelte-oq97c4:hover:not(:disabled){background:var(--bg-card);border-color:var(--edge);color:var(--ink)}.clone-btn.svelte-oq97c4:disabled{opacity:var(--dim);cursor:not-allowed}.crumbs.svelte-oq97c4{border-bottom:1px solid var(--rule-soft);overflow-x:auto;overflow-y:hidden;flex-shrink:0;min-height:18px;padding:10px 18px}.crumbs.svelte-oq97c4 code:where(.svelte-oq97c4){font-family:var(--font-mono);color:var(--ink-soft);white-space:nowrap;font-size:12px}.recent.svelte-oq97c4{border-bottom:1px solid var(--rule-soft);overflow:auto;flex-shrink:0;max-height:40vh;padding:8px}.recent-label.svelte-oq97c4{text-transform:uppercase;letter-spacing:.06em;color:var(--ink-faint);padding:2px 10px 6px;font-size:11px}.recent-row.svelte-oq97c4{position:relative;display:flex;align-items: center}.recent-pick.svelte-oq97c4{display:flex;cursor:pointer;font:inherit;text-align:left;color:var(--ink);background:0 0;border:none;border-radius:8px;flex:1;align-items: center;gap:10px;min-width:0;padding:8px 10px}.recent-pick.svelte-oq97c4:hover{background:var(--fill);color:var(--fill-ink)}.recent-pick.svelte-oq97c4:hover .recent-path:where(.svelte-oq97c4){color:var(--fill-ink)}.recent-pick.svelte-oq97c4:hover .icon:where(.svelte-oq97c4){color:var(--fill-ink)}.recent-text.svelte-oq97c4{display:flex;flex-direction:column;min-width:0}.recent-name.svelte-oq97c4{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.recent-path.svelte-oq97c4{font-family:var(--font-mono);color:var(--ink-faint);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11px}.recent-x.svelte-oq97c4{position:absolute;display:inline-flex;background:var(--bg-card);color:var(--ink-soft);cursor:pointer;opacity:0;border:none;border-radius:6px;align-items: center;padding:5px 7px;line-height:1;top:50%;right:8px;transform:translateY(-50%)}.recent-row.svelte-oq97c4:hover .recent-x:where(.svelte-oq97c4){opacity:1}.recent-x.svelte-oq97c4:hover{color:var(--fill-ink);background:var(--fill)}.recent-toggle.svelte-oq97c4{cursor:pointer;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.05em;color:var(--ink);background:0 0;border:none;margin:4px 6px 2px;padding:4px 6px;font-size:12px}.recent-toggle.svelte-oq97c4:hover{text-decoration:underline}.search.svelte-oq97c4{border-bottom:1px solid var(--rule-soft);padding:10px 18px}.search.svelte-oq97c4 input:where(.svelte-oq97c4){font-family:var(--font-mono);border:1px solid var(--ink);background:var(--bg);color:var(--ink);width:100%;padding:8px 12px;font-size:13px}.search.svelte-oq97c4 input:where(.svelte-oq97c4)::placeholder{color:var(--ink-faint)}.search.svelte-oq97c4 input:where(.svelte-oq97c4):focus{outline:none;box-shadow:inset 3px 3px 0 var(--rule-soft)}.list.svelte-oq97c4{overflow:auto;flex:1;padding:8px}.row.svelte-oq97c4{display:flex;border:1px solid #0000;border-radius:8px;align-items: center;gap:6px;padding:2px 4px}.row.first-match.svelte-oq97c4{border-color:var(--rule-soft)}.row.svelte-oq97c4 .nav:where(.svelte-oq97c4){display:flex;cursor:pointer;font:inherit;text-align:left;color:var(--ink);background:0 0;border:none;border-radius:8px;flex:1;align-items: center;gap:10px;padding:9px 10px}.row.svelte-oq97c4 .nav:where(.svelte-oq97c4):hover{background:var(--fill);color:var(--fill-ink)}.row.svelte-oq97c4 .nav:where(.svelte-oq97c4):hover .icon:where(.svelte-oq97c4){color:var(--fill-ink)}.ename.svelte-oq97c4{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.badge.svelte-oq97c4{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.08em;color:var(--ink);border:1px solid var(--edge);background:0 0;padding:2px 5px;font-size:9px;font-weight:600}.row.svelte-oq97c4 .nav:where(.svelte-oq97c4):hover .badge:where(.svelte-oq97c4){color:var(--fill-ink);border-color:var(--fill-ink)}.pick-inline.svelte-oq97c4{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.05em;border:1px solid var(--edge);background:var(--bg-card);cursor:pointer;color:var(--ink);padding:6px 10px;font-size:11px;font-weight:600}.pick-inline.svelte-oq97c4:hover{background:var(--fill);border-color:var(--fill);color:var(--fill-ink)}.muted.svelte-oq97c4{color:var(--ink-faint);text-align:center;padding:18px}.muted.err.svelte-oq97c4{color:var(--ink);font-weight:600}.warn.svelte-oq97c4{display:flex;background:var(--warn-bg);color:var(--warn-ink);font-family:var(--font-mono);border-top:1px solid var(--warn-line);align-items: flex-start;gap:8px;padding:10px 18px;font-size:12.5px}.warn.svelte-oq97c4 svg{flex:none;margin-top:1px}.warn.svelte-oq97c4 code:where(.svelte-oq97c4){font-family:var(--font-mono);background:var(--warn-chip);border:1px solid var(--warn-line);padding:0 5px;font-size:.9em}.foot.svelte-oq97c4{display:flex;border-top:1px solid var(--edge);justify-content:space-between;align-items: center;gap:12px;padding:14px 18px}.hint.svelte-oq97c4{font-family:var(--font-mono);color:var(--ink-faint);font-size:12px}.primary.svelte-oq97c4{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.06em;border:1px solid var(--fill);background:var(--fill);color:var(--fill-ink);cursor:pointer;white-space:nowrap;padding:9px 16px;font-size:13px;font-weight:700}.primary.svelte-oq97c4:hover:not(:disabled){background:var(--bg-card);border-color:var(--edge);color:var(--ink)}.primary.svelte-oq97c4:disabled{opacity:var(--dim);cursor:not-allowed}.icon.svelte-oq97c4{display:inline-flex;color:var(--ink-soft);align-items: center}
@@ -0,0 +1 @@
1
+ .healthwrap.svelte-1hnopyv{overflow:hidden}.healthwrap.dim.svelte-1hnopyv{opacity:var(--dim-panel)}.health.svelte-1hnopyv{background:var(--bg-card);display:grid;grid-template-columns:max-content 1fr max-content;align-items: center}.hrow.svelte-1hnopyv{display:grid;grid-template-columns:subgrid;grid-column:1/-1;border-top:1px solid var(--rule-soft);align-items: center;gap:12px;padding:10px 14px}.hrow.svelte-1hnopyv:first-child{border-top:none}.box.svelte-1hnopyv{border:1px solid var(--edge);display:inline-flex;color:var(--ink);justify-content:center;align-items: center;width:16px;height:16px}.box.ok.svelte-1hnopyv{background:var(--fill);border-color:var(--fill);color:var(--fill-ink)}.box.bad.svelte-1hnopyv{background:0 0}.box.idle.svelte-1hnopyv{border-color:var(--ink-faint)}.hlabel.svelte-1hnopyv{font-family:var(--font-mono);color:var(--ink-soft);font-size:13px}.hvalue.svelte-1hnopyv{font-family:var(--font-display);letter-spacing:.1em;text-transform:uppercase;color:var(--ink);justify-self:end;font-size:11px;font-weight:700}.hfoot.svelte-1hnopyv{border-top:1px solid var(--rule-soft);background:var(--bg);font-family:var(--font-mono);color:var(--ink-faint);padding:7px 14px;font-size:11px}
@@ -0,0 +1 @@
1
+ .right.svelte-r39acv{display:flex;align-items:stretch;margin-left:auto}.cog.svelte-r39acv,.reload.svelte-r39acv{display:inline-flex;color:var(--ink);border-left:1px solid var(--rule);flex:none;justify-content:center;align-items: center;width:48px}.reload.svelte-r39acv{appearance:none;cursor:pointer;background:0 0;border-top:0;border-bottom:0;border-right:0;padding:0}.cog.svelte-r39acv:hover,.reload.svelte-r39acv:hover{background:var(--fill);color:var(--fill-ink)}.strip.svelte-r39acv{display:flex;align-items:stretch;min-width:0}.viewport.svelte-r39acv{display:flex;overflow-x:auto;scroll-behavior:smooth;scrollbar-width:none;min-width:0}.viewport.svelte-r39acv::-webkit-scrollbar{display:none}@media (prefers-reduced-motion:reduce){.viewport.svelte-r39acv{scroll-behavior:auto}}.tabs.svelte-r39acv{display:flex;flex:none;align-items:stretch}.page.svelte-r39acv{display:inline-flex;appearance:none;border:0;border-right:1px solid var(--rule);background:var(--bg-card);color:var(--ink);cursor:pointer;flex:none;justify-content:center;align-items: center;width:28px;margin:0;padding:0}.page.trailing.svelte-r39acv{border-right:0;border-left:1px solid var(--rule)}.page.svelte-r39acv:hover:not(:disabled){background:var(--fill);color:var(--fill-ink)}.page.svelte-r39acv:disabled{opacity:var(--dim);cursor:default}.page.svelte-r39acv:focus-visible{outline:2px solid var(--ink);outline-offset:-2px}.tab.svelte-r39acv{display:inline-flex;appearance:none;border:0;border-right:1px solid var(--rule);color:var(--ink-soft);font-family:var(--font-display);text-transform:uppercase;letter-spacing:.06em;cursor:pointer;background:0 0;flex:none;align-items: center;gap:10px;max-width:240px;margin:0;padding:0 12px;transition:background 80ms steps(2,end);font-size:13px;font-weight:700}.tab.svelte-r39acv:not(.active):hover{background:color-mix(in srgb,var(--ink)12%,transparent);color:var(--ink)}.tab.active.svelte-r39acv{background:var(--fill);color:var(--fill-ink);cursor:default;box-shadow:inset 0 3px 0 var(--bg)}.tab.svelte-r39acv:focus-visible{outline:2px solid var(--ink);outline-offset:-2px}.tab.active.svelte-r39acv:focus-visible{outline-color:var(--fill-ink)}.tab-name.svelte-r39acv{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tab-mode.svelte-r39acv{display:inline-flex;opacity:.7;border:1px solid;flex:none;justify-content:center;align-items: center;width:18px;height:18px}.attn.svelte-r39acv{border:1px solid var(--edge);animation:svelte-r39acv-tab-attn-pulse 1.4s ease-in-out infinite;flex:none;width:10px;height:10px}.attn.done.svelte-r39acv{background:var(--attn-done);color:var(--attn-done)}.attn.waiting.svelte-r39acv{background:var(--attn-waiting);color:var(--attn-waiting)}@keyframes svelte-r39acv-tab-attn-pulse{0%,to{box-shadow:0 0 #0000;filter:brightness(.85)}50%{box-shadow:0 0 6px 2px color-mix(in srgb,currentColor 60%,transparent);filter:brightness(1.15)}}@media (prefers-reduced-motion:reduce){.attn.svelte-r39acv{animation:none;filter:none}}.tab.editing.svelte-r39acv{cursor:default}.tab-name-edit.svelte-r39acv{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.06em;border:1px solid var(--ink);background:var(--bg);color:var(--ink);width:148px;margin:0;padding:3px 6px;font-size:12px}.tab-name-edit.svelte-r39acv:focus-visible{outline:2px solid var(--ink);outline-offset:-2px}
@@ -0,0 +1 @@
1
+ .card.svelte-13338y7{position:relative;background:var(--bg-card);padding:16px 16px 14px;transition:transform 80ms steps(2,end),box-shadow 80ms steps(2,end)}.card.svelte-13338y7:hover:not(.busy){box-shadow:6px 6px 0 var(--shadow);transform:translate(-1px,-1px)}.busy-overlay.svelte-13338y7{position:absolute;z-index:1;display:flex;background:color-mix(in srgb,var(--bg-card)78%,transparent);justify-content:center;align-items: center;inset:0}.busy-label.svelte-13338y7{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.1em;border:1px solid var(--fill);background:var(--fill);color:var(--fill-ink);animation:svelte-13338y7-lcd-blink 1.1s steps(1)infinite;padding:4px 9px;font-size:12px;font-weight:600}@keyframes svelte-13338y7-lcd-blink{50%{background:0 0;color:var(--fill)}}@media (prefers-reduced-motion:reduce){.busy-label.svelte-13338y7{animation:none}}.card-head.svelte-13338y7{display:flex;align-items: center;gap:11px}.attn.svelte-13338y7{border:1px solid var(--edge);flex:none;width:14px;height:14px}.attn.attn-done.svelte-13338y7{background:var(--attn-done);animation:svelte-13338y7-card-attn-pulse 1.4s ease-in-out infinite}.attn.attn-waiting.svelte-13338y7{background:var(--attn-waiting);animation:svelte-13338y7-card-attn-pulse 1.4s ease-in-out infinite}@keyframes svelte-13338y7-card-attn-pulse{0%,to{box-shadow:0 0 #0000;filter:brightness(.85)}50%{box-shadow:0 0 7px 2px color-mix(in srgb,currentColor 60%,transparent);filter:brightness(1.15)}}.attn.attn-done.svelte-13338y7{color:var(--attn-done)}.attn.attn-waiting.svelte-13338y7{color:var(--attn-waiting)}@media (prefers-reduced-motion:reduce){.attn.svelte-13338y7{animation:none;filter:none}}.name.svelte-13338y7{font-family:var(--font-mono);overflow-wrap:anywhere;color:var(--ink);text-align:left;cursor:pointer;background:0 0;border:1px solid #0000;flex:1;min-width:0;margin:0;padding:2px 4px;font-size:15px;font-weight:600}.name.svelte-13338y7:hover{border-color:var(--ink-faint)}.name-edit.svelte-13338y7{font-family:var(--font-mono);border:1px solid var(--ink);background:var(--bg);color:var(--ink);outline:none;flex:1;min-width:0;margin:0;padding:2px 4px;font-size:15px;font-weight:600}.path.svelte-13338y7{font-family:var(--font-mono);color:var(--ink-soft);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:10px;font-size:12px}.card-error.svelte-13338y7{font-family:var(--font-mono);color:var(--ink);background:var(--bg);border:1px solid var(--edge);overflow:auto;max-height:80px;margin-top:10px;padding:8px 10px;font-size:12px}.actions.svelte-13338y7{display:flex;flex-wrap:wrap;gap:8px;margin-top:16px}
@@ -0,0 +1 @@
1
+ .picker.svelte-12yor8r{display:inline-flex;border:1px solid var(--edge);background:var(--bg-card);flex:none}.segment.svelte-12yor8r{display:inline-flex;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.06em;color:var(--ink);cursor:pointer;background:0 0;border:none;align-items: center;gap:6px;padding:7px 12px;font-size:12px;font-weight:600}.segment.svelte-12yor8r+.segment:where(.svelte-12yor8r){border-left:1px solid var(--edge)}.segment.svelte-12yor8r:hover:not(.active){background:var(--fill);color:var(--fill-ink)}.segment.active.svelte-12yor8r{background:var(--fill);color:var(--fill-ink);cursor:default;font-weight:700}.segment.svelte-12yor8r:focus-visible{outline:2px solid var(--ink);outline-offset:-2px}
@@ -0,0 +1 @@
1
+ .topbar.svelte-15fxkvm{display:flex;border-bottom:1px solid var(--rule);align-items: center;gap:18px;padding:16px 24px}.back.svelte-15fxkvm{display:inline-flex;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.06em;color:var(--ink-soft);text-decoration:none;align-items: center;gap:5px;font-size:12px}.back.svelte-15fxkvm:hover{color:var(--ink)}.title.svelte-15fxkvm{display:flex;flex:1;align-items: center;gap:12px}.name.svelte-15fxkvm{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.03em;font-size:20px;font-weight:700}.open.svelte-15fxkvm{display:inline-flex;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.06em;color:var(--ink);text-decoration:none;border:1px solid var(--edge);align-items: center;gap:6px;padding:7px 12px;font-size:12px;font-weight:600}.open.svelte-15fxkvm:hover{background:var(--fill);border-color:var(--fill);color:var(--fill-ink)}.restart.svelte-15fxkvm{display:inline-flex;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.06em;color:var(--ink);background:var(--bg);border:1px solid var(--edge);cursor:pointer;align-items: center;gap:6px;padding:7px 12px;font-size:12px;font-weight:600}.restart.svelte-15fxkvm:hover:not(:disabled){background:var(--fill);border-color:var(--fill);color:var(--fill-ink)}.restart.svelte-15fxkvm:disabled{opacity:var(--dim-panel);cursor:not-allowed}.restart-err.svelte-15fxkvm{font-family:var(--font-mono);color:var(--danger);margin:0;padding:8px 24px 0;font-size:12px}.stage.svelte-15fxkvm{max-width:1200px;margin:0 auto;padding:20px 24px 40px}.meta.svelte-15fxkvm{display:grid;grid-template-columns:max-content 1fr;align-items: center;gap:6px 14px;margin-bottom:18px}.meta.svelte-15fxkvm .k:where(.svelte-15fxkvm){font-family:var(--font-display);letter-spacing:.14em;text-transform:uppercase;color:var(--ink-faint);font-size:12px;font-weight:700}.meta.svelte-15fxkvm code:where(.svelte-15fxkvm){font-family:var(--font-mono);color:var(--ink-soft);font-size:13px}.meta.svelte-15fxkvm code.muted:where(.svelte-15fxkvm){color:var(--ink-faint)}.healthslot.svelte-15fxkvm,.ports.svelte-15fxkvm{margin-bottom:18px}.ports-bar.svelte-15fxkvm{display:flex;justify-content:space-between;align-items: center}.rebuild.svelte-15fxkvm{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.08em;background:var(--fill-ink);color:var(--fill);border:1px solid var(--fill-ink);cursor:pointer;padding:4px 9px;font-size:10px;font-weight:600}.rebuild.svelte-15fxkvm:hover:not(:disabled){color:var(--fill-ink);background:0 0}.rebuild.svelte-15fxkvm:disabled{opacity:var(--dim-panel);cursor:not-allowed}.ports-body.svelte-15fxkvm{background:var(--bg-card);padding:12px 14px 14px}.port-list.svelte-15fxkvm{list-style:none;display:flex;flex-direction:column;gap:6px;margin:0 0 12px;padding:0}.port-list.svelte-15fxkvm li:where(.svelte-15fxkvm){display:flex;font-family:var(--font-mono);align-items: center;gap:8px;font-size:13px}.port-list.svelte-15fxkvm .cp:where(.svelte-15fxkvm){color:var(--ink);font-weight:600}.port-list.svelte-15fxkvm .arr:where(.svelte-15fxkvm){color:var(--ink-faint)}.port-list.svelte-15fxkvm a:where(.svelte-15fxkvm){display:inline-flex;color:var(--ink);text-decoration:none;border-bottom:1px solid var(--ink-faint);align-items: center;gap:4px}.port-list.svelte-15fxkvm a:where(.svelte-15fxkvm):hover{border-bottom-color:var(--ink)}.rm.svelte-15fxkvm{border:1px solid var(--ink-faint);color:var(--ink-soft);cursor:pointer;background:0 0;width:20px;height:20px;margin-left:auto;font-size:15px;line-height:1}.rm.svelte-15fxkvm:hover{border-color:var(--danger);color:var(--danger)}.empty.svelte-15fxkvm{font-family:var(--font-mono);color:var(--ink-faint);margin:0 0 12px;font-size:12px}.add.svelte-15fxkvm{display:flex;gap:8px}.add.svelte-15fxkvm input:where(.svelte-15fxkvm){font-family:var(--font-mono);border:1px solid var(--ink);background:var(--bg);color:var(--ink);outline:none;flex:1;min-width:0;padding:6px 9px;font-size:13px}.add.svelte-15fxkvm button:where(.svelte-15fxkvm){font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.06em;border:1px solid var(--edge);background:var(--bg-card);color:var(--ink);cursor:pointer;padding:6px 14px;font-size:12px;font-weight:600}.add.svelte-15fxkvm button:where(.svelte-15fxkvm):hover{background:var(--fill);border-color:var(--fill);color:var(--fill-ink)}.port-err.svelte-15fxkvm{font-family:var(--font-mono);color:var(--danger);margin:10px 0 0;font-size:12px}.hint.svelte-15fxkvm{font-family:var(--font-mono);color:var(--ink-faint);margin:10px 0 0;font-size:11px}.hint.pending.svelte-15fxkvm{color:var(--ink-soft)}.hint.svelte-15fxkvm code:where(.svelte-15fxkvm){color:var(--ink)}.logwrap.svelte-15fxkvm{overflow:hidden}.log-bar.svelte-15fxkvm{display:flex;justify-content:space-between;align-items: center}.log-actions.svelte-15fxkvm{display:flex;align-items: center;gap:6px}.copy.svelte-15fxkvm{display:inline-flex;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.08em;background:var(--fill-ink);color:var(--fill);border:1px solid var(--fill-ink);cursor:pointer;align-items: center;gap:5px;padding:4px 9px;font-size:10px;font-weight:600}.copy.svelte-15fxkvm:hover:not(:disabled),.copy.active.svelte-15fxkvm{color:var(--fill-ink);background:0 0}.dot.svelte-15fxkvm{background:var(--attn-done);border-radius:50%;flex:none;width:6px;height:6px}.copy.svelte-15fxkvm:disabled{opacity:var(--dim-panel);cursor:not-allowed}.logs.svelte-15fxkvm{position:relative;background:repeating-linear-gradient(0deg,var(--screen-line)0 1px,transparent 1px 3px),var(--screen-bg);color:var(--screen-ink);overflow:auto;overflow-anchor:none;height:calc(100vh - 320px);min-height:360px;padding:14px}.logs.svelte-15fxkvm pre:where(.svelte-15fxkvm){font-family:var(--font-mono);white-space:pre-wrap;word-break:break-word;margin:0;font-size:12.5px;line-height:1.5}@keyframes svelte-15fxkvm-lcd-blink{50%{background:0 0}}.caret.svelte-15fxkvm{display:inline-block;background:var(--screen-ink);vertical-align:text-bottom;animation:svelte-15fxkvm-lcd-blink 1.05s steps(1)infinite;width:.6em;height:1.05em;margin-left:2px}.err.svelte-15fxkvm{background:var(--bg-card);color:var(--ink);border-top:2px solid var(--ink);font-family:var(--font-mono);padding:12px 14px;font-size:13px}
@@ -0,0 +1 @@
1
+ .cog.svelte-1e745g8{display:inline-flex;border:1px solid var(--edge);background:var(--bg-card);color:var(--ink);justify-content:center;align-items: center;width:32px;height:32px}.cog.svelte-1e745g8:hover{background:var(--fill);border-color:var(--fill);color:var(--fill-ink)}
@@ -1 +1 @@
1
- .page.svelte-1n6ht58{display:flex;flex-direction:column;min-height:100vh}.title.svelte-1n6ht58{display:inline-flex;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.08em;color:var(--ink-soft);align-items: center;padding:0 14px;font-size:12px}.content.svelte-1n6ht58{display:flex;flex-direction:column;flex:1;align-items: center;gap:16px;padding:32px 20px}.card.svelte-1n6ht58{background:var(--bg-card);border:1px solid var(--rule);width:100%;max-width:560px;height:max-content}.danger-card.svelte-1n6ht58{border-color:var(--danger)}details.advanced.svelte-1n6ht58>summary:where(.svelte-1n6ht58){display:flex;cursor:pointer;list-style:none;font-family:var(--font-mono);align-items: center;gap:10px;padding:14px 16px}details.advanced.svelte-1n6ht58>summary:where(.svelte-1n6ht58)::-webkit-details-marker{display:none}details.advanced.svelte-1n6ht58>summary:where(.svelte-1n6ht58) .name:where(.svelte-1n6ht58){font-size:13px}details.advanced.svelte-1n6ht58>summary:where(.svelte-1n6ht58) .hint:where(.svelte-1n6ht58){color:var(--ink-soft);font-size:12px}details.advanced.svelte-1n6ht58>summary:where(.svelte-1n6ht58):after{content:"▸";color:var(--ink-soft);margin-left:auto}details.advanced[open].svelte-1n6ht58>summary:where(.svelte-1n6ht58):after{content:"▾"}.disabled-card.svelte-1n6ht58{opacity:.55;pointer-events:none}.danger-card.svelte-1n6ht58 .btn{white-space:nowrap;flex:none}.version.svelte-1n6ht58{font-family:var(--font-mono);letter-spacing:.08em;color:var(--ink-soft);font-size:11px}.shutting.svelte-1n6ht58{font-family:var(--font-mono);color:var(--danger);text-align:right;flex:none;max-width:200px;font-size:12px;line-height:1.4}.row.svelte-1n6ht58{display:flex;justify-content:space-between;align-items: center;gap:16px;padding:18px}.row.divided.svelte-1n6ht58{border-top:1px solid var(--rule);align-items: flex-start}.row.divided.svelte-1n6ht58 .btn{white-space:nowrap;flex:none}.sub.svelte-1n6ht58{padding:0 18px 14px}code.svelte-1n6ht58{font-family:var(--font-mono);background:var(--bg);border:1px solid var(--rule);border-radius:3px;padding:1px 4px;font-size:.92em}.label.svelte-1n6ht58{display:flex;color:var(--ink);align-items: flex-start;gap:12px;min-width:0}.label.svelte-1n6ht58>svg{flex:none}.text.svelte-1n6ht58{min-width:0}.name.svelte-1n6ht58{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.06em;font-size:13px}.arch.svelte-1n6ht58{letter-spacing:.04em;color:var(--ink-soft);border:1px solid var(--rule);vertical-align:middle;border-radius:3px;margin-left:8px;padding:2px 6px;font-size:11px}.tip.svelte-1n6ht58{color:var(--ink-soft);background:color-mix(in srgb,var(--info)10%,transparent);border:1px solid color-mix(in srgb,var(--info)35%,transparent);border-radius:4px;width:100%;margin-top:4px;padding:8px 10px}.desc.svelte-1n6ht58{font-family:var(--font-mono);color:var(--ink-faint);margin-top:4px;font-size:12px;line-height:1.4}.image-row.svelte-1n6ht58,.token-row.svelte-1n6ht58{flex-wrap:wrap}.image-controls.svelte-1n6ht58{display:flex;flex:1;justify-content:flex-end;align-items: center;gap:8px;min-width:220px}.image-input.svelte-1n6ht58{font-family:var(--font-mono);color:var(--ink);background:var(--bg);border:1px solid var(--rule);flex:1;min-width:0;padding:8px 10px;font-size:12px}.image-input.svelte-1n6ht58:focus-visible{outline:2px solid var(--ink);outline-offset:1px}.image-controls.svelte-1n6ht58 .btn{flex:none}.msg.svelte-1n6ht58{font-family:var(--font-mono);width:100%;margin-top:2px;font-size:12px;line-height:1.4}.msg.error.svelte-1n6ht58{color:var(--danger)}.msg.ok.svelte-1n6ht58{color:var(--ink-soft)}.pets.svelte-1n6ht58{display:grid;grid-template-columns:repeat(auto-fill,minmax(44px,1fr));gap:6px}.pets.svelte-1n6ht58 form:where(.svelte-1n6ht58){display:contents}.pet.svelte-1n6ht58:disabled{cursor:progress}.pet.svelte-1n6ht58{display:flex;appearance:none;cursor:pointer;background:0 0;border:1px solid #0000;justify-content:center;align-items: center;padding:4px}.pet.svelte-1n6ht58:hover{border-color:var(--rule)}.pet.selected.svelte-1n6ht58{border-color:var(--attn-done);background:var(--switch-on-bg)}.pet.svelte-1n6ht58:focus-visible{outline:2px solid var(--ink);outline-offset:1px}.mode-toggle.svelte-1n6ht58{display:flex;border:1px solid var(--ink);flex:none}.mode-btn.svelte-1n6ht58{display:inline-flex;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.05em;background:var(--bg);color:var(--ink);cursor:pointer;border:none;align-items: center;gap:6px;padding:7px 14px;font-size:12px;font-weight:700}.mode-btn.svelte-1n6ht58+.mode-btn:where(.svelte-1n6ht58){border-left:1px solid var(--ink)}.mode-btn.active.svelte-1n6ht58{background:var(--ink);color:var(--bg)}.mode-btn.svelte-1n6ht58:disabled{cursor:not-allowed}.switch.svelte-1n6ht58{position:relative;cursor:pointer;flex:none}.switch.svelte-1n6ht58 input:where(.svelte-1n6ht58){position:absolute;opacity:0;cursor:pointer;margin:0;inset:0}.track.svelte-1n6ht58{display:block;border:1px solid var(--rule);background:var(--bg);border-radius:999px;width:44px;height:24px;transition:background .15s}.thumb.svelte-1n6ht58{display:block;background:var(--ink-faint);border-radius:999px;width:18px;height:18px;margin:2px;transition:transform .15s,background .15s}.switch.svelte-1n6ht58 input:where(.svelte-1n6ht58):checked+.track:where(.svelte-1n6ht58){background:var(--switch-on-bg)}.switch.svelte-1n6ht58 input:where(.svelte-1n6ht58):checked+.track:where(.svelte-1n6ht58) .thumb:where(.svelte-1n6ht58){background:var(--ink);transform:translate(20px)}.switch.svelte-1n6ht58 input:where(.svelte-1n6ht58):focus-visible+.track:where(.svelte-1n6ht58){outline:2px solid var(--ink);outline-offset:2px}.model-fields.svelte-1n6ht58{display:flex;flex-direction:column;flex:1;gap:6px;min-width:220px}.model-row.svelte-1n6ht58{display:flex;align-items: center;gap:8px}.model-label.svelte-1n6ht58{font-family:var(--font-mono);color:var(--ink-soft);text-align:right;flex:none;width:72px;font-size:11px}.model-row.svelte-1n6ht58 .image-input:where(.svelte-1n6ht58){flex:1}.model-save-row.svelte-1n6ht58{display:flex;justify-content:flex-end;margin-top:4px}.var-row.svelte-1n6ht58{flex-direction:column;align-items:stretch;gap:10px}.var-list.svelte-1n6ht58{display:flex;flex-direction:column;gap:6px}.var-item.svelte-1n6ht58{display:flex;background:var(--bg);border:1px solid var(--rule);align-items: center;gap:8px;padding:6px 8px}.var-name.svelte-1n6ht58{font-family:var(--font-mono);color:var(--ink);word-break:break-all;flex:1;min-width:0;font-size:12px}.var-status.svelte-1n6ht58{font-family:var(--font-mono);letter-spacing:.04em;color:var(--danger);flex:none;font-size:11px}.var-status.present.svelte-1n6ht58{color:var(--ink-soft)}.var-remove.svelte-1n6ht58{display:inline-flex;color:var(--ink-soft);border:1px solid var(--rule);cursor:pointer;background:0 0;flex:none;justify-content:center;align-items: center;width:22px;height:22px;padding:0}.var-remove.svelte-1n6ht58:hover:not(:disabled){color:var(--danger);border-color:var(--danger)}.var-remove.svelte-1n6ht58:disabled{opacity:.4;cursor:not-allowed}.var-empty.svelte-1n6ht58{font-family:var(--font-mono);color:var(--ink-faint);font-size:12px}.var-add.svelte-1n6ht58{display:flex;gap:8px}.var-add.svelte-1n6ht58 .btn{flex:none}
1
+ .page.svelte-1n6ht58{display:flex;flex-direction:column;min-height:100vh}.title.svelte-1n6ht58{display:inline-flex;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.08em;color:var(--ink-soft);align-items: center;padding:0 14px;font-size:12px}.content.svelte-1n6ht58{display:flex;flex-direction:column;flex:1;align-items: center;gap:16px;padding:32px 20px}.card.svelte-1n6ht58{background:var(--bg-card);border:1px solid var(--rule);width:100%;max-width:560px;height:max-content}.danger-card.svelte-1n6ht58{border-color:var(--danger)}details.advanced.svelte-1n6ht58>summary:where(.svelte-1n6ht58){display:flex;cursor:pointer;list-style:none;font-family:var(--font-mono);align-items: center;gap:10px;padding:14px 16px}details.advanced.svelte-1n6ht58>summary:where(.svelte-1n6ht58)::-webkit-details-marker{display:none}details.advanced.svelte-1n6ht58>summary:where(.svelte-1n6ht58) .name:where(.svelte-1n6ht58){font-size:13px}details.advanced.svelte-1n6ht58>summary:where(.svelte-1n6ht58) .hint:where(.svelte-1n6ht58){color:var(--ink-soft);font-size:12px}details.advanced.svelte-1n6ht58>summary:where(.svelte-1n6ht58):after{content:"▸";color:var(--ink-soft);margin-left:auto}details.advanced[open].svelte-1n6ht58>summary:where(.svelte-1n6ht58):after{content:"▾"}.disabled-card.svelte-1n6ht58{opacity:.55;pointer-events:none}.danger-card.svelte-1n6ht58 .btn{white-space:nowrap;flex:none}.version.svelte-1n6ht58{font-family:var(--font-mono);letter-spacing:.08em;color:var(--ink-soft);font-size:11px}.shutting.svelte-1n6ht58{font-family:var(--font-mono);color:var(--danger);text-align:right;flex:none;max-width:200px;font-size:12px;line-height:1.4}.row.svelte-1n6ht58{display:flex;justify-content:space-between;align-items: center;gap:16px;padding:18px}.row.divided.svelte-1n6ht58{border-top:1px solid var(--rule);align-items: flex-start}.row.divided.svelte-1n6ht58 .btn{white-space:nowrap;flex:none}.sub.svelte-1n6ht58{padding:0 18px 14px}code.svelte-1n6ht58{font-family:var(--font-mono);background:var(--bg);border:1px solid var(--rule);border-radius:3px;padding:1px 4px;font-size:.92em}.label.svelte-1n6ht58{display:flex;color:var(--ink);align-items: flex-start;gap:12px;min-width:0}.label.svelte-1n6ht58>svg{flex:none}.text.svelte-1n6ht58{min-width:0}.name.svelte-1n6ht58{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.06em;font-size:13px}.arch.svelte-1n6ht58{letter-spacing:.04em;color:var(--ink-soft);border:1px solid var(--rule);vertical-align:middle;border-radius:3px;margin-left:8px;padding:2px 6px;font-size:11px}.tip.svelte-1n6ht58{color:var(--ink-soft);background:color-mix(in srgb,var(--info)10%,transparent);border:1px solid color-mix(in srgb,var(--info)35%,transparent);border-radius:4px;width:100%;margin-top:4px;padding:8px 10px}.desc.svelte-1n6ht58{font-family:var(--font-mono);color:var(--ink-faint);margin-top:4px;font-size:12px;line-height:1.4}.image-row.svelte-1n6ht58,.token-row.svelte-1n6ht58{flex-wrap:wrap}.image-controls.svelte-1n6ht58{display:flex;flex:1;justify-content:flex-end;align-items: center;gap:8px;min-width:220px}.image-input.svelte-1n6ht58{font-family:var(--font-mono);color:var(--ink);background:var(--bg);border:1px solid var(--rule);flex:1;min-width:0;padding:8px 10px;font-size:12px}.image-input.svelte-1n6ht58:focus-visible{outline:2px solid var(--ink);outline-offset:1px}.image-controls.svelte-1n6ht58 .btn{flex:none}.msg.svelte-1n6ht58{font-family:var(--font-mono);width:100%;margin-top:2px;font-size:12px;line-height:1.4}.msg.error.svelte-1n6ht58{color:var(--danger)}.msg.ok.svelte-1n6ht58{color:var(--ink-soft)}.pets.svelte-1n6ht58{display:grid;grid-template-columns:repeat(auto-fill,minmax(44px,1fr));gap:6px}.pets.svelte-1n6ht58 form:where(.svelte-1n6ht58){display:contents}.pet.svelte-1n6ht58:disabled{cursor:progress}.pet.svelte-1n6ht58{display:flex;appearance:none;cursor:pointer;background:0 0;border:1px solid #0000;justify-content:center;align-items: center;padding:4px}.pet.svelte-1n6ht58:hover{border-color:var(--rule)}.pet.selected.svelte-1n6ht58{border-color:var(--attn-done);background:var(--switch-on-bg)}.pet.svelte-1n6ht58:focus-visible{outline:2px solid var(--ink);outline-offset:1px}.mode-toggle.svelte-1n6ht58{display:flex;border:1px solid var(--edge);flex:none}.mode-btn.svelte-1n6ht58{display:inline-flex;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.05em;background:var(--bg);color:var(--ink);cursor:pointer;border:none;align-items: center;gap:6px;padding:7px 14px;font-size:12px;font-weight:700}.mode-btn.svelte-1n6ht58+.mode-btn:where(.svelte-1n6ht58){border-left:1px solid var(--edge)}.mode-btn.active.svelte-1n6ht58{background:var(--fill);color:var(--fill-ink)}.mode-btn.svelte-1n6ht58:disabled{cursor:not-allowed}.switch.svelte-1n6ht58{position:relative;cursor:pointer;flex:none}.switch.svelte-1n6ht58 input:where(.svelte-1n6ht58){position:absolute;opacity:0;cursor:pointer;margin:0;inset:0}.track.svelte-1n6ht58{display:block;border:1px solid var(--rule);background:var(--bg);border-radius:999px;width:44px;height:24px;transition:background .15s}.thumb.svelte-1n6ht58{display:block;background:var(--ink-faint);border-radius:999px;width:18px;height:18px;margin:2px;transition:transform .15s,background .15s}.switch.svelte-1n6ht58 input:where(.svelte-1n6ht58):checked+.track:where(.svelte-1n6ht58){background:var(--switch-on-bg)}.switch.svelte-1n6ht58 input:where(.svelte-1n6ht58):checked+.track:where(.svelte-1n6ht58) .thumb:where(.svelte-1n6ht58){background:var(--ink);transform:translate(20px)}.switch.svelte-1n6ht58 input:where(.svelte-1n6ht58):focus-visible+.track:where(.svelte-1n6ht58){outline:2px solid var(--ink);outline-offset:2px}.model-fields.svelte-1n6ht58{display:flex;flex-direction:column;flex:1;gap:6px;min-width:220px}.model-row.svelte-1n6ht58{display:flex;align-items: center;gap:8px}.model-label.svelte-1n6ht58{font-family:var(--font-mono);color:var(--ink-soft);text-align:right;flex:none;width:72px;font-size:11px}.model-row.svelte-1n6ht58 .image-input:where(.svelte-1n6ht58){flex:1}.model-save-row.svelte-1n6ht58{display:flex;justify-content:flex-end;margin-top:4px}.var-row.svelte-1n6ht58{flex-direction:column;align-items:stretch;gap:10px}.var-list.svelte-1n6ht58{display:flex;flex-direction:column;gap:6px}.var-item.svelte-1n6ht58{display:flex;background:var(--bg);border:1px solid var(--rule);align-items: center;gap:8px;padding:6px 8px}.var-name.svelte-1n6ht58{font-family:var(--font-mono);color:var(--ink);word-break:break-all;flex:1;min-width:0;font-size:12px}.var-status.svelte-1n6ht58{font-family:var(--font-mono);letter-spacing:.04em;color:var(--danger);flex:none;font-size:11px}.var-status.present.svelte-1n6ht58{color:var(--ink-soft)}.var-remove.svelte-1n6ht58{display:inline-flex;color:var(--ink-soft);border:1px solid var(--rule);cursor:pointer;background:0 0;flex:none;justify-content:center;align-items: center;width:22px;height:22px;padding:0}.var-remove.svelte-1n6ht58:hover:not(:disabled){color:var(--danger);border-color:var(--danger)}.var-remove.svelte-1n6ht58:disabled{opacity:var(--dim);cursor:not-allowed}.var-empty.svelte-1n6ht58{font-family:var(--font-mono);color:var(--ink-faint);font-size:12px}.var-add.svelte-1n6ht58{display:flex;gap:8px}.var-add.svelte-1n6ht58 .btn{flex:none}
@@ -0,0 +1 @@
1
+ .status.svelte-1hqr9xd{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.1em;border:1px solid var(--edge);white-space:nowrap;padding:3px 7px;font-size:10px;font-weight:600}.status.running.svelte-1hqr9xd{background:var(--fill);color:var(--fill-ink);border-color:var(--fill)}.status.stopped.svelte-1hqr9xd{color:var(--ink-soft);border-color:var(--ink-faint);background:0 0}.status.creating.svelte-1hqr9xd{background:var(--fill);color:var(--fill-ink);border-color:var(--fill);animation:svelte-1hqr9xd-lcd-blink 1.1s steps(1)infinite}.status.error.svelte-1hqr9xd{background:var(--danger);color:var(--bg);border-color:var(--danger);font-weight:700}@keyframes svelte-1hqr9xd-lcd-blink{50%{background:0 0;color:var(--fill)}}
@@ -0,0 +1 @@
1
+ .term.svelte-ui3nvu{background:var(--screen-bg);color:var(--screen-ink);box-sizing:border-box;width:100%;height:100%;padding:6px 8px}.term.svelte-ui3nvu .xterm,.term.svelte-ui3nvu .xterm-viewport{height:100%}.overlay.svelte-ui3nvu{position:absolute;display:flex;pointer-events:none;align-items: center;gap:8px;top:6px;right:8px}.status.svelte-ui3nvu{font-family:var(--font-mono);letter-spacing:.05em;text-transform:uppercase;color:var(--ink-faint);font-size:11px}.overlay.svelte-ui3nvu button{pointer-events:auto;appearance:none;display:inline-flex;cursor:pointer;background:var(--bg);border:1px solid var(--rule);color:var(--ink);opacity:.3;justify-content:center;align-items: center;width:24px;height:24px;padding:0;transition:opacity .15s}.overlay.svelte-ui3nvu button:hover,.overlay.svelte-ui3nvu button[aria-pressed=true]{opacity:1;background:var(--fill);color:var(--fill-ink)}.overlay.svelte-ui3nvu button:focus-visible{opacity:1;background:var(--fill);color:var(--fill-ink)}@media (prefers-reduced-motion:reduce){.overlay.svelte-ui3nvu button{transition:none}}
@@ -0,0 +1 @@
1
+ .picker.svelte-3gcwuj{display:inline-flex;border:1px solid var(--edge);background:var(--bg-card);flex:none}.segment.svelte-3gcwuj{display:inline-flex;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.06em;color:var(--ink);cursor:pointer;background:0 0;border:none;align-items: center;gap:6px;padding:7px 12px;font-size:12px;font-weight:600}.segment.svelte-3gcwuj+.segment:where(.svelte-3gcwuj){border-left:1px solid var(--edge)}.segment.svelte-3gcwuj:hover:not(.active){background:var(--fill);color:var(--fill-ink)}.segment.active.svelte-3gcwuj{background:var(--fill);color:var(--fill-ink);cursor:default;font-weight:700}.segment.svelte-3gcwuj:focus-visible{outline:2px solid var(--ink);outline-offset:-2px}.crt.svelte-3gcwuj{position:fixed;z-index:9999;pointer-events:none;inset:0}.bar.svelte-3gcwuj{position:absolute;background:#000;height:50%;left:0;right:0}.bar.top.svelte-3gcwuj{transform-origin:top center;top:0}.bar.bottom.svelte-3gcwuj{transform-origin:bottom center;bottom:0}.line.svelte-3gcwuj{position:absolute;background:var(--screen-ink);box-shadow:0 0 14px 3px var(--screen-ink);opacity:0;height:2px;margin-top:-1px;top:50%;left:0;right:0}.crt.collapse.svelte-3gcwuj .bar:where(.svelte-3gcwuj){animation:svelte-3gcwuj-crt-collapse .2s cubic-bezier(.7,0,.84,0)forwards}.crt.collapse.svelte-3gcwuj .line:where(.svelte-3gcwuj){animation:svelte-3gcwuj-crt-line-out .32s linear forwards}.crt.restore.svelte-3gcwuj .bar:where(.svelte-3gcwuj){animation:svelte-3gcwuj-crt-open .26s cubic-bezier(.16,1,.3,1).12s both}.crt.restore.svelte-3gcwuj .line:where(.svelte-3gcwuj){animation:svelte-3gcwuj-crt-line-in .38s linear both}@keyframes svelte-3gcwuj-crt-collapse{0%{transform:scaleY(0)}to{transform:scaleY(1)}}@keyframes svelte-3gcwuj-crt-open{0%{transform:scaleY(1)}to{transform:scaleY(0)}}@keyframes svelte-3gcwuj-crt-line-out{0%,55%{opacity:0;transform:scaleX(1)}62%,75%{opacity:1;transform:scaleX(1)}to{opacity:0;transform:scaleX(.015)}}@keyframes svelte-3gcwuj-crt-line-in{0%{opacity:0;transform:scaleX(.015)}12%{opacity:1;transform:scaleX(.015)}32%,55%{opacity:1;transform:scaleX(1)}to{opacity:0;transform:scaleX(1)}}
@@ -0,0 +1 @@
1
+ ALTER TABLE instances ADD COLUMN config_migrated INTEGER NOT NULL DEFAULT 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codebay",
3
- "version": "0.10.1",
3
+ "version": "0.11.0",
4
4
  "description": "Web UI for spinning up isolated devcontainer instances from any local folder, each with a browser-based VS Code (code-server) — built for parallel Claude Code workflows.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -62,30 +62,30 @@
62
62
  "@devcontainers/cli": "^0.88.0",
63
63
  "@fontsource-variable/doto": "^5.3.0",
64
64
  "@fontsource-variable/jetbrains-mono": "^5.3.0",
65
- "@lucide/svelte": "^1.28.0",
65
+ "@lucide/svelte": "^1.31.0",
66
66
  "@xterm/addon-fit": "^0.11.0",
67
67
  "@xterm/xterm": "^6.0.0",
68
68
  "@zihaolam/bun-sqlite-migrations": "^1.0.3",
69
69
  "dockerode": "^5.0.1",
70
70
  "mochi-framework": "^0.9.1",
71
- "svelte": "^5.56.8",
71
+ "svelte": "^5.56.9",
72
72
  "svelte-french-toast": "^1.2.0"
73
73
  },
74
74
  "devDependencies": {
75
75
  "@eslint/js": "^10.0.1",
76
76
  "@types/bun": "1.3.14",
77
77
  "@types/dockerode": "^4.0.1",
78
- "eslint": "^10.8.0",
79
- "eslint-plugin-svelte": "^3.22.0",
80
- "globals": "^17.8.0",
78
+ "eslint": "^10.8.1",
79
+ "eslint-plugin-svelte": "^3.23.0",
80
+ "globals": "^17.11.0",
81
81
  "prettier": "^3.9.6",
82
82
  "prettier-plugin-svelte": "^4.1.1",
83
83
  "svelte-check": "4.7.4",
84
84
  "typescript": "^6.0.3",
85
- "typescript-eslint": "^8.65.0"
85
+ "typescript-eslint": "^8.67.0"
86
86
  },
87
87
  "resolutions": {
88
88
  "msgpackr-extract": "npm:@mochi-framework/msgpackr-extract-stub@*",
89
- "svelte": "5.56.8"
89
+ "svelte": "5.56.9"
90
90
  }
91
91
  }
@@ -36,7 +36,7 @@
36
36
  border-right: 1px solid var(--rule);
37
37
  }
38
38
  .home:hover {
39
- background: var(--ink);
40
- color: var(--bg);
39
+ background: var(--fill);
40
+ color: var(--fill-ink);
41
41
  }
42
42
  </style>
@@ -1,7 +1,9 @@
1
1
  <script lang="ts">
2
2
  import { ideUrl, type Instance, type InstanceFilter, type Preflight } from '../types.ts';
3
3
  import { findAvatar, type AvatarArt } from '../avatars/index.ts';
4
+ import { tick } from 'svelte';
4
5
  import { SvelteSet } from 'svelte/reactivity';
6
+ import { nextTabIndex } from '../lib/tab-nav.ts';
5
7
  import DashboardView from './DashboardView.svelte';
6
8
  import IdeBar from './IdeBar.svelte';
7
9
  import IdeLoader from './IdeLoader.svelte';
@@ -9,7 +11,9 @@
9
11
  import { playChime, unlockAudio } from '../sound.ts';
10
12
  import { liveStream } from '../live.ts';
11
13
  import { apiPost } from '../api.ts';
14
+ import { syncTheme } from '../theme.ts';
12
15
  import toast, { Toaster } from 'svelte-french-toast';
16
+ import { TOAST_OPTIONS } from '../toast.ts';
13
17
 
14
18
  // `snapshot` seeds the live state so neither view renders a loading flash first.
15
19
  let {
@@ -42,6 +46,8 @@
42
46
  let loaded = $state(snapshot.length > 0);
43
47
  const running = $derived(instances.filter((i) => i.status === 'running'));
44
48
 
49
+ // Seeded from the SSR snapshot like `instances` above — the live stream overwrites it.
50
+ // svelte-ignore state_referenced_locally
45
51
  let attention = $state<Record<string, 'done' | 'waiting' | null>>(
46
52
  Object.fromEntries(snapshot.map((i) => [i.id, i.attention]))
47
53
  );
@@ -179,6 +185,60 @@
179
185
  document.title = onIde && activeInstance ? `${activeInstance.name} — Codebay` : 'Codebay';
180
186
  });
181
187
 
188
+ // Alt+1-9 switches tabs. Alt, specifically: Cmd/Ctrl+digit is reserved by the browser
189
+ // for its own tabs and can't be intercepted, and Ctrl+Alt is AltGr on many European
190
+ // layouts, so it would collide with typing punctuation.
191
+ function jumpToTab(e: KeyboardEvent, fromFrame: boolean) {
192
+ if (!e.altKey || e.ctrlKey || e.metaKey || editingId) return;
193
+ // `code`, not `key`: Alt+digit emits punctuation on macOS layouts.
194
+ const digit = /^Digit([1-9])$/.exec(e.code)?.[1];
195
+ if (!digit) return;
196
+ const next = nextTabIndex(
197
+ running.findIndex((i) => i.id === active),
198
+ digit,
199
+ running.length
200
+ );
201
+ const target = next === null ? undefined : running[next];
202
+ if (!target) return;
203
+ e.preventDefault();
204
+ // Stops the editor acting on the same keystroke as well.
205
+ e.stopPropagation();
206
+ navigate(`/ide/${target.id}`);
207
+ // Came from inside an editor, so land inside the next one rather than dumping
208
+ // focus on the body — after a tick, once the destination pane is no longer hidden.
209
+ if (fromFrame) void tick().then(() => frames[target.id]?.contentWindow?.focus());
210
+ }
211
+
212
+ // Joined rather than an array so the value compares equal across reconcile ticks —
213
+ // otherwise the effect below would tear down and re-add every listener every few
214
+ // seconds, with a window each time where a keystroke lands on nothing.
215
+ const framedTabIds = $derived(
216
+ running
217
+ .filter((i) => i.mode !== 'terminal' && loadedFrames.has(i.id))
218
+ .map((i) => i.id)
219
+ .join(' ')
220
+ );
221
+
222
+ // A focused iframe never bubbles keydown to the parent, so the shortcut has to be
223
+ // installed inside each editor document as well — possible only because the proxy
224
+ // serves code-server same-origin under /p/:id/. Capture phase, so it lands before
225
+ // VS Code's own handlers (and before xterm.js in the terminal panes).
226
+ $effect(() => {
227
+ if (!onIde) return;
228
+ function listen(target: Window, fromFrame: boolean) {
229
+ const handler = (e: KeyboardEvent) => jumpToTab(e, fromFrame);
230
+ target.addEventListener('keydown', handler, { capture: true });
231
+ return () => target.removeEventListener('keydown', handler, { capture: true });
232
+ }
233
+ const detach = [listen(window, false)];
234
+ // A reloaded iframe gets a fresh Window, and the old listener dies with it.
235
+ for (const id of framedTabIds.split(' ').filter(Boolean)) {
236
+ const frameWindow = frames[id]?.contentWindow;
237
+ if (frameWindow) detach.push(listen(frameWindow, true));
238
+ }
239
+ return () => detach.forEach((off) => off());
240
+ });
241
+
182
242
  // Browsers block audio until the page has been interacted with.
183
243
  $effect(() => {
184
244
  window.addEventListener('pointerdown', unlockAudio);
@@ -210,6 +270,10 @@
210
270
  livePreflight = { ...livePreflight, defaultMode: msg.data.mode };
211
271
  return;
212
272
  }
273
+ if (msg.type === 'theme') {
274
+ syncTheme(msg.data.value);
275
+ return;
276
+ }
213
277
  if (msg.type === 'health') {
214
278
  // A tick in flight when a rebuild starts probes the *old* container and
215
279
  // reports it accessible, which would mount the iframe against the replacement too early.
@@ -303,7 +367,12 @@
303
367
  <div class="panes" class:hidden={!onIde}>
304
368
  {#each running as inst (inst.id)}
305
369
  {#if visited.has(inst.id)}
306
- <div class="pane" class:active={inst.id === active}>
370
+ <div
371
+ class="pane"
372
+ class:active={inst.id === active}
373
+ role="tabpanel"
374
+ aria-labelledby="tab-{inst.id}"
375
+ >
307
376
  {#if mountable(inst.id)}
308
377
  {#if inst.mode === 'terminal'}
309
378
  <TerminalSplit
@@ -342,12 +411,7 @@
342
411
  </div>
343
412
 
344
413
  <!-- Hoisted out of DashboardView so IDE-route toasts have somewhere to render too. -->
345
- <Toaster
346
- toastOptions={{
347
- style:
348
- 'border:1px solid var(--ink); background:var(--bg-card); color:var(--ink); box-shadow:4px 4px 0 var(--ink); font-family:var(--font-mono); font-size:13px;'
349
- }}
350
- />
414
+ <Toaster toastOptions={TOAST_OPTIONS} />
351
415
 
352
416
  <style>
353
417
  /* The IDE route fills the viewport; the dashboard stays in normal scrolling flow. */