localdeck 1.4.0 → 1.5.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.
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ import {
31
31
  unreachableListenerMessage,
32
32
  waitForReadiness,
33
33
  wrapper_default
34
- } from "./index-316fp4p2.js";
34
+ } from "./index-tv699dzb.js";
35
35
 
36
36
  // src/index.ts
37
37
  import { spawn as spawn2 } from "node:child_process";
@@ -915,13 +915,13 @@ async function main(argv, overrides = {}) {
915
915
  case "--update":
916
916
  if (rest.length)
917
917
  throw new Error("Usage: localdeck --update");
918
- return (await import("./update-w6vc3sdy.js")).updateLocalDeck();
918
+ return (await import("./update-a6z3akjx.js")).updateLocalDeck();
919
919
  case "up":
920
920
  return cmdUp(rest, dependencies);
921
921
  case "init":
922
922
  return cmdInit(rest, dependencies);
923
923
  case "mcp":
924
- return (await import("./mcp-h8gf5pgj.js")).runMcp(rest);
924
+ return (await import("./mcp-c138pjc5.js")).runMcp(rest);
925
925
  case "doctor":
926
926
  return cmdDoctor(rest);
927
927
  case "forward":
@@ -9,7 +9,7 @@ import {
9
9
  listProjectSecrets,
10
10
  redactDiagnostic,
11
11
  resolveProjectSecrets
12
- } from "./index-316fp4p2.js";
12
+ } from "./index-tv699dzb.js";
13
13
 
14
14
  // ../../node_modules/.bun/ajv@8.20.0/node_modules/ajv/dist/compile/codegen/code.js
15
15
  var require_code = __commonJS((exports) => {
@@ -33935,20 +33935,20 @@ function sanitize(value, secrets) {
33935
33935
  }
33936
33936
  return value;
33937
33937
  }
33938
- function largestString(value) {
33938
+ function largestString(value, preserveItems = false) {
33939
33939
  if (!value || typeof value !== "object")
33940
33940
  return;
33941
33941
  let largest;
33942
33942
  for (const [key2, item] of Object.entries(value)) {
33943
- const candidate = typeof item === "string" && key2 !== "password" ? { text: item, replace: (text) => {
33943
+ const candidate = typeof item === "string" && key2 !== "password" && !/cursor$/i.test(key2) && !(preserveItems && /^(id|service|serviceKey)$/i.test(key2)) ? { text: item, replace: (text) => {
33944
33944
  Reflect.set(value, key2, text);
33945
- } } : largestString(item);
33945
+ } } : largestString(item, preserveItems);
33946
33946
  if (candidate && (!largest || candidate.text.length > largest.text.length))
33947
33947
  largest = candidate;
33948
33948
  }
33949
33949
  return largest;
33950
33950
  }
33951
- function result(data, secrets, isError = false, password) {
33951
+ function result(data, secrets, isError = false, password, preserveItems = false) {
33952
33952
  const clean = sanitize(data, secrets);
33953
33953
  if (password)
33954
33954
  clean.password = password;
@@ -33961,7 +33961,7 @@ function result(data, secrets, isError = false, password) {
33961
33961
  if (fits())
33962
33962
  return encode3();
33963
33963
  clean.truncated = true;
33964
- if (Array.isArray(clean.items) && clean.items.length > 1) {
33964
+ if (!preserveItems && Array.isArray(clean.items) && clean.items.length > 1) {
33965
33965
  const items = clean.items;
33966
33966
  const select = (count) => clean.retainedWindow ? items.slice(-count) : items.slice(0, count);
33967
33967
  let low = 1;
@@ -33977,7 +33977,7 @@ function result(data, secrets, isError = false, password) {
33977
33977
  clean.items = select(low);
33978
33978
  }
33979
33979
  while (!fits()) {
33980
- const largest = largestString(clean);
33980
+ const largest = largestString(clean, preserveItems);
33981
33981
  if (!largest || largest.text.length < 100) {
33982
33982
  return {
33983
33983
  content: [{ type: "text", text: JSON.stringify({ truncated: true, error: "Result exceeds output limit; narrow the query." }) }],
@@ -34000,7 +34000,7 @@ function createMcpServer(options) {
34000
34000
  const connection = await options.connect();
34001
34001
  secrets.push(...connection.secrets ?? [], ...Object.entries(process.env).flatMap(([k, v]) => /password|secret|token|api[_-]?key|credential/i.test(k) && v ? [v] : []));
34002
34002
  const response = await handler(args, connection.api, secrets);
34003
- return result(response.data, secrets, response.data.ok === false, response.password);
34003
+ return result(response.data, secrets, response.data.ok === false, response.password, name === "get_timeline");
34004
34004
  } catch (error61) {
34005
34005
  return result({ error: error61 instanceof Error ? error61.message : "LocalDeck request failed" }, secrets, true);
34006
34006
  }
@@ -34086,6 +34086,64 @@ function createMcpServer(options) {
34086
34086
  await service(api2, args.serviceKey, secrets);
34087
34087
  return { data: { serviceKey: args.serviceKey, requestId: args.requestId, response: await api2.response(args.serviceKey, args.requestId), notice } };
34088
34088
  });
34089
+ const selectedServices = exports_external.array(key).min(1).max(100).optional();
34090
+ function serviceScope(projectId, services) {
34091
+ scope(projectId);
34092
+ if (services?.some((serviceKey) => serviceKey.split(":")[0] !== projectId))
34093
+ throw new Error("Selected services must belong to the requested project");
34094
+ }
34095
+ tool("get_timeline", "Read retained project activity, with optional exact service keys, incidents filter, text query and opaque pagination cursor. Coverage describes missing evidence; absence is not proof of recovery.", { projectId: id, services: selectedServices, filter: exports_external.enum(["all", "incidents"]).optional(), query: exports_external.string().max(200).optional(), cursor: exports_external.string().max(4096).optional(), limit }, false, async (args, api2, secrets) => {
34096
+ serviceScope(args.projectId, args.services);
34097
+ await project(api2, args.projectId, secrets);
34098
+ return { data: { ...await api2.timeline(args.projectId, args), notice } };
34099
+ });
34100
+ tool("mark_baseline", "Explicitly mark current retained evidence before a debugging change. Does not start services or send requests.", { projectId: id, services: selectedServices, label: exports_external.string().max(100).optional() }, true, async (args, api2, secrets) => {
34101
+ serviceScope(args.projectId, args.services);
34102
+ await project(api2, args.projectId, secrets);
34103
+ return { data: { ...await api2.markBaseline(args.projectId, { services: args.services, label: args.label }), notice } };
34104
+ });
34105
+ tool("list_baselines", "Read saved project baseline markers.", { projectId: id }, false, async (args, api2, secrets) => {
34106
+ await project(api2, args.projectId, secrets);
34107
+ return { data: { ...await api2.baselines(args.projectId), notice } };
34108
+ });
34109
+ tool("compare_baseline", "Compare retained evidence before and after a marker. Not observed again does not mean fixed; inspect coverage and insufficientEvidence.", { projectId: id, baselineId: id }, false, async (args, api2, secrets) => {
34110
+ await project(api2, args.projectId, secrets);
34111
+ return { data: { ...await api2.compareBaseline(args.projectId, args.baselineId), notice } };
34112
+ });
34113
+ tool("list_environments", "Read Git worktree environments for a project without registering or starting them.", { projectId: id }, false, async (args, api2, secrets) => {
34114
+ await project(api2, args.projectId, secrets);
34115
+ const discovery = await api2.environments(args.projectId);
34116
+ if (options.projectId) {
34117
+ const environments = Array.isArray(discovery.environments) ? discovery.environments.filter((environment) => environment && typeof environment === "object" && ("projectId" in environment) && environment.projectId === options.projectId) : [];
34118
+ return { data: { environments, notice } };
34119
+ }
34120
+ return { data: { ...discovery, notice } };
34121
+ });
34122
+ tool("register_environment", "Explicitly remember a discovered worktree environment without starting apps. Unavailable on project-restricted MCP servers because it expands project scope.", { projectId: id, environmentId: id }, true, async (args, api2, secrets) => {
34123
+ scope(args.projectId);
34124
+ if (options.projectId)
34125
+ throw new Error("Environment registration expands project scope and is unavailable on a project-restricted MCP server");
34126
+ await project(api2, args.projectId, secrets);
34127
+ return { data: { ...await api2.registerEnvironment(args.projectId, args.environmentId), notice } };
34128
+ });
34129
+ tool("export_request", "Export a redacted reproduction of a recorded request without executing it. Inspect completeness and omitted credentials before use.", { ...serviceInput, requestId: id }, false, async (args, api2, secrets) => {
34130
+ await service(api2, args.serviceKey, secrets);
34131
+ return { data: { ...await api2.exportRequest(args.serviceKey, args.requestId), notice } };
34132
+ });
34133
+ tool("save_check", "Explicitly save a recorded GET/HEAD as a status check without running it. Credentials and arbitrary destinations cannot be supplied.", { projectId: id, ...serviceInput, requestId: id, name: exports_external.string().min(1).max(200), expectedStatus: exports_external.number().int().min(100).max(599) }, true, async (args, api2, secrets) => {
34134
+ serviceScope(args.projectId, [args.serviceKey]);
34135
+ await project(api2, args.projectId, secrets);
34136
+ await service(api2, args.serviceKey, secrets);
34137
+ return { data: { ...await api2.saveCheck(args.projectId, { serviceKey: args.serviceKey, requestId: args.requestId, name: args.name, expectedStatus: args.expectedStatus }), notice } };
34138
+ });
34139
+ tool("list_checks", "Read saved project status checks and their retained results without running requests.", { projectId: id }, false, async (args, api2, secrets) => {
34140
+ await project(api2, args.projectId, secrets);
34141
+ return { data: { ...await api2.checks(args.projectId), notice } };
34142
+ });
34143
+ tool("run_check", "Explicitly run one saved GET/HEAD check against its current local service. Even GET can have side effects. No automatic retries.", { projectId: id, checkId: id }, true, async (args, api2, secrets) => {
34144
+ await project(api2, args.projectId, secrets);
34145
+ return { data: { ...await api2.runCheck(args.projectId, args.checkId), notice } };
34146
+ });
34089
34147
  for (const action of ["start", "restart"])
34090
34148
  tool(`${action}_service`, `${action === "start" ? "Start a configured service and its prerequisites in the background" : "Restart a daemon-owned configured service; terminal-owned services must be restarted in their terminal"}. May execute project commands.`, serviceInput, true, async (args, api2, secrets) => {
34091
34149
  const target = await service(api2, args.serviceKey, secrets, true);
@@ -3,7 +3,7 @@ import {
3
3
  STATE_FILE,
4
4
  assertUserRuntime,
5
5
  findDaemon
6
- } from "./index-316fp4p2.js";
6
+ } from "./index-tv699dzb.js";
7
7
 
8
8
  // src/update.ts
9
9
  import { spawn } from "node:child_process";
package/docs/dashboard.md CHANGED
@@ -85,3 +85,23 @@ Traffic must pass through a LocalDeck service URL to be captured. Calls directly
85
85
  For an occupied startup port, service errors show recovery guidance with the raw output under Technical details. Vite guidance covers `strictPort` and reading `PORT`; LocalDeck does not change your application configuration or terminate unrelated listeners.
86
86
 
87
87
  Clean URLs and public links are distinct browser origins. Your API must allow the frontend origin you visit. Injected `LOCALDECK_URL` and service URL references use stable numeric localhost addresses for service-to-service communication. See [configuration](configuration.md).
88
+
89
+ ## Activity and Since my change
90
+
91
+ Open a project and select **Activity** to combine request records, logs, and service lifecycle transitions. The default **Incidents** view emphasizes failures and state changes; **All activity**, service filters, and search narrow the stream. Inspecting an event pauses live updates so the evidence stays in place. Event links can be copied and reopened; expired or cleared records are identified instead of silently replaced. Nearby events are temporal context, not proof that a request caused a log line.
92
+
93
+ Use **Mark baseline** before changing code. LocalDeck saves a summary of the preceding five minutes and compares it with later observations for the same services. Comparisons show sample counts, error rates, restarts, error signatures, and route latency. Windows may have different lengths. “Not observed again” does not mean verified fixed; sparse traffic and incomplete history are explicitly reported. The latest 50 baselines are retained across restarts. Logs and requests keep their existing bounded history, and the lifecycle journal retains the latest 2,000 transitions. Clearing logs or requests also removes those records from Activity.
94
+
95
+ ## Worktree environments
96
+
97
+ The project environment selector discovers existing Git worktrees from the selected repository, including matching nested project configurations. Choose **Register & switch** to add a sibling worktree, or **Switch** for one already registered. Discovery does not start services. Branch names, detached HEADs, directories, availability, and running counts identify the selected environment.
98
+
99
+ Each worktree retains its path-based project ID and independent automatic ports. Copied nicknames are qualified when needed to avoid routing to another environment. Conflicting explicitly pinned ports are reported; LocalDeck does not override them. Databases, Docker resources, and external services can still be shared through configuration. Secrets are not copied. This release discovers existing worktrees; it does not create or delete them.
100
+
101
+ ## Saved reproduction checks
102
+
103
+ In a request inspector, choose **Preview sanitized request**, review omitted values, then copy cURL or structured JSON. Exported headers are restricted to representation metadata, recognized credentials are removed, and unsupported/incomplete bodies are omitted. Review the preview before sharing it: application data may still be private.
104
+
105
+ Eligible GET/HEAD requests can be saved with a name and an explicitly chosen expected HTTP status. Open the project's **Checks** tab to run them. Saving never executes a request. Runs use the selected environment's current local service, omit credentials, do not follow redirects, and retain the existing five-second/64-KiB replay bounds. Secret-bearing paths and requests with bodies cannot be saved as executable checks. Even GET can have application side effects.
106
+
107
+ Check definitions survive expiration or clearing of the source request. The latest 200 checks and 20 results per check are retained. Results distinguish an expected status, a status mismatch, and transport failure; response bodies are not persisted in run history.
package/docs/mcp.md CHANGED
@@ -56,6 +56,16 @@ A protocol connection alone starts no apps. The first tool call starts the daemo
56
56
  | `get_logs` | Read recent logs, optionally filtered by `stream`: stdout, stderr or system. |
57
57
  | `get_requests` | Read HTTP request records, captured headers, and body previews when available, optionally filtered by exact `status`, `method`, or a `path` substring. |
58
58
  | `get_response` | Read a cached response body using the exact service key and request ID from `get_requests`; does not replay the request. |
59
+ | `get_timeline` | Read project activity with optional exact `services`, `filter` (`all` or `incidents`), `query`, `cursor`, and `limit` (maximum 200). Returns `items`, optional `nextCursor`, and `coverage`. |
60
+ | `mark_baseline` | Explicitly save a marker for `projectId`, optional exact `services` and `label`. Does not run requests. |
61
+ | `list_baselines` | Read saved markers for a project. |
62
+ | `compare_baseline` | Compare a project's `baselineId`: before/after evidence, `newlyObserved`, `notObservedAgain`, `insufficientEvidence`, and `coverage`. |
63
+ | `list_environments` | Discover a project's Git worktree environments without registering or starting them. With `--project`, returns only that project's environment. |
64
+ | `register_environment` | Explicitly register a discovered `environmentId`. Disabled with `--project`, because registration can add another project. |
65
+ | `export_request` | Export a redacted reproduction for an exact service key and request ID without executing it. |
66
+ | `save_check` | Save a recorded GET/HEAD using `projectId`, `serviceKey`, `requestId`, `name`, and `expectedStatus` (100–599), without running it. |
67
+ | `list_checks` | Read a project's saved checks and retained results. |
68
+ | `run_check` | Explicitly execute one saved `checkId` against its current local service. Even GET can have side effects. |
59
69
  | `start_service` | Start a configured service and prerequisites in the background, using the daemon supervisor. |
60
70
  | `stop_service` | Stop a registered service and its share. Terminal services receive the existing stop request. |
61
71
  | `restart_service` | Restart a configured daemon-owned service. Active terminal services must be restarted in their original terminal. |
@@ -64,7 +74,7 @@ A protocol connection alone starts no apps. The first tool call starts the daemo
64
74
  | `start_share` | Create a Cloudflare quick share, generating a password and returning it once. `public: true` explicitly removes password protection. Requires cloudflared. |
65
75
  | `stop_share` | Close the tunnel while keeping the local service running. |
66
76
 
67
- List tools accept `limit` (default 50, maximum 200). Logs and request filters search the last 200 retained records; they are not full-history queries. Responses contain structured data and a JSON text fallback, capped together at 64 KiB, with `truncated` when information is omitted. No infinite log-follow operation is exposed.
77
+ `list_projects`, `list_services`, `get_logs`, `get_requests`, and `get_timeline` accept `limit` (default 50, maximum 200). Logs and request filters search the last 200 retained records; they are not full-history queries. Responses contain structured data and a JSON text fallback, capped together at 64 KiB, with `truncated` when information is omitted. No infinite log-follow operation is exposed.
68
78
 
69
79
  ## Actions and data
70
80
 
@@ -129,7 +139,7 @@ Bodies live in the daemon's shared 64 MiB cache. They can be evicted or lost on
129
139
 
130
140
  1. If an action times out, do not repeat it immediately: it may already have completed.
131
141
  2. Call `get_service` or `get_share` to inspect the resulting state. Each tool call rediscovers the daemon connection.
132
- 3. Retry only after establishing that the requested change is still needed. Log and request reads are bounded snapshots; there is no live-follow tool or pagination cursor.
142
+ 3. Retry only after establishing that the requested change is still needed. Log and request reads are bounded snapshots; there is no live-follow tool. Timeline reads provide an opaque pagination cursor for retained activity.
133
143
 
134
144
  ### Share a service for review
135
145
 
@@ -138,3 +148,15 @@ Bodies live in the daemon's shared 64 MiB cache. They can be evicted or lost on
138
148
  3. When sharing is authorized, call `start_share`; password protection is the default. Use `public: true` only when unprotected public access is intended.
139
149
  4. Return the URL and the newly generated password from that result. `get_share` cannot recover the password later.
140
150
  5. Call `stop_share` when the share is no longer needed; the local service stays running.
151
+
152
+
153
+ ### Compare evidence around a fix
154
+
155
+ 1. Discover the project and exact service keys. Read `get_timeline` with `filter: "incidents"`; use `nextCursor` for another retained page and inspect `coverage`.
156
+ 2. Before changing code, explicitly call `mark_baseline` with the project, optional service keys, and a useful label.
157
+ 3. Make the change and generate representative traffic only when authorized. Marking or comparing a baseline never sends requests automatically.
158
+ 4. Call `compare_baseline` using the marker's ID. Report newly observed evidence and evidence not observed again separately. Missing retention or traffic can make a comparison inconclusive; absence of an incident does not prove a fix.
159
+ 5. Use `export_request` to inspect a redacted reproduction without executing it. Missing credentials and omitted bodies can limit reproducibility.
160
+ 6. For an authorized repeatable GET/HEAD check, call `save_check` with the expected status, then explicitly `run_check`. Saving and listing checks never runs them. Check execution retains the same local-destination and credential restrictions as replay.
161
+
162
+ Environment discovery is read-only. `register_environment` remembers an explicitly selected worktree and does not launch it. Project-restricted MCP servers reject registration; use an unrestricted server or register through the dashboard when that broader action is intended.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "localdeck",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "type": "module",
5
5
  "description": "Stable ports, shareable HTTPS links and request logs for your local dev servers",
6
6
  "bin": {
@@ -1 +0,0 @@
1
- :root{color-scheme:dark;--bg: #191b1d;--bg-2: #202325;--bg-3: #24282b;--border: #353a3d;--text: #ededed;--muted: #a0a6aa;--accent: #b6ef6b;--accent-hover: #c5f58a;--accent-ink: #1c2515;--selected: #293322;--input-border: #515b61;--radius: 6px;--orange: #b6ef6b;--ok: #b6ef6b;--warn: #d1b576;--err: #ed9e91;--share: #91c7c4;--chrome: #191b1d;--chrome-border: #353a3d;--chrome-text: #ededed;--chrome-muted: #a0a6aa;--mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;--sans: var(--mono);--text-small: .75rem;--text-body: .8125rem;--text-label: .875rem;--text-section: 1rem;--text-title: 2.25rem;--control-height: 2.25rem}*{box-sizing:border-box}html{font-size:100%}html,body{margin:0;min-width:320px;height:100%;background:var(--chrome);color:var(--text);font-family:var(--sans);line-height:1.5}body{font-size:var(--text-body)}#app{height:100%}a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline}button{display:inline-flex;align-items:center;justify-content:center;text-align:center;gap:6px;font:500 var(--text-body)/1.4 var(--sans);color:var(--text);background:transparent;border:1px solid var(--border);border-radius:var(--radius);padding:7px 12px;min-height:var(--control-height);cursor:pointer;white-space:nowrap}button:hover{background:var(--bg-2);border-color:var(--muted)}button.primary{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}button.primary:hover{background:var(--accent-hover);border-color:var(--accent-hover)}button.danger:hover{color:var(--err);border-color:var(--err)}button:disabled{opacity:.45;cursor:default}input,select,textarea{font:inherit;color:var(--text);background:transparent;border:1px solid var(--border);border-radius:var(--radius);padding:8px 10px}input:not([type=checkbox]):not([type=radio]),select{min-height:var(--control-height)}input,select,textarea{font-size:var(--text-body);border-color:var(--input-border)}input[type=checkbox]{accent-color:var(--accent)}button:focus-visible,a:focus-visible,summary:focus-visible{outline:2px solid var(--accent);outline-offset:3px}code,.mono{font-family:var(--mono);font-size:var(--text-small)}::-webkit-scrollbar{width:7px;height:7px}::-webkit-scrollbar-thumb{background:#8f8f8560}[hidden]{display:none!important}summary{cursor:pointer}pre{overflow:auto}@media(prefers-reduced-motion:reduce){*,*:before,*:after{scroll-behavior:auto!important;transition:none!important}}@media(pointer:coarse),(max-width:760px){:root{--control-height: 2.75rem}input:not([type=checkbox]):not([type=radio]),select,textarea{font-size:1rem}}label:has(input[type=checkbox]){min-height:var(--control-height)}input:focus-visible,select:focus-visible,textarea:focus-visible{outline:2px solid var(--accent);outline-offset:3px}::selection{background:var(--accent);color:var(--accent-ink)}input::placeholder,textarea::placeholder{color:#929a9f}button,a{-webkit-tap-highlight-color:transparent;transition:background .12s,border-color .12s,color .12s}button:active:not(:disabled){transform:translateY(1px)}h1{font-weight:400;letter-spacing:-.04em}@media(prefers-reduced-motion:reduce){button,a{transition:none}button:active:not(:disabled){transform:none}}:root{--page-padding-x: 40px;--page-padding-y: 48px}.page-shell{width:100%;min-width:0;padding:var(--page-padding-y) var(--page-padding-x)}.page-heading{display:flex;align-items:flex-start;justify-content:space-between;flex-wrap:wrap;gap:20px;margin:0 0 24px}.page-heading h1{margin:0;font:400 var(--text-title)/1.25 var(--sans);letter-spacing:-.04em;overflow-wrap:anywhere}.page-heading .page-subtitle{margin:8px 0 0;color:var(--muted);font:400 var(--text-small)/1.5 var(--sans)}@media(max-width:760px){:root{--page-padding-x: 16px;--page-padding-y: 24px;--text-title: 1.5rem}.page-heading{gap:12px}}dialog.svelte-vw7b2v{width:min(640px,calc(100vw - 32px));max-height:min(620px,80dvh);margin:12dvh auto auto;padding:0;border:1px solid var(--border);background:var(--bg);color:var(--text);box-shadow:0 24px 80px #0005;overflow:hidden;border-radius:8px}dialog[open].svelte-vw7b2v{display:flex;flex-direction:column}dialog.svelte-vw7b2v::backdrop{background:#1119}.search-row.svelte-vw7b2v{display:flex;align-items:center;gap:12px;padding:14px 18px;border-bottom:1px solid var(--border);flex-shrink:0}.search-row.svelte-vw7b2v svg{flex-shrink:0;color:var(--muted)}input.svelte-vw7b2v{flex:1;min-width:0;border:0;padding:8px 0}.close.svelte-vw7b2v{min-height:28px;padding:3px 6px;font:12px var(--mono);color:var(--muted)}.results.svelte-vw7b2v{overflow:auto;min-height:0;padding:6px}.results.svelte-vw7b2v button:where(.svelte-vw7b2v){width:100%;justify-content:space-between;gap:16px;border:0;padding:12px;text-align:left;white-space:normal}.results.svelte-vw7b2v button.chosen:where(.svelte-vw7b2v){background:var(--accent);color:var(--accent-ink)}.results.svelte-vw7b2v button.chosen:where(.svelte-vw7b2v) small:where(.svelte-vw7b2v){color:var(--accent-ink)}.search-row.svelte-vw7b2v:focus-within{border-bottom-color:var(--accent)}.search-row.svelte-vw7b2v input:where(.svelte-vw7b2v):focus-visible{outline:none}.results.svelte-vw7b2v button[aria-disabled=true]:where(.svelte-vw7b2v){color:var(--muted)}strong.svelte-vw7b2v,small.svelte-vw7b2v{display:block}strong.svelte-vw7b2v{font-weight:500}small.svelte-vw7b2v{font-size:var(--text-small);color:var(--muted);overflow-wrap:anywhere}footer.svelte-vw7b2v{display:flex;justify-content:space-between;gap:12px;padding:12px 18px;border-top:1px solid var(--border);font-size:var(--text-small);color:var(--muted);flex-shrink:0}.separator.svelte-vw7b2v{margin:0 6px}.empty.svelte-vw7b2v,.error.svelte-vw7b2v{padding:16px 18px;margin:0}.empty.svelte-vw7b2v{color:var(--muted)}.error.svelte-vw7b2v{color:var(--err)}.load-error.svelte-vw7b2v{display:flex;align-items:center;gap:12px;padding:12px 18px;color:var(--err);border-top:1px solid var(--border);font-size:var(--text-small)}@media(max-width:480px){dialog.svelte-vw7b2v{margin-top:6dvh;max-height:88dvh}.search-row.svelte-vw7b2v{gap:8px;padding:10px}footer.svelte-vw7b2v{flex-wrap:wrap}}section.svelte-1hauwfi{margin-top:32px}h3.svelte-1hauwfi{margin:0 0 12px;font:500 var(--text-section)/1.4 var(--sans)}p.svelte-1hauwfi,li.svelte-1hauwfi{line-height:1.7}p.svelte-1hauwfi{color:var(--muted)}ul.svelte-1hauwfi{padding-left:20px}code.svelte-1hauwfi{overflow-wrap:anywhere}.copy-command.svelte-1hauwfi{display:inline-flex;vertical-align:middle;padding:4px;margin-left:5px;min-height:28px;width:28px;border:0;border-radius:0;background:transparent;color:var(--muted)}.copy-command.svelte-1hauwfi:hover{background:transparent;color:var(--text)}.sr-only.svelte-1hauwfi{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}li.svelte-1hauwfi+li:where(.svelte-1hauwfi){margin-top:8px}h2.svelte-1vwaeio{font-size:var(--text-section);line-height:1.4;margin:0 0 12px;font-weight:600}p.svelte-1vwaeio{line-height:1.6;margin:0 0 16px;max-width:65ch}.about.svelte-1vwaeio>section:where(.svelte-1vwaeio){margin-top:40px;padding-top:28px;border-top:1px solid var(--border)}.steps.svelte-1vwaeio{padding-left:24px;margin:20px 0}.steps.svelte-1vwaeio li:where(.svelte-1vwaeio){padding-left:8px;margin-bottom:16px}.steps.svelte-1vwaeio span:where(.svelte-1vwaeio){display:block;margin-top:4px;color:var(--muted)}.note.svelte-1vwaeio{color:var(--muted);font-size:var(--text-small)}code.svelte-1vwaeio{overflow-wrap:anywhere}.command-groups.svelte-1vwaeio{margin:24px 0;border-top:1px solid var(--border)}details.svelte-1vwaeio{border-bottom:1px solid var(--border)}summary.svelte-1vwaeio{padding:16px 0;min-height:var(--control-height);font-weight:500}summary.svelte-1vwaeio span:where(.svelte-1vwaeio){color:var(--muted);font-size:var(--text-small);font-weight:400;margin-left:12px;white-space:nowrap}dl.svelte-1vwaeio{margin:0 0 16px}dl.svelte-1vwaeio>div:where(.svelte-1vwaeio){padding:16px 0}dl.svelte-1vwaeio>div:where(.svelte-1vwaeio)+div:where(.svelte-1vwaeio){border-top:1px solid var(--border)}dt.svelte-1vwaeio{margin-bottom:8px}dd.svelte-1vwaeio{margin:0;color:var(--muted);line-height:1.6;max-width:65ch}@media(max-width:760px){summary.svelte-1vwaeio span:where(.svelte-1vwaeio){display:block;margin:4px 0 0 18px}}h3.svelte-1offp6a{margin-top:32px;font:500 var(--text-section)/1.4 var(--sans)}label.svelte-1offp6a{display:block;margin-bottom:8px}.controls.svelte-1offp6a{display:flex;align-items:center;gap:8px}input.svelte-1offp6a{width:160px}input.svelte-1offp6a:focus-visible{outline:none;border-color:var(--text)}p.svelte-1offp6a{color:var(--muted);line-height:1.6}.current.svelte-1offp6a{font-size:var(--text-small)}article.svelte-1tl5wtp{padding:28px 0;border-bottom:1px solid var(--border)}h2.svelte-1tl5wtp{margin:0 0 16px;font:500 var(--text-section)/1.4 var(--sans)}h2.svelte-1tl5wtp span:where(.svelte-1tl5wtp){color:var(--muted);margin-left:12px;font-size:var(--text-label)}h3.svelte-1tl5wtp{font-size:var(--text-label);font-weight:500;margin:0 0 10px}.release-section.svelte-1tl5wtp{max-width:100ch;margin-top:28px}li.svelte-1tl5wtp+li:where(.svelte-1tl5wtp){margin-top:8px}ul.svelte-1tl5wtp{margin:0;padding-left:20px;line-height:1.8}.secrets.svelte-sh54s5{margin-top:28px}h2.svelte-sh54s5{font-size:18px;margin:0;font-weight:500}.section-heading.svelte-sh54s5{display:flex;align-items:center;justify-content:space-between;gap:16px}.count.svelte-sh54s5,.section-note.svelte-sh54s5{font-size:var(--text-small);color:var(--muted)}.section-note.svelte-sh54s5{margin:8px 0 22px;line-height:1.6}ul.svelte-sh54s5{padding:0;margin:0;list-style:none}.list-heading.svelte-sh54s5,li.svelte-sh54s5{display:grid;grid-template-columns:minmax(0,1fr) 130px minmax(124px,auto);gap:16px;align-items:center}.list-heading.svelte-sh54s5{padding:0 0 10px;border-bottom:1px solid var(--border);color:var(--muted);font-size:var(--text-small)}li.svelte-sh54s5{min-height:66px;padding:12px 0;border-bottom:1px solid var(--border)}code.svelte-sh54s5{overflow-wrap:anywhere;font-size:var(--text-small)}.secret-status.svelte-sh54s5{display:flex;gap:7px;align-items:center;font-size:var(--text-small);color:var(--muted)}.secret-status.svelte-sh54s5 i:where(.svelte-sh54s5){width:6px;height:6px;flex-shrink:0;background:currentColor}.secret-status.configured.svelte-sh54s5{color:var(--ok)}.actions.svelte-sh54s5{display:flex;justify-content:flex-end;gap:14px}.text-action.svelte-sh54s5{padding:4px 0;min-height:32px;border:0;background:transparent;font-size:var(--text-small);text-decoration:underline;text-underline-offset:4px}.text-action.svelte-sh54s5:hover{text-decoration-thickness:2px}.remove.svelte-sh54s5{color:var(--muted)}.count.svelte-sh54s5{display:block;margin-top:6px}.secret-editor.svelte-sh54s5{position:relative}summary.svelte-sh54s5{cursor:pointer;list-style:none;display:inline-flex;gap:7px;align-items:center;justify-content:center}summary.svelte-sh54s5::-webkit-details-marker{display:none}summary[aria-disabled=true].svelte-sh54s5{opacity:.5;cursor:default}.add-secret.svelte-sh54s5{padding:7px 12px;min-height:var(--control-height);border:1px solid var(--border);font-weight:500}.add-secret.svelte-sh54s5:hover{background:var(--bg-2)}.editor-popover.svelte-sh54s5{position:absolute;top:calc(100% + 8px);right:0;z-index:40;width:min(340px,calc(100vw - 110px));padding:20px;background:var(--bg);border:1px solid var(--border);border-radius:8px;box-shadow:0 8px 24px #0005;text-align:left}.editor-popover.svelte-sh54s5 h2:where(.svelte-sh54s5){margin-bottom:20px}.editor-popover.svelte-sh54s5 .section-note:where(.svelte-sh54s5){margin:14px 0}.editor-popover.svelte-sh54s5 .primary:where(.svelte-sh54s5){width:100%}.fields.svelte-sh54s5{display:grid;grid-template-columns:1fr;gap:16px}label.svelte-sh54s5{display:grid;gap:8px;font-size:var(--text-small);font-weight:500;min-width:0}input.svelte-sh54s5{width:100%;min-width:0;background:var(--bg)}.storage-note.svelte-sh54s5{margin-top:28px;padding-left:14px;border-left:2px solid var(--border);max-width:680px;font-size:var(--text-small);color:var(--muted)}.storage-note.svelte-sh54s5 strong:where(.svelte-sh54s5){font-weight:500;color:var(--text)}.storage-note.svelte-sh54s5 p:where(.svelte-sh54s5){margin:6px 0 0;line-height:1.6}.error.svelte-sh54s5{color:var(--err)}.saved.svelte-sh54s5{color:var(--ok)}.empty.svelte-sh54s5{padding:22px 0;border-block:1px solid var(--border);color:var(--muted)}@media(max-width:1000px){.list-heading.svelte-sh54s5{display:none}li.svelte-sh54s5{grid-template-columns:minmax(0,1fr) auto;gap:8px 16px}.secret-status.svelte-sh54s5{grid-column:1;grid-row:2}.actions.svelte-sh54s5{grid-column:2;grid-row:1 / 3}}@media(max-width:650px){.fields.svelte-sh54s5{grid-template-columns:1fr;gap:16px}form.svelte-sh54s5{padding:18px}}.share-line.svelte-iodvty{display:flex;align-items:center;flex-wrap:wrap;gap:8px 16px;min-width:0}.slow-hint.svelte-iodvty{flex-basis:100%;color:var(--muted);font-size:var(--text-small)}.slow-hint.svelte-iodvty a:where(.svelte-iodvty){text-decoration:underline}.password.svelte-iodvty{display:inline-flex;flex-wrap:wrap;align-items:center;gap:7px;color:var(--muted);font-size:var(--text-small);overflow-wrap:anywhere}.password.svelte-iodvty button:where(.svelte-iodvty){padding:0;min-height:0;border:0;background:transparent;text-decoration:underline;color:inherit}a.svelte-iodvty{width:fit-content;max-width:100%;overflow-wrap:anywhere;color:var(--share);font-size:var(--text-small)}.connecting.svelte-iodvty,.error.svelte-iodvty{display:flex;align-items:center;gap:7px;font-size:var(--text-small)}.connecting.svelte-iodvty{flex-wrap:wrap;color:var(--muted)}.error.svelte-iodvty{color:var(--err);align-items:flex-start;overflow-wrap:anywhere}.error.svelte-iodvty svg{flex-shrink:0;margin-top:3px}.spinner.svelte-iodvty{display:inline-flex;animation:svelte-iodvty-spin 1s linear infinite}@keyframes svelte-iodvty-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){.spinner.svelte-iodvty{animation:none}}.menu-item.svelte-1u7hpyn>summary:where(.svelte-1u7hpyn){justify-content:flex-start;gap:10px;border:0;font-weight:400;padding:10px 12px}.menu-item.svelte-1u7hpyn .share-popover:where(.svelte-1u7hpyn){position:static;width:100%;box-shadow:none;border:0;padding:12px}.share-control.svelte-1u7hpyn{position:relative}summary.svelte-1u7hpyn{display:flex;align-items:center;justify-content:center;gap:7px;padding:7px 12px;min-height:var(--control-height);border:1px solid var(--border);list-style:none;font-weight:500}summary.svelte-1u7hpyn::-webkit-details-marker{display:none}summary.svelte-1u7hpyn:hover{background:var(--bg-2);border-color:var(--muted)}.share-popover.svelte-1u7hpyn{position:absolute;right:0;top:calc(100% + 8px);z-index:30;width:min(340px,calc(100vw - 96px));padding:18px;border:1px solid var(--border);background:var(--bg);border-radius:8px;box-shadow:0 8px 24px #0005;text-align:left}.share-url.svelte-1u7hpyn{display:block;margin-top:12px;overflow-wrap:anywhere}p.svelte-1u7hpyn{font-size:var(--text-small);color:var(--muted);line-height:1.6;overflow-wrap:anywhere}label.svelte-1u7hpyn{display:grid;gap:6px;font-size:var(--text-small)}label.public.svelte-1u7hpyn{display:flex;align-items:center;gap:8px;margin-bottom:12px}label.public.svelte-1u7hpyn input:where(.svelte-1u7hpyn){width:auto}input.svelte-1u7hpyn{width:100%;min-width:0}.actions.svelte-1u7hpyn{display:flex;flex-wrap:wrap;gap:8px}.error.svelte-1u7hpyn{color:var(--err)}.service-options.svelte-m918bk{position:relative}summary.svelte-m918bk{display:flex;align-items:center;justify-content:center;gap:8px;padding:7px 12px;min-height:var(--control-height);border:1px solid var(--border);border-radius:var(--radius);list-style:none;font-weight:500;cursor:pointer}summary.svelte-m918bk::-webkit-details-marker{display:none}summary.svelte-m918bk:hover,.service-options[open].svelte-m918bk>summary:where(.svelte-m918bk){background:var(--bg-2);border-color:var(--muted)}.options-popover.svelte-m918bk{position:absolute;z-index:40;right:0;top:calc(100% + 6px);width:min(300px,calc(100vw - 100px));padding:6px;background:var(--bg);border:1px solid var(--border);border-radius:8px;box-shadow:0 8px 24px #0005}.options-popover.svelte-m918bk>button:where(.svelte-m918bk){width:100%;border:0;background:transparent;display:flex;gap:10px;justify-content:flex-start;padding:10px 12px;text-align:left;font-weight:400}.options-popover.svelte-m918bk>button:where(.svelte-m918bk):hover{background:var(--bg-2)}.share-action.svelte-m918bk{border-top:1px solid var(--border);margin-top:4px;padding-top:4px}.service-error.svelte-13pnhk8{padding:12px 0;font-size:var(--text-small);overflow-wrap:anywhere}strong.svelte-13pnhk8,p.svelte-13pnhk8{color:var(--err)}p.svelte-13pnhk8{margin:0;white-space:pre-wrap}ul.svelte-13pnhk8{margin:8px 0 12px;padding-left:20px;color:var(--text);line-height:1.7}li.svelte-13pnhk8+li:where(.svelte-13pnhk8){margin-top:6px}summary.svelte-13pnhk8{width:fit-content;color:var(--muted)}pre.svelte-13pnhk8{margin:8px 0 0;white-space:pre-wrap;font:inherit;font-family:var(--mono);color:var(--muted)}.diagnostics.svelte-1xk5qw3{margin:16px 0;padding:12px;border:1px solid var(--border);border-radius:0}summary.svelte-1xk5qw3{cursor:pointer}p.svelte-1xk5qw3{color:var(--muted);font-size:var(--text-small)}textarea.svelte-1xk5qw3{display:block;width:100%;box-sizing:border-box;margin:8px 0;background:var(--bg-2);color:var(--text);border:1px solid var(--border);font:var(--text-small)/1.5 var(--mono)}form.svelte-1gn57ev{width:100%;min-width:0;padding:20px 0 8px}fieldset.svelte-1gn57ev{border:0;padding:0;margin:0;min-width:0}.fields.svelte-1gn57ev{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}label.svelte-1gn57ev{display:flex;flex-direction:column;gap:6px;font-size:var(--text-body);color:var(--text)}input.svelte-1gn57ev,select.svelte-1gn57ev{width:100%;min-width:0;background:var(--bg)}.dependencies.svelte-1gn57ev{margin:20px 0;font-size:var(--text-small)}.dependencies.svelte-1gn57ev>div:where(.svelte-1gn57ev){display:flex;flex-wrap:wrap;gap:16px;margin-top:8px}.dependencies.svelte-1gn57ev label:where(.svelte-1gn57ev){flex-direction:row;align-items:center}.dependencies.svelte-1gn57ev input:where(.svelte-1gn57ev){width:auto}p.svelte-1gn57ev{color:var(--muted);font-size:var(--text-small)}.error.svelte-1gn57ev{color:var(--err)}@media(max-width:600px){.fields.svelte-1gn57ev{grid-template-columns:1fr}}form.svelte-ruqv4s{margin:24px 0 40px;max-width:480px}label.svelte-ruqv4s{font-weight:600}p.svelte-ruqv4s{font-size:var(--text-small);color:var(--muted);line-height:1.6}.controls.svelte-ruqv4s{display:flex;gap:8px;margin-top:8px}input.svelte-ruqv4s{flex:1;width:180px;min-width:0}.error.svelte-ruqv4s{color:var(--err);margin-bottom:0}.notice.svelte-ruqv4s{color:var(--ok);margin-bottom:0}.hint.svelte-ruqv4s{font-size:var(--text-small)}.service-port.svelte-1poq4pf{display:flex;flex-wrap:wrap;gap:4px 16px;color:var(--muted);font-size:var(--text-small);line-height:1.5}strong.svelte-1poq4pf{color:var(--text);font-weight:500}.project-overview.svelte-l7un4l{min-height:100%;display:flex;flex-direction:column}.heading.svelte-l7un4l{min-width:0}h1.svelte-l7un4l,h2.svelte-l7un4l,p.svelte-l7un4l{margin-top:0}h2.svelte-l7un4l{margin-bottom:8px;font-size:var(--text-section)}.project-actions.svelte-l7un4l,.service-actions.svelte-l7un4l,.recovery-actions.svelte-l7un4l{display:flex;align-items:center;gap:8px}.summary-row.svelte-l7un4l{display:flex;flex-wrap:wrap;gap:14px;padding:4px 0;color:var(--muted);font-size:var(--text-small)}.summary-row.svelte-l7un4l strong:where(.svelte-l7un4l){color:var(--text);font-variant-numeric:tabular-nums}.bulk-summary.svelte-l7un4l{margin:0 0 10px;color:var(--muted)}.service-grid.svelte-l7un4l{display:grid;grid-template-columns:1fr;gap:0}.service-card.svelte-l7un4l{min-width:0;display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;column-gap:16px;padding:22px 0;border-bottom:1px solid var(--border)}.service-card.failed.svelte-l7un4l{border-color:#f87171a6}.service-main.svelte-l7un4l{display:grid;grid-template-columns:minmax(0,1fr);justify-content:stretch;width:100%;padding:0;border:0;background:transparent;text-align:left;white-space:normal}.service-main.svelte-l7un4l:hover{background:transparent}.service-heading.svelte-l7un4l{display:flex;align-items:center;gap:8px}.status-dot.svelte-l7un4l{width:7px;height:7px;border-radius:50%;background:var(--muted)}.status-dot.running.svelte-l7un4l{background:var(--ok)}.status-dot.waiting.svelte-l7un4l{background:var(--warn)}.status-text.svelte-l7un4l{margin-left:8px;color:var(--muted);font-size:var(--text-small);background:var(--bg-3);border-radius:var(--radius);padding:2px 7px}.ownership.svelte-l7un4l{margin:4px 0 8px 15px;color:var(--muted);font-size:var(--text-small)}.service-url.svelte-l7un4l{color:var(--accent);overflow:hidden;text-overflow:ellipsis}.command.svelte-l7un4l{margin-top:7px;color:var(--text);overflow:hidden;text-overflow:ellipsis}.dependency-summary.svelte-l7un4l{margin-top:7px;color:var(--accent);font-size:var(--text-small)}.dependency-summary.svelte-l7un4l span:where(.svelte-l7un4l){color:var(--muted)}.dependency-editor.svelte-l7un4l{margin-top:10px;padding-top:9px;border-top:1px solid var(--border)}.dependency-editor.svelte-l7un4l summary:where(.svelte-l7un4l){color:var(--muted);cursor:pointer;font-size:var(--text-small)}.dependency-editor.svelte-l7un4l form:where(.svelte-l7un4l){margin-top:9px}.dependency-editor.svelte-l7un4l fieldset:where(.svelte-l7un4l){display:flex;flex-wrap:wrap;gap:7px 12px;margin:0;padding:0;border:0}.dependency-editor.svelte-l7un4l legend:where(.svelte-l7un4l){width:100%;margin-bottom:6px;color:var(--muted);font-size:var(--text-small)}.dependency-editor.svelte-l7un4l label:where(.svelte-l7un4l){display:inline-flex;align-items:center;gap:5px;font-size:var(--text-small)}.dependency-actions.svelte-l7un4l{display:flex;gap:7px;margin-top:10px}.no-dependencies.svelte-l7un4l{color:var(--muted);font-size:var(--text-small)}.inline-error.svelte-l7un4l{margin:9px 0 0;color:var(--err);font-size:var(--text-small);overflow-wrap:anywhere}.unavailable.svelte-l7un4l{display:flex;justify-content:space-between;align-items:center;gap:20px;margin-top:16px;padding:16px;border:1px solid rgba(248,113,113,.55);border-radius:var(--radius);background:var(--bg-2)}.unavailable.svelte-l7un4l p:where(.svelte-l7un4l),.empty-services.svelte-l7un4l p:where(.svelte-l7un4l){margin-bottom:0;color:var(--muted)}.active-services.svelte-l7un4l{margin-top:18px}.active-services.svelte-l7un4l>h2:where(.svelte-l7un4l){margin-bottom:3px}.active-services.svelte-l7un4l>p:where(.svelte-l7un4l){margin-bottom:10px;color:var(--muted)}.empty-services.svelte-l7un4l{grid-column:1 / -1;padding:24px;border:1px dashed var(--border);border-radius:var(--radius);text-align:center}.launch-panel.svelte-l7un4l{padding:20px;background:var(--bg-2);border:1px solid var(--err);border-radius:var(--radius);margin-bottom:32px}.launch-panel.svelte-l7un4l h2:where(.svelte-l7un4l){font-size:var(--text-section);letter-spacing:-.025em;margin:7px 0}.launch-panel.svelte-l7un4l p:where(.svelte-l7un4l):last-child{color:var(--muted);margin-bottom:0;font-size:var(--text-small)}.open-app.svelte-l7un4l{display:inline-flex;align-items:center;gap:10px;padding:7px 12px;min-height:var(--control-height);font-family:var(--sans);line-height:1.4;border-radius:var(--radius);background:var(--accent);color:var(--accent-ink);font-weight:600;white-space:nowrap;font-size:var(--text-body)}.open-app.svelte-l7un4l:hover{background:var(--accent-hover);text-decoration:none}.list-heading.svelte-l7un4l{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:18px}.list-heading.svelte-l7un4l h2:where(.svelte-l7un4l){font-size:var(--text-section);margin:0;font-weight:600}.service-search.svelte-l7un4l span:where(.svelte-l7un4l){display:block;color:var(--muted);font-size:var(--text-small);margin-bottom:4px}.service-search.svelte-l7un4l input:where(.svelte-l7un4l){background:var(--bg-2);width:220px}.service-heading.svelte-l7un4l strong:where(.svelte-l7un4l){font-size:var(--text-body)}.service-settings.svelte-l7un4l{grid-column:1 / -1;margin-top:14px;border-top:1px solid var(--border);padding-top:9px;color:var(--muted);font-size:var(--text-small)}.service-settings[open].svelte-l7un4l{padding-bottom:12px}.service-open.svelte-l7un4l{font-weight:600;padding:8px;white-space:nowrap}.service-actions.svelte-l7un4l{flex-wrap:wrap;justify-content:flex-end}.copy.svelte-l7un4l{background:transparent}.service-links.svelte-l7un4l{display:grid;gap:5px;margin-top:8px;min-width:0}.service-links.svelte-l7un4l a:where(.svelte-l7un4l){width:fit-content;max-width:100%;overflow-wrap:anywhere;font-size:var(--text-small)}.inline-error.svelte-l7un4l{grid-column:1 / -1}.settings-panel.svelte-l7un4l{width:100%;min-width:0}.settings-note.svelte-l7un4l{color:var(--muted);font-size:var(--text-small)}.config-list.svelte-l7un4l{width:100%;min-width:0;margin:20px 0 32px;border-top:1px solid var(--border)}.config-list.svelte-l7un4l>details:where(.svelte-l7un4l){min-width:0;border-bottom:1px solid var(--border);padding:16px 0}.config-list.svelte-l7un4l summary:where(.svelte-l7un4l){min-height:var(--control-height);display:flex;gap:20px;align-items:center;list-style:none}.config-list.svelte-l7un4l summary:where(.svelte-l7un4l)::-webkit-details-marker{display:none}.config-list.svelte-l7un4l summary:where(.svelte-l7un4l) strong:where(.svelte-l7un4l){min-width:80px;font:500 var(--text-label)/1.4 var(--sans)}.config-list.svelte-l7un4l summary:where(.svelte-l7un4l) span:where(.svelte-l7un4l){color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--text-small)}.config-list.svelte-l7un4l summary:where(.svelte-l7un4l) .edit-label:where(.svelte-l7un4l){margin-left:auto;flex-shrink:0;color:var(--text)}.settings-tools.svelte-l7un4l{padding:12px 0;color:var(--muted)}.settings-panel.svelte-l7un4l h2:where(.svelte-l7un4l){margin-top:24px}.project-health.svelte-l7un4l{display:flex;align-items:center;gap:12px;color:var(--muted)}.project-health.svelte-l7un4l:has(.running:where(.svelte-l7un4l)){color:var(--ok)}.project-address.svelte-l7un4l{display:flex;align-items:center;gap:12px;min-width:0;color:var(--muted);padding:24px 0;border-bottom:1px solid var(--border);margin-bottom:28px}.project-address.svelte-l7un4l a:where(.svelte-l7un4l){color:var(--muted);overflow-wrap:anywhere;font-size:var(--text-body)}.project-address.svelte-l7un4l button:where(.svelte-l7un4l),.manage-button.svelte-l7un4l{display:inline-flex;align-items:center;border:0;background:transparent;color:var(--muted);padding:10px}.manage-button.svelte-l7un4l{border-radius:var(--radius);text-decoration:none;border:1px solid var(--border);min-height:var(--control-height);gap:8px;padding:7px 12px;justify-content:center}.overview-row.svelte-l7un4l{display:grid;grid-template-columns:36px minmax(90px,1fr) minmax(60px,.8fr) minmax(90px,1fr);gap:16px;align-items:center;width:100%;font-size:var(--text-body)}.overview-row.svelte-l7un4l strong:where(.svelte-l7un4l){font-size:var(--text-label);font-weight:500;overflow-wrap:anywhere}.service-icon.svelte-l7un4l{width:36px;height:36px;display:grid;place-items:center;border:1px solid var(--border);border-radius:var(--radius);background:var(--bg-2);color:var(--muted)}.technical-name.svelte-l7un4l{color:var(--muted);font-weight:400;overflow-wrap:anywhere}.row-health.svelte-l7un4l{display:flex;align-items:center;gap:9px;color:var(--muted);font-weight:400}.row-health.svelte-l7un4l .status-dot:where(.svelte-l7un4l){background:currentColor;flex-shrink:0}.row-health.ready.svelte-l7un4l{color:var(--ok)}.row-health.errored.svelte-l7un4l{color:var(--err)}.row-health.svelte-l7un4l{text-transform:capitalize}.readiness-summary.svelte-l7un4l{color:var(--muted);font-size:var(--text-body);margin:24px 0 48px}.managing.svelte-l7un4l{margin-top:32px}.muted.svelte-l7un4l{color:var(--muted)}.profiles.svelte-l7un4l{padding:18px;border:1px solid var(--border);border-radius:var(--radius);background:var(--bg-2)}.profiles[open].svelte-l7un4l summary:where(.svelte-l7un4l){margin-bottom:16px}@media(min-width:801px)and (max-width:1100px){.overview-row.svelte-l7un4l{grid-template-columns:48px minmax(0,1fr) auto;gap:16px}.technical-name.svelte-l7un4l{white-space:nowrap;display:none}.managing.svelte-l7un4l .service-card:where(.svelte-l7un4l){grid-template-columns:1fr}.managing.svelte-l7un4l .service-actions:where(.svelte-l7un4l){justify-content:flex-start;margin-top:16px}}@media(max-width:800px){.unavailable.svelte-l7un4l{align-items:stretch;flex-direction:column}.project-actions.svelte-l7un4l button:where(.svelte-l7un4l),.recovery-actions.svelte-l7un4l button:where(.svelte-l7un4l){flex:1}.service-grid.svelte-l7un4l{grid-template-columns:1fr}.service-card.svelte-l7un4l{grid-template-columns:1fr;padding:18px}.service-actions.svelte-l7un4l{justify-content:flex-start;margin-top:16px;gap:6px}.service-actions.svelte-l7un4l button:where(.svelte-l7un4l){padding:8px 10px}.launch-panel.svelte-l7un4l{align-items:flex-start;flex-direction:column;padding:20px}.list-heading.svelte-l7un4l{align-items:stretch;flex-direction:column}.service-search.svelte-l7un4l input:where(.svelte-l7un4l){width:100%}.project-actions.svelte-l7un4l{flex-wrap:wrap}.open-app.svelte-l7un4l{padding:7px 12px;font-size:var(--text-small)}.project-actions.svelte-l7un4l{gap:8px;flex-shrink:0}.manage-button.svelte-l7un4l{min-height:var(--control-height)}.project-address.svelte-l7un4l{padding:24px 0;margin-bottom:28px}.overview-row.svelte-l7un4l{grid-template-columns:40px minmax(0,1fr) auto;gap:12px}.service-icon.svelte-l7un4l{width:40px;height:40px}.technical-name.svelte-l7un4l{white-space:nowrap;display:none}.overview-row.svelte-l7un4l strong:where(.svelte-l7un4l){font-size:var(--text-label)}.row-health.svelte-l7un4l{font-size:var(--text-small)}.service-card.svelte-l7un4l{padding:18px 0}}.service-row.svelte-1h3c7zm{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:12px 24px;padding:20px 0;border-bottom:1px solid var(--border)}.service-info.svelte-1h3c7zm{display:grid;gap:5px;min-width:0}.service-heading.svelte-1h3c7zm{display:flex;align-items:center;gap:9px}strong.svelte-1h3c7zm{font-size:var(--text-label);font-weight:500}.status-dot.svelte-1h3c7zm{width:7px;height:7px;background:var(--muted);flex-shrink:0}.status-dot.running.svelte-1h3c7zm{background:var(--ok)}.service-status.svelte-1h3c7zm,.project-name.svelte-1h3c7zm{color:var(--muted);font-size:var(--text-small)}.service-status.svelte-1h3c7zm{margin-left:6px}.service-address.svelte-1h3c7zm{width:fit-content;max-width:100%;overflow-wrap:anywhere;color:var(--text)}.service-controls.svelte-1h3c7zm{display:flex;align-items:center;gap:8px;flex-wrap:wrap}button.svelte-1h3c7zm{display:inline-flex;justify-content:center;align-items:center;gap:7px}.action-error.svelte-1h3c7zm{grid-column:1 / -1;margin:0;color:var(--err);font-size:var(--text-small)}@media(max-width:900px){.service-row.svelte-1h3c7zm{grid-template-columns:minmax(0,1fr)}.service-controls.svelte-1h3c7zm{justify-content:flex-start}}.body-viewer.svelte-1eh4gal{min-width:0;margin:12px 0;border:1px solid var(--chrome-border)}.body-toolbar.svelte-1eh4gal{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:6px 10px;border-bottom:1px solid var(--chrome-border);color:var(--chrome-muted);font-size:.6875rem}button.svelte-1eh4gal{border:0;border-radius:0;background:transparent;color:var(--chrome-muted);min-height:28px;padding:3px 0;font-size:.6875rem}button.svelte-1eh4gal:hover{background:transparent;color:var(--chrome-text)}pre.svelte-1eh4gal{margin:0;padding:12px;max-height:440px;overflow:auto;white-space:pre;-moz-tab-size:2;tab-size:2;color:var(--chrome-text)}pre.svelte-1eh4gal,code.svelte-1eh4gal{font:.75rem/1.7 var(--mono)}.key.svelte-1eh4gal{color:#b6cbd7}.string.svelte-1eh4gal{color:#b6d598}.number.svelte-1eh4gal{color:#dfbc86}.literal.svelte-1eh4gal{color:#d4a8bb}p.svelte-1eh4gal{margin:8px 12px;color:var(--err)}.metadata.svelte-s74nzf{display:flex;flex-direction:column;margin:16px 0}details.svelte-s74nzf{min-width:0;border-bottom:1px solid var(--chrome-border)}summary.svelte-s74nzf{display:flex;align-items:center;justify-content:space-between;padding:10px 0;list-style:none;cursor:pointer;font-weight:600;color:var(--chrome-text)}summary.svelte-s74nzf::-webkit-details-marker{display:none}summary.svelte-s74nzf:after{content:"›";font-size:1rem}details[open].svelte-s74nzf>summary:where(.svelte-s74nzf):after{transform:rotate(90deg)}summary.svelte-s74nzf:hover{color:#fff}dl.svelte-s74nzf{margin:8px 0;font-family:var(--mono)}dl.svelte-s74nzf>div:where(.svelte-s74nzf){display:grid;grid-template-columns:minmax(90px,1fr) minmax(0,2fr);gap:12px;padding:5px 0;border-bottom:1px solid var(--chrome-border)}dt.svelte-s74nzf,dd.svelte-s74nzf{overflow-wrap:anywhere;white-space:pre-wrap}dd.svelte-s74nzf{margin:0;color:var(--chrome-muted)}h4.svelte-s74nzf{font-size:inherit;margin:12px 0 6px}p.svelte-s74nzf{color:var(--chrome-muted)}.requests-panel.svelte-tqqrb7{display:grid;grid-template-columns:minmax(0,1fr);flex:1;min-height:0;overflow:hidden;font:.75rem/1.6 var(--mono)}.requests-panel.inspecting.svelte-tqqrb7{grid-template-columns:minmax(260px,1fr) minmax(280px,.85fr)}.request-list.svelte-tqqrb7{min-height:0;min-width:0;overflow:auto}table.svelte-tqqrb7{font:inherit;width:100%;border-collapse:collapse;text-align:left;table-layout:fixed}th.svelte-tqqrb7,td.svelte-tqqrb7{padding:9px 14px;vertical-align:middle}th.svelte-tqqrb7{position:sticky;top:0;z-index:1;background:var(--chrome);color:var(--chrome-muted);font-size:.6875rem;font-weight:400;border-bottom:1px solid var(--chrome-border)}.numeric.svelte-tqqrb7{width:88px;text-align:right;white-space:nowrap;font-variant-numeric:tabular-nums}.service-column.svelte-tqqrb7{width:24%;color:var(--chrome-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.request-row.svelte-tqqrb7{cursor:pointer}.request-row.svelte-tqqrb7:nth-of-type(2n){background:#ffffff03}.request-row.svelte-tqqrb7:hover,.request-row.svelte-tqqrb7:focus-within{background:var(--bg-3)}.request-row.selected.svelte-tqqrb7{background:var(--bg-3);box-shadow:inset 2px 0 var(--accent)}button.svelte-tqqrb7{font:inherit;color:var(--chrome-text);background:transparent;border-radius:0}.request-cell.svelte-tqqrb7 button:where(.svelte-tqqrb7){display:flex;justify-content:flex-start;gap:10px;width:100%;min-height:24px;padding:0;border:0;text-align:left}.request-cell.svelte-tqqrb7 button:where(.svelte-tqqrb7):hover{background:transparent}.disclosure.svelte-tqqrb7{color:var(--chrome-muted);flex-shrink:0}.method.svelte-tqqrb7{width:6ch;flex-shrink:0;font-size:.6875rem;color:var(--chrome-muted)}.path.svelte-tqqrb7{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.status.svelte-tqqrb7{color:var(--chrome-text)}.status.failed.svelte-tqqrb7,.error.svelte-tqqrb7{color:var(--err)}.status.redirect.svelte-tqqrb7{color:var(--warn)}.duration.svelte-tqqrb7,.unit.svelte-tqqrb7{color:var(--chrome-muted)}.inspector.svelte-tqqrb7{min-width:0;min-height:0;overflow:auto;padding:0 20px 20px;background:var(--bg-2);border-left:1px solid var(--chrome-border);overflow-wrap:anywhere}.inspector.svelte-tqqrb7 header:where(.svelte-tqqrb7){position:sticky;top:0;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 0;margin-bottom:8px;background:var(--bg-2);z-index:2}.inspector.svelte-tqqrb7 h3:where(.svelte-tqqrb7){margin:0;font-size:inherit;font-weight:500}.close-inspector.svelte-tqqrb7{min-height:28px;width:28px;border:0;padding:0}.inspector.svelte-tqqrb7>strong:where(.svelte-tqqrb7){font-weight:500}.inspector.svelte-tqqrb7 p:where(.svelte-tqqrb7),.inspector.svelte-tqqrb7>span:where(.svelte-tqqrb7){color:var(--chrome-muted)}.replay.svelte-tqqrb7{border:1px solid var(--chrome-border);padding:6px 10px}.empty.svelte-tqqrb7{padding:28px 20px;color:var(--chrome-muted);text-align:center}.empty.svelte-tqqrb7 strong:where(.svelte-tqqrb7){color:var(--chrome-text);font-weight:500}.empty.svelte-tqqrb7 p:where(.svelte-tqqrb7){margin:6px 0 0}@media(max-width:900px){.requests-panel.inspecting.svelte-tqqrb7{grid-template-columns:minmax(0,1fr)}.inspecting.svelte-tqqrb7 .request-list:where(.svelte-tqqrb7){display:none}.inspector.svelte-tqqrb7{border-left:0}}@media(max-width:680px){th.svelte-tqqrb7,td.svelte-tqqrb7{padding:8px}.numeric.svelte-tqqrb7{width:65px}.service-column.svelte-tqqrb7{width:22%}.request-cell.svelte-tqqrb7 button:where(.svelte-tqqrb7){gap:5px}.inspector.svelte-tqqrb7{padding:16px}}.source-tabs-row.svelte-147la1m{display:flex;align-items:stretch;flex-shrink:0;min-width:0;border-bottom:1px solid var(--chrome-border)}.request-options.svelte-147la1m{position:relative;flex-shrink:0;margin-left:auto}.request-options.svelte-147la1m summary:where(.svelte-147la1m){height:100%;padding:8px 14px;border:0;border-left:1px solid var(--chrome-border);color:var(--chrome-muted)}.request-options-menu.svelte-147la1m{position:absolute;bottom:calc(100% + 8px);right:0;z-index:32;width:max-content;max-width:calc(100vw - 80px);padding:8px 12px;border:1px solid var(--chrome-border);background:var(--chrome);box-shadow:0 8px 24px #0005}.request-options-menu.svelte-147la1m label:where(.svelte-147la1m){display:flex;align-items:center;gap:8px;cursor:pointer;font-size:.75rem}.request-options-menu.svelte-147la1m input:where(.svelte-147la1m){flex-shrink:0}.logs-dock.svelte-147la1m{position:relative;display:flex;flex-direction:column;min-height:0;min-width:0;color:var(--chrome-text);background:var(--chrome);border-top:1px solid var(--chrome-border)}.resize-handle.svelte-147la1m{position:absolute;top:-4px;left:0;right:0;height:8px;cursor:ns-resize;touch-action:none;z-index:31}.resize-handle.svelte-147la1m:hover,.resize-handle.svelte-147la1m:focus-visible{background:var(--chrome-muted);outline:none}.logs-toolbar.svelte-147la1m{display:flex;align-items:center;gap:8px;padding:8px 14px;flex:0 0 auto}h2.svelte-147la1m{display:flex;align-items:center;gap:8px;margin:0 10px 0 0;font-size:.875rem;font-weight:500}button.svelte-147la1m,summary.svelte-147la1m{border-radius:0;display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:32px;color:var(--chrome-text);border-color:var(--chrome-border);font-size:.75rem;padding:5px 9px}button.svelte-147la1m:hover,summary.svelte-147la1m:hover{background:#ffffff0b;border-color:var(--chrome-muted)}button.svelte-147la1m:focus-visible,summary.svelte-147la1m:focus-visible,input.svelte-147la1m:focus-visible,.log-output.svelte-147la1m:focus-visible{outline:2px solid var(--chrome-muted);outline-offset:-2px}.source-picker.svelte-147la1m{position:relative;flex-shrink:0}summary.svelte-147la1m{list-style:none;border:1px solid var(--chrome-border)}summary.svelte-147la1m::-webkit-details-marker{display:none}.count.svelte-147la1m{color:var(--chrome-muted)}.source-options.svelte-147la1m{position:absolute;bottom:calc(100% + 8px);left:0;z-index:30;width:min(300px,calc(100vw - 40px));max-height:min(420px,calc(100dvh - var(--logs-height) - 64px));overflow:auto;border:1px solid var(--chrome-border);padding:8px;background:var(--chrome);box-shadow:0 8px 24px #0005}.source-group.svelte-147la1m{border:0;padding:0;margin:0;min-width:0}.source-group.svelte-147la1m+.source-group:where(.svelte-147la1m){border-top:1px solid var(--chrome-border);margin-top:8px;padding-top:8px}.source-group.svelte-147la1m legend:where(.svelte-147la1m){position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.source-options.svelte-147la1m .group-toggle:where(.svelte-147la1m){justify-content:space-between;gap:12px;font-weight:500}.group-toggle.svelte-147la1m>span:where(.svelte-147la1m):first-child{min-width:0;overflow-wrap:anywhere}.select-all.svelte-147la1m{display:inline-flex;align-items:center;gap:6px;flex-shrink:0;color:var(--chrome-muted);font-size:.6875rem;font-weight:400}.source-options.svelte-147la1m .service-choice:where(.svelte-147la1m){padding-left:22px}.source-options.svelte-147la1m input:where(.svelte-147la1m){flex-shrink:0}.source-options.svelte-147la1m label:where(.svelte-147la1m){display:flex;align-items:center;gap:9px;padding:6px 8px;cursor:pointer;font-size:.8125rem}.source-options.svelte-147la1m label:where(.svelte-147la1m):hover{background:#ffffff0b}.source-options.svelte-147la1m input:where(.svelte-147la1m){accent-color:var(--accent)}.filter.svelte-147la1m{display:flex;align-items:center;gap:7px;flex:1;min-width:110px;max-width:360px;color:var(--chrome-muted);border:1px solid var(--chrome-border);padding-left:9px}.filter.svelte-147la1m input:where(.svelte-147la1m){border-radius:0;min-width:0;width:100%;min-height:30px;border:0;padding:4px 8px 4px 0;font-size:.75rem;color:var(--chrome-text)}.filter.svelte-147la1m input:where(.svelte-147la1m)::placeholder{color:var(--chrome-muted)}.close.svelte-147la1m{margin-left:auto;width:32px;padding:0;flex-shrink:0;border:0;background:transparent;color:var(--chrome-muted)}.close.svelte-147la1m:hover{background:transparent;color:var(--chrome-text)}.source-tabs.svelte-147la1m{display:flex;gap:0;min-width:0;overflow-x:auto;padding:0 0 0 14px}.source-tab.svelte-147la1m,.source-tabs.svelte-147la1m .all-sources:where(.svelte-147la1m){display:flex;flex-shrink:0;align-items:center;border:0;border-right:1px solid var(--chrome-border);border-bottom:2px solid transparent;border-radius:0;color:var(--chrome-muted)}.source-tab.active.svelte-147la1m,.source-tabs.svelte-147la1m .all-sources.active:where(.svelte-147la1m){border-bottom-color:var(--accent);background:var(--bg-3);color:var(--chrome-text)}.source-tabs.svelte-147la1m button:where(.svelte-147la1m){border:0;border-radius:0;color:inherit;background:transparent;transform:none}.source-tabs.svelte-147la1m .all-sources:where(.svelte-147la1m){padding:8px 12px}.source-tabs.svelte-147la1m .source-select:where(.svelte-147la1m){align-self:stretch;padding:8px 8px 8px 12px}.source-tab.svelte-147la1m:hover,.source-tabs.svelte-147la1m .all-sources:where(.svelte-147la1m):hover{background:var(--bg-3);color:var(--chrome-text)}.source-tabs.svelte-147la1m .source-select:where(.svelte-147la1m):hover{background:transparent}.source-tabs.svelte-147la1m .clear-source:where(.svelte-147la1m){width:24px;min-height:28px;align-self:stretch;padding:0;margin:0;flex-shrink:0;color:var(--chrome-muted)}.source-tabs.svelte-147la1m .clear-source:where(.svelte-147la1m):hover:not(:disabled){color:var(--err);background:transparent}.source-tabs.svelte-147la1m .clear-source:where(.svelte-147la1m):active:not(:disabled){color:var(--err);background:transparent}.clear-source.svelte-147la1m:disabled{opacity:.4;cursor:wait}.project-name.svelte-147la1m{opacity:.7}.log-output.svelte-147la1m{flex:1;overflow:auto;min-height:0;padding:8px 0;font:.75rem/1.75 var(--mono)}.log-row.svelte-147la1m{display:grid;grid-template-columns:8ch minmax(12ch,22ch) 6ch minmax(0,1fr) 24px;gap:14px;padding:5px 14px;align-items:start}.log-row.single-source.svelte-147la1m{grid-template-columns:8ch 6ch minmax(0,1fr) 24px}.copy-line.svelte-147la1m{opacity:0;min-height:24px;width:24px;padding:0;border:0;color:var(--chrome-muted)}.log-row.svelte-147la1m:hover .copy-line:where(.svelte-147la1m),.copy-line.svelte-147la1m:focus-visible{opacity:1}.copy-line.svelte-147la1m:hover{background:transparent;color:var(--chrome-text)}.log-controls.svelte-147la1m{display:flex;gap:12px}.service-signal.svelte-147la1m{width:6px;height:6px;flex-shrink:0;background:var(--chrome-muted)}.service-signal.running.svelte-147la1m{background:var(--ok)}.service-signal.starting.svelte-147la1m{background:var(--warn)}.service-state.svelte-147la1m{margin-left:auto;color:var(--chrome-muted);font-size:.6875rem}@media(pointer:coarse){.copy-line.svelte-147la1m{opacity:1}}.log-row.svelte-147la1m:nth-child(2n){background:#ffffff03}.log-row.svelte-147la1m:hover{background:var(--bg-3)}time.svelte-147la1m{color:var(--chrome-muted);font-size:.6875rem;font-variant-numeric:tabular-nums;padding-top:1px}.source.svelte-147la1m{color:var(--chrome-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.6875rem;padding-top:1px}.stream.svelte-147la1m{color:var(--chrome-muted);font-size:.6875rem;padding-top:1px}.line.svelte-147la1m{min-width:0;white-space:pre-wrap;overflow-wrap:anywhere;-moz-tab-size:2;tab-size:2}.shared.svelte-147la1m .stream:where(.svelte-147la1m){color:var(--share)}.stderr.svelte-147la1m .stream:where(.svelte-147la1m){color:var(--warn)}@media(max-width:680px){.log-row.svelte-147la1m{grid-template-columns:8ch minmax(0,1fr) 6ch;gap:4px 10px;padding:7px 10px}.log-row.single-source.svelte-147la1m{grid-template-columns:8ch minmax(0,1fr)}.line.svelte-147la1m{grid-column:1 / -1}.copy-line.svelte-147la1m{grid-column:-2 / -1;justify-self:end;opacity:1}}.empty.svelte-147la1m{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100%;gap:4px;text-align:center;font-family:var(--sans)}.empty.svelte-147la1m strong:where(.svelte-147la1m){font-weight:500;font-size:.8125rem}.empty.svelte-147la1m span:where(.svelte-147la1m){color:var(--chrome-muted)}.history-error.svelte-147la1m{padding:8px 14px;color:var(--chrome-text);display:flex;align-items:center;gap:12px}.logs-status.svelte-147la1m{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-shrink:0;min-height:30px;padding:0 14px;border-top:1px solid var(--chrome-border);color:var(--chrome-muted);font-size:.6875rem}.logs-status.svelte-147la1m button:where(.svelte-147la1m){border:0;min-height:28px;font-size:.6875rem;padding:2px 5px}@media(max-width:680px){.logs-toolbar.svelte-147la1m{flex-wrap:wrap;gap:6px;padding:6px 10px}h2.svelte-147la1m{margin-right:0}.filter.svelte-147la1m{order:5;flex-basis:100%;max-width:none}.record-count.svelte-147la1m{display:none}}.layout.svelte-1n46o8q{position:relative;display:grid;grid-template-columns:var(--sidebar-width) minmax(0,1fr);grid-template-rows:minmax(0,1fr) auto auto;height:100dvh;min-height:0;background:var(--chrome)}.app-rail.svelte-1n46o8q{position:relative;grid-row:1 / 3;min-height:0;border-right:1px solid var(--chrome-border);display:flex;flex-direction:column;color:var(--chrome-text)}.brand.svelte-1n46o8q{letter-spacing:-.03em;display:flex;align-items:center;justify-content:space-between;padding:20px 16px;font:500 var(--text-section)/1.2 var(--sans);text-transform:none}.brand-identity.svelte-1n46o8q{display:flex;align-items:center;gap:10px;min-width:0}.brand-identity.svelte-1n46o8q img:where(.svelte-1n46o8q){display:block;flex-shrink:0}.brand-name.svelte-1n46o8q{font-size:var(--text-label)}.collapsed.svelte-1n46o8q .brand-name:where(.svelte-1n46o8q){display:none}.app-rail.svelte-1n46o8q nav:where(.svelte-1n46o8q){display:grid;grid-template-columns:minmax(0,1fr);gap:4px;padding:0 8px}.app-rail.svelte-1n46o8q :is(button:where(.svelte-1n46o8q),a:where(.svelte-1n46o8q)){display:flex;align-items:center;gap:10px;width:100%;min-height:44px;padding:12px 16px;font:500 var(--text-body)/1.4 var(--sans);text-transform:none;color:var(--chrome-muted);background:transparent;border:0;border-left:3px solid transparent;text-align:left}.app-rail.svelte-1n46o8q :where(.svelte-1n46o8q):is(button:where(.svelte-1n46o8q),a:where(.svelte-1n46o8q)):hover{color:var(--chrome-text);background:#ffffff0c}.app-rail.svelte-1n46o8q a:where(.svelte-1n46o8q){text-decoration:none}.app-rail.svelte-1n46o8q a.active:where(.svelte-1n46o8q){color:var(--accent);border-left-color:var(--accent);background:var(--selected)}.app-rail.svelte-1n46o8q :is(button:where(.svelte-1n46o8q),a:where(.svelte-1n46o8q)) svg{flex-shrink:0}main.svelte-1n46o8q{grid-column:2;grid-row:1;min-width:0;min-height:0;overflow:auto;display:flex;flex-direction:column;background:var(--bg);color:var(--text)}.logs-slot.svelte-1n46o8q{grid-column:2;grid-row:2;min-width:0}.statusbar.svelte-1n46o8q{grid-column:1 / -1;grid-row:3;min-height:40px;display:flex;align-items:center;gap:24px;border-top:1px solid var(--chrome-border);color:var(--chrome-muted);font-size:var(--text-small)}.runtime-label.svelte-1n46o8q{width:var(--sidebar-width);align-self:stretch;display:flex;align-items:center;flex-shrink:0;padding:0 20px;border-right:1px solid var(--chrome-border)}.collapsed.svelte-1n46o8q .runtime-label:where(.svelte-1n46o8q){width:64px;padding:0 8px;font-size:11px}.panel-controls.svelte-1n46o8q{display:flex;align-items:center;gap:8px;margin-left:auto;margin-right:16px}.statusbar.svelte-1n46o8q .logs-toggle:where(.svelte-1n46o8q){min-height:30px;color:var(--chrome-muted);border:0;background:transparent;text-decoration:underline;text-underline-offset:4px}.statusbar.svelte-1n46o8q .logs-toggle:where(.svelte-1n46o8q):hover,.statusbar.svelte-1n46o8q .logs-toggle[aria-expanded=true]:where(.svelte-1n46o8q){background:transparent;color:var(--chrome-text);text-decoration-thickness:2px}.connection.svelte-1n46o8q{display:flex;align-items:center;gap:14px}.connection.svelte-1n46o8q i:where(.svelte-1n46o8q){display:block;width:7px;height:7px;border-radius:50%;background:var(--muted)}.connection.connected.svelte-1n46o8q i:where(.svelte-1n46o8q){background:var(--orange)}.port-status.svelte-1n46o8q{padding-left:30px;border-left:1px solid var(--chrome-border)}.catalog-error.svelte-1n46o8q{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 24px;color:var(--err);background:var(--bg-2)}h2.svelte-1n46o8q{font:500 var(--text-section)/1.4 var(--sans)}.all-service-grid.svelte-1n46o8q{display:grid;margin-top:14px}.all-service-card.svelte-1n46o8q{display:grid;justify-content:stretch;min-width:0;padding:18px 16px;gap:6px;text-align:left;white-space:normal;background:transparent;border:0;border-bottom:1px solid var(--border);border-radius:0}.all-service-card.svelte-1n46o8q:hover{background:var(--bg-3)}.service-heading.svelte-1n46o8q strong:where(.svelte-1n46o8q){font:500 var(--text-label)/1.4 var(--sans)}.service-heading.svelte-1n46o8q{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.service-status.svelte-1n46o8q{margin-left:auto;color:var(--muted);font:var(--text-small)/1.4 var(--sans);text-transform:none}.project-name.svelte-1n46o8q{color:var(--muted);font-size:var(--text-small)}.empty-state.svelte-1n46o8q{width:100%;padding:48px 32px;text-align:center;color:var(--muted)}.load-state.svelte-1n46o8q{display:block;color:var(--muted)}.empty-state.svelte-1n46o8q h2:where(.svelte-1n46o8q),.load-state.svelte-1n46o8q h1:where(.svelte-1n46o8q){color:var(--text)}.global-settings.svelte-1n46o8q{font-size:var(--text-body);line-height:1.8}.global-settings.svelte-1n46o8q h3:where(.svelte-1n46o8q){margin-top:40px;font:500 var(--text-section)/1.4 var(--sans)}.global-settings.svelte-1n46o8q label:where(.svelte-1n46o8q){display:flex;gap:12px;align-items:center}.forwarder-error.svelte-1n46o8q{color:var(--err)}.collapsed.svelte-1n46o8q{grid-template-columns:64px minmax(0,1fr)}.app-rail.svelte-1n46o8q .collapse-toggle:where(.svelte-1n46o8q){width:36px;min-height:44px;flex-shrink:0;padding:4px;border:0;justify-content:center}.collapsed.svelte-1n46o8q .brand:where(.svelte-1n46o8q){flex-direction:column;gap:12px;padding:16px 4px}.collapsed.svelte-1n46o8q nav:where(.svelte-1n46o8q) a:where(.svelte-1n46o8q){justify-content:center;padding:12px 0}.collapsed.svelte-1n46o8q nav:where(.svelte-1n46o8q) a:where(.svelte-1n46o8q) span:where(.svelte-1n46o8q){display:none}.palette-trigger.svelte-1n46o8q span:where(.svelte-1n46o8q){min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.palette-trigger.svelte-1n46o8q kbd:where(.svelte-1n46o8q){margin-left:auto;flex-shrink:0;font:11px var(--mono)}.collapsed.svelte-1n46o8q .palette-trigger:where(.svelte-1n46o8q){justify-content:center;padding:12px 0}.collapsed.svelte-1n46o8q .palette-trigger:where(.svelte-1n46o8q) span:where(.svelte-1n46o8q),.collapsed.svelte-1n46o8q .palette-trigger:where(.svelte-1n46o8q) kbd:where(.svelte-1n46o8q){display:none}.app-rail.svelte-1n46o8q .clean-urls-warning:where(.svelte-1n46o8q){margin-top:auto;border:0;border-top:1px solid var(--chrome-border);padding:16px 20px;color:#d1b78d;flex-shrink:0;justify-content:flex-start;white-space:normal}.app-rail.svelte-1n46o8q .clean-urls-warning:where(.svelte-1n46o8q):hover{color:#ead5ac;background:#ffffff0c;text-decoration:none}.clean-urls-warning.svelte-1n46o8q strong:where(.svelte-1n46o8q),.clean-urls-warning.svelte-1n46o8q small:where(.svelte-1n46o8q){display:block}.clean-urls-warning.svelte-1n46o8q strong:where(.svelte-1n46o8q){font-size:var(--text-small);font-weight:500}.clean-urls-warning.svelte-1n46o8q small:where(.svelte-1n46o8q){color:var(--chrome-muted);font-size:var(--text-small)}.collapsed.svelte-1n46o8q .clean-urls-warning:where(.svelte-1n46o8q){justify-content:center;padding:16px 0}.collapsed.svelte-1n46o8q .clean-urls-warning:where(.svelte-1n46o8q) span:where(.svelte-1n46o8q){display:none}.project-shortcuts.svelte-1n46o8q{overflow:auto;padding:24px 8px}.project-shortcuts.svelte-1n46o8q p:where(.svelte-1n46o8q){padding:0 12px;color:var(--chrome-muted);font:var(--text-small)/1.4 var(--sans);text-transform:none}.project-shortcuts.svelte-1n46o8q button:where(.svelte-1n46o8q){text-transform:none;overflow:hidden;text-overflow:ellipsis;display:block;min-height:36px;padding:8px 12px}.project-shortcuts.svelte-1n46o8q button.current:where(.svelte-1n46o8q){color:var(--accent);background:var(--selected)}.sidebar-resizer.svelte-1n46o8q{position:absolute;right:-3px;top:0;bottom:0;width:7px;cursor:col-resize;touch-action:none;z-index:10}.sidebar-resizer.svelte-1n46o8q:hover,.sidebar-resizer.svelte-1n46o8q:focus-visible{background:var(--orange)}.all-search.svelte-1n46o8q{display:flex;align-items:center;gap:16px;margin-top:24px;color:var(--muted)}.all-search.svelte-1n46o8q input:where(.svelte-1n46o8q){width:min(360px,100%)}@media(max-width:760px){.layout.svelte-1n46o8q,.layout.collapsed.svelte-1n46o8q{grid-template-columns:64px minmax(0,1fr)}.layout.svelte-1n46o8q:not(.collapsed) .app-rail:where(.svelte-1n46o8q){position:absolute;inset:0 auto 0 0;width:min(var(--sidebar-width),calc(100vw - 64px));z-index:20;background:var(--chrome)}.sidebar-resizer.svelte-1n46o8q{display:none}.statusbar.svelte-1n46o8q{gap:10px;font-size:11px}.runtime-label.svelte-1n46o8q{width:64px;padding:0 8px;font-size:11px}.panel-controls.svelte-1n46o8q{gap:0;margin-right:8px}.statusbar.svelte-1n46o8q .logs-toggle:where(.svelte-1n46o8q){padding:4px 8px}.port-status.svelte-1n46o8q{padding-left:10px}.connection.svelte-1n46o8q{gap:6px}.connection.svelte-1n46o8q i:where(.svelte-1n46o8q){width:6px;height:6px}.all-search.svelte-1n46o8q{align-items:stretch;flex-direction:column;gap:6px}}