archbyte 0.5.0 → 0.5.2

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.
@@ -20,6 +20,25 @@ let sourceWatcher = null;
20
20
  const pendingSourceChanges = new Map();
21
21
  let changeDebounceTimer = null;
22
22
  const CHANGE_DEBOUNCE_MS = 2500;
23
+ function pendingChangesPath() {
24
+ return path.join(config.workspaceRoot, ".archbyte", "pending-changes.json");
25
+ }
26
+ function savePendingChanges() {
27
+ const entries = Array.from(pendingSourceChanges.values());
28
+ writeFile(pendingChangesPath(), JSON.stringify(entries), "utf-8").catch(() => { });
29
+ }
30
+ function loadPendingChanges() {
31
+ try {
32
+ const raw = readFileSync(pendingChangesPath(), "utf-8");
33
+ const entries = JSON.parse(raw);
34
+ for (const entry of entries) {
35
+ pendingSourceChanges.set(entry.path, entry);
36
+ }
37
+ }
38
+ catch {
39
+ // No persisted changes — fresh start
40
+ }
41
+ }
23
42
  const sessionChanges = [];
24
43
  const MAX_SESSION_CHANGES = 50;
25
44
  let currentArchitecture = null;
@@ -33,7 +52,7 @@ function getArchbyteBin() {
33
52
  }
34
53
  catch {
35
54
  // Fallback: resolve relative to this package
36
- return path.resolve(__dirname, "../../../cli/dist/index.js");
55
+ return path.resolve(__dirname, "../../../bin/archbyte.js");
37
56
  }
38
57
  }
39
58
  // Broadcast ops event to SSE clients
@@ -119,6 +138,11 @@ function createHttpServer() {
119
138
  return;
120
139
  }
121
140
  const url = req.url || "/";
141
+ // Log API actions to terminal (skip static files, SSE, health checks)
142
+ if (url.startsWith("/api/") && url !== "/api/health") {
143
+ const label = url.replace("/api/", "").split("?")[0];
144
+ console.error(`[archbyte] ${req.method} ${label}`);
145
+ }
122
146
  // SSE endpoint
123
147
  if (url === "/events") {
124
148
  res.writeHead(200, {
@@ -260,77 +284,72 @@ function createHttpServer() {
260
284
  }));
261
285
  return;
262
286
  }
263
- // API: Impact analysisblast radius BFS from a node
264
- if (url.startsWith("/api/impact/") && req.method === "GET") {
287
+ // API: Deep Drillfocused static analysis of a single component
288
+ if (url.startsWith("/api/component/") && url.includes("/deep") && req.method === "GET") {
265
289
  const arch = currentArchitecture || (await loadArchitecture());
266
290
  if (!arch) {
267
291
  res.writeHead(404, { "Content-Type": "application/json" });
268
292
  res.end(JSON.stringify({ error: "No architecture loaded" }));
269
293
  return;
270
294
  }
271
- const urlParts = url.split("?");
272
- const nodeId = decodeURIComponent(urlParts[0].replace("/api/impact/", ""));
273
- const params = new URL(url, `http://localhost:${config.port}`).searchParams;
274
- const depth = Math.min(Math.max(parseInt(params.get("depth") || "2", 10) || 2, 1), 5);
275
- const direction = params.get("direction") || "both";
276
- // Build adjacency lists
277
- const forward = new Map();
278
- const reverse = new Map();
279
- for (const nd of arch.nodes) {
280
- forward.set(nd.id, []);
281
- reverse.set(nd.id, []);
295
+ // Extract component ID: /api/component/{id}/deep
296
+ const urlPath = url.split("?")[0];
297
+ const match = urlPath.match(/^\/api\/component\/(.+)\/deep$/);
298
+ if (!match) {
299
+ res.writeHead(400, { "Content-Type": "application/json" });
300
+ res.end(JSON.stringify({ error: "Invalid URL format" }));
301
+ return;
282
302
  }
283
- for (const edge of arch.edges) {
284
- forward.get(edge.source)?.push(edge.target);
285
- reverse.get(edge.target)?.push(edge.source);
303
+ const componentId = decodeURIComponent(match[1]);
304
+ const node = arch.nodes.find((n) => n.id === componentId);
305
+ if (!node) {
306
+ res.writeHead(404, { "Content-Type": "application/json" });
307
+ res.end(JSON.stringify({ error: `Component not found: ${componentId}` }));
308
+ return;
286
309
  }
287
- const nodeMap = new Map();
288
- for (const nd of arch.nodes)
289
- nodeMap.set(nd.id, nd);
290
- // BFS helper
291
- function bfs(startId, adj, maxDepth) {
292
- const visited = new Map();
293
- visited.set(startId, 0);
294
- const queue = [{ id: startId, d: 0 }];
295
- const result = [];
296
- while (queue.length > 0) {
297
- const { id, d } = queue.shift();
298
- if (d >= maxDepth)
299
- continue;
300
- for (const neighbor of adj.get(id) || []) {
301
- if (!visited.has(neighbor)) {
302
- const nd = d + 1;
303
- visited.set(neighbor, nd);
304
- result.push({ id: neighbor, label: nodeMap.get(neighbor)?.label.split("\n")[0] || neighbor, depth: nd });
305
- queue.push({ id: neighbor, d: nd });
306
- }
310
+ const nodePath = node.path;
311
+ if (!nodePath) {
312
+ res.writeHead(400, { "Content-Type": "application/json" });
313
+ res.end(JSON.stringify({ error: `Component "${node.label}" has no path` }));
314
+ return;
315
+ }
316
+ try {
317
+ const { runDeepDrill } = await import("../../agents/static/deep-drill.js");
318
+ const result = await runDeepDrill(config.workspaceRoot, componentId, node.label.split("\n")[0], nodePath);
319
+ // Enrich with connection data from architecture edges
320
+ const outgoing = [];
321
+ const incoming = [];
322
+ const nodeMap = new Map();
323
+ for (const n of arch.nodes)
324
+ nodeMap.set(n.id, n);
325
+ for (const edge of arch.edges) {
326
+ if (edge.source === componentId) {
327
+ const target = nodeMap.get(edge.target);
328
+ outgoing.push({
329
+ targetId: edge.target,
330
+ targetName: target?.label.split("\n")[0] || edge.target,
331
+ type: edge.label || "depends-on",
332
+ description: edge.label || "",
333
+ });
334
+ }
335
+ if (edge.target === componentId) {
336
+ const source = nodeMap.get(edge.source);
337
+ incoming.push({
338
+ sourceId: edge.source,
339
+ sourceName: source?.label.split("\n")[0] || edge.source,
340
+ type: edge.label || "depends-on",
341
+ description: edge.label || "",
342
+ });
307
343
  }
308
344
  }
309
- return result;
310
- }
311
- const upstream = (direction === "downstream") ? [] : bfs(nodeId, reverse, depth);
312
- const downstream = (direction === "upstream") ? [] : bfs(nodeId, forward, depth);
313
- // Collect all affected node IDs (including origin)
314
- const affectedSet = new Set([nodeId]);
315
- for (const n of upstream)
316
- affectedSet.add(n.id);
317
- for (const n of downstream)
318
- affectedSet.add(n.id);
319
- // Affected edges: edges between any two nodes in the affected set
320
- const affectedEdges = [];
321
- for (const edge of arch.edges) {
322
- if (affectedSet.has(edge.source) && affectedSet.has(edge.target)) {
323
- affectedEdges.push(edge.id);
324
- }
345
+ result.connections = { outgoing, incoming };
346
+ res.writeHead(200, { "Content-Type": "application/json" });
347
+ res.end(JSON.stringify(result));
348
+ }
349
+ catch (error) {
350
+ res.writeHead(500, { "Content-Type": "application/json" });
351
+ res.end(JSON.stringify({ error: String(error) }));
325
352
  }
326
- res.writeHead(200, { "Content-Type": "application/json" });
327
- res.end(JSON.stringify({
328
- nodeId,
329
- upstream,
330
- downstream,
331
- affectedEdges,
332
- totalAffected: affectedSet.size - 1,
333
- }));
334
353
  return;
335
354
  }
336
355
  // API: Audit — unified validation + health endpoint
@@ -1115,7 +1134,7 @@ function createHttpServer() {
1115
1134
  const child = spawn(process.execPath, [bin, "generate"], {
1116
1135
  cwd: config.workspaceRoot,
1117
1136
  stdio: ["ignore", "pipe", "pipe"],
1118
- env: { ...process.env, FORCE_COLOR: "0" },
1137
+ env: { ...process.env, FORCE_COLOR: "0", ARCHBYTE_INTERNAL: "1" },
1119
1138
  });
1120
1139
  runningWorkflows.set("__generate__", child);
1121
1140
  broadcastOpsEvent({ type: "generate:started" });
@@ -1133,6 +1152,18 @@ function createHttpServer() {
1133
1152
  res.end(JSON.stringify({ running: runningWorkflows.has("__generate__") }));
1134
1153
  return;
1135
1154
  }
1155
+ // API: Reload — re-read architecture, reconcile pending changes
1156
+ if (url === "/api/reload" && req.method === "POST") {
1157
+ currentArchitecture = await loadArchitecture();
1158
+ reconcilePendingWithGit();
1159
+ broadcastUpdate();
1160
+ if (pendingSourceChanges.size > 0) {
1161
+ broadcastPendingChanges();
1162
+ }
1163
+ res.writeHead(200, { "Content-Type": "application/json" });
1164
+ res.end(JSON.stringify({ ok: true }));
1165
+ return;
1166
+ }
1136
1167
  // API: Run analyze (static or LLM) + generate
1137
1168
  if (url === "/api/analyze" && req.method === "POST") {
1138
1169
  if (isAnalyzing) {
@@ -1164,10 +1195,17 @@ function createHttpServer() {
1164
1195
  }
1165
1196
  // API: Pending source file changes — hydrates UI on reconnect
1166
1197
  if (url === "/api/changes/pending" && req.method === "GET") {
1167
- const files = Array.from(pendingSourceChanges.values()).map((c) => ({ event: c.event, path: c.path }));
1168
- const count = files.length;
1198
+ const changes = Array.from(pendingSourceChanges.values()).map((c) => ({ event: c.event, path: c.path }));
1199
+ const count = changes.length;
1200
+ const { componentChanges, unmapped } = mapFilesToComponents(changes, currentArchitecture);
1169
1201
  res.writeHead(200, { "Content-Type": "application/json" });
1170
- res.end(JSON.stringify({ count, files: files.slice(0, 20), truncated: count > 20 }));
1202
+ res.end(JSON.stringify({
1203
+ count,
1204
+ files: changes.slice(0, 20).map((c) => ({ event: c.event, path: c.path })),
1205
+ componentChanges,
1206
+ unmapped,
1207
+ truncated: count > 20,
1208
+ }));
1171
1209
  return;
1172
1210
  }
1173
1211
  // API: Run workflow
@@ -1188,7 +1226,7 @@ function createHttpServer() {
1188
1226
  const child = spawn(process.execPath, [bin, "workflow", "--run", id], {
1189
1227
  cwd: config.workspaceRoot,
1190
1228
  stdio: ["ignore", "pipe", "pipe"],
1191
- env: { ...process.env, FORCE_COLOR: "0" },
1229
+ env: { ...process.env, FORCE_COLOR: "0", ARCHBYTE_INTERNAL: "1" },
1192
1230
  });
1193
1231
  runningWorkflows.set(id, child);
1194
1232
  broadcastOpsEvent({ type: "workflow:started", id });
@@ -1419,6 +1457,22 @@ function createHttpServer() {
1419
1457
  }
1420
1458
  return;
1421
1459
  }
1460
+ // API: UI event logging — fire-and-forget from UI to server console
1461
+ if (url === "/api/ui-event" && req.method === "POST") {
1462
+ let body = "";
1463
+ req.on("data", (chunk) => { body += chunk.toString(); });
1464
+ req.on("end", () => {
1465
+ try {
1466
+ const { event, detail } = JSON.parse(body);
1467
+ const msg = detail ? `${event} — ${detail}` : event;
1468
+ console.error(`[archbyte] ui: ${msg}`);
1469
+ }
1470
+ catch { }
1471
+ res.writeHead(204);
1472
+ res.end();
1473
+ });
1474
+ return;
1475
+ }
1422
1476
  // API: Telemetry — record agent timing data
1423
1477
  if (url === "/api/telemetry" && req.method === "POST") {
1424
1478
  let body = "";
@@ -1666,6 +1720,7 @@ function runAnalyzePipeline(mode = "static", fileChanges) {
1666
1720
  fileChanges = Array.from(pendingSourceChanges.values()).map((c) => ({ event: c.event, path: c.path }));
1667
1721
  }
1668
1722
  pendingSourceChanges.clear();
1723
+ savePendingChanges();
1669
1724
  if (changeDebounceTimer) {
1670
1725
  clearTimeout(changeDebounceTimer);
1671
1726
  changeDebounceTimer = null;
@@ -1683,20 +1738,26 @@ function runAnalyzePipeline(mode = "static", fileChanges) {
1683
1738
  const analyzeChild = spawn(process.execPath, analyzeArgs, {
1684
1739
  cwd: config.workspaceRoot,
1685
1740
  stdio: ["ignore", "pipe", "pipe"],
1686
- env: { ...process.env, FORCE_COLOR: "0" },
1741
+ env: { ...process.env, FORCE_COLOR: "0", ARCHBYTE_INTERNAL: "1" },
1687
1742
  });
1743
+ let analyzeStderr = "";
1744
+ analyzeChild.stdout?.on("data", (d) => process.stderr.write(`[analyze] ${d}`));
1745
+ analyzeChild.stderr?.on("data", (d) => { analyzeStderr += d; process.stderr.write(`[analyze] ${d}`); });
1688
1746
  analyzeChild.on("close", (analyzeCode) => {
1689
1747
  if (analyzeCode !== 0) {
1690
1748
  isAnalyzing = false;
1691
- broadcastOpsEvent({ type: "analyzing:finished", code: analyzeCode, success: false });
1749
+ const errMsg = analyzeStderr.trim().split("\n").pop() || `Analyze failed (exit ${analyzeCode})`;
1750
+ broadcastOpsEvent({ type: "analyzing:finished", code: analyzeCode, success: false, error: errMsg });
1692
1751
  return;
1693
1752
  }
1694
1753
  // Chain: generate after successful analyze
1695
1754
  const genChild = spawn(process.execPath, [bin, "generate"], {
1696
1755
  cwd: config.workspaceRoot,
1697
1756
  stdio: ["ignore", "pipe", "pipe"],
1698
- env: { ...process.env, FORCE_COLOR: "0" },
1757
+ env: { ...process.env, FORCE_COLOR: "0", ARCHBYTE_INTERNAL: "1" },
1699
1758
  });
1759
+ genChild.stdout?.on("data", (d) => process.stderr.write(`[generate] ${d}`));
1760
+ genChild.stderr?.on("data", (d) => process.stderr.write(`[generate] ${d}`));
1700
1761
  genChild.on("close", async (genCode) => {
1701
1762
  isAnalyzing = false;
1702
1763
  const durationMs = Date.now() - pipelineStart;
@@ -1761,15 +1822,52 @@ function setupWatcher() {
1761
1822
  broadcastUpdate();
1762
1823
  });
1763
1824
  }
1825
+ // Map changed file paths to architecture components using longest-prefix matching
1826
+ function mapFilesToComponents(changes, arch) {
1827
+ if (!arch || arch.nodes.length === 0) {
1828
+ return { componentChanges: [], unmapped: changes.map((c) => ({ path: c.path, event: c.event })) };
1829
+ }
1830
+ // Build sorted list of component paths (longest first for greedy matching)
1831
+ const componentPaths = arch.nodes
1832
+ .filter((n) => n.path)
1833
+ .map((n) => ({ id: n.id, name: n.label.split("\n")[0], path: n.path }))
1834
+ .sort((a, b) => b.path.length - a.path.length);
1835
+ const groups = new Map();
1836
+ const unmapped = [];
1837
+ for (const change of changes) {
1838
+ let matched = false;
1839
+ for (const comp of componentPaths) {
1840
+ const prefix = comp.path.endsWith("/") ? comp.path : `${comp.path}/`;
1841
+ if (change.path.startsWith(prefix) || change.path === comp.path) {
1842
+ if (!groups.has(comp.id)) {
1843
+ groups.set(comp.id, { componentId: comp.id, componentName: comp.name, files: [] });
1844
+ }
1845
+ groups.get(comp.id).files.push({ path: change.path, event: change.event });
1846
+ matched = true;
1847
+ break;
1848
+ }
1849
+ }
1850
+ if (!matched) {
1851
+ unmapped.push({ path: change.path, event: change.event });
1852
+ }
1853
+ }
1854
+ return {
1855
+ componentChanges: Array.from(groups.values()),
1856
+ unmapped,
1857
+ };
1858
+ }
1764
1859
  // Broadcast pending source changes to SSE clients
1765
1860
  function broadcastPendingChanges() {
1766
- const files = Array.from(pendingSourceChanges.values()).map((c) => c.path);
1767
- const count = files.length;
1861
+ const changes = Array.from(pendingSourceChanges.values()).map((c) => ({ event: c.event, path: c.path }));
1862
+ const count = changes.length;
1768
1863
  const truncated = count > 20;
1864
+ const { componentChanges, unmapped } = mapFilesToComponents(changes, currentArchitecture);
1769
1865
  broadcastOpsEvent({
1770
1866
  type: "changes:detected",
1771
1867
  count,
1772
- files: files.slice(0, 20),
1868
+ files: changes.slice(0, 20).map((c) => c.path),
1869
+ componentChanges,
1870
+ unmapped,
1773
1871
  truncated,
1774
1872
  });
1775
1873
  }
@@ -1808,9 +1906,60 @@ function setupSourceWatcher() {
1808
1906
  changeDebounceTimer = setTimeout(() => {
1809
1907
  changeDebounceTimer = null;
1810
1908
  broadcastPendingChanges();
1909
+ savePendingChanges();
1811
1910
  }, CHANGE_DEBOUNCE_MS);
1812
1911
  });
1813
1912
  }
1913
+ // Watch for git commits — reconcile pending changes against actual dirty files
1914
+ let gitWatcher = null;
1915
+ let gitDebounceTimer = null;
1916
+ function setupGitWatcher() {
1917
+ const gitIndex = path.join(config.workspaceRoot, ".git", "index");
1918
+ if (!existsSync(gitIndex))
1919
+ return;
1920
+ gitWatcher = watch(gitIndex, { ignoreInitial: true, depth: 0 });
1921
+ gitWatcher.on("change", () => {
1922
+ // Debounce — git writes the index multiple times during a commit
1923
+ if (gitDebounceTimer)
1924
+ clearTimeout(gitDebounceTimer);
1925
+ gitDebounceTimer = setTimeout(() => {
1926
+ gitDebounceTimer = null;
1927
+ reconcilePendingWithGit();
1928
+ }, 1000);
1929
+ });
1930
+ }
1931
+ function reconcilePendingWithGit() {
1932
+ if (pendingSourceChanges.size === 0)
1933
+ return;
1934
+ try {
1935
+ // Get files that are still dirty (modified, untracked, staged)
1936
+ const output = execSync("git status --porcelain", {
1937
+ cwd: config.workspaceRoot,
1938
+ encoding: "utf-8",
1939
+ timeout: 5000,
1940
+ });
1941
+ const dirtyFiles = new Set(output.trim().split("\n").filter(Boolean).map((line) => line.slice(3).trim()));
1942
+ let changed = false;
1943
+ for (const [filePath] of pendingSourceChanges) {
1944
+ if (!dirtyFiles.has(filePath)) {
1945
+ pendingSourceChanges.delete(filePath);
1946
+ changed = true;
1947
+ }
1948
+ }
1949
+ if (changed) {
1950
+ savePendingChanges();
1951
+ if (pendingSourceChanges.size === 0) {
1952
+ broadcastOpsEvent({ type: "changes:cleared" });
1953
+ }
1954
+ else {
1955
+ broadcastPendingChanges();
1956
+ }
1957
+ }
1958
+ }
1959
+ catch {
1960
+ // Not a git repo or git not available — ignore
1961
+ }
1962
+ }
1814
1963
  // Graceful shutdown
1815
1964
  function setupShutdown() {
1816
1965
  const shutdown = async () => {
@@ -1839,6 +1988,7 @@ function setupShutdown() {
1839
1988
  sseClients.clear();
1840
1989
  await sourceWatcher?.close();
1841
1990
  await diagramWatcher?.close();
1991
+ await gitWatcher?.close();
1842
1992
  httpServer?.close();
1843
1993
  process.exit(0);
1844
1994
  };
@@ -1929,8 +2079,12 @@ export async function startServer(cfg) {
1929
2079
  console.error("[archbyte] Failed to start HTTP server:", err);
1930
2080
  process.exit(1);
1931
2081
  }
2082
+ currentArchitecture = await loadArchitecture();
1932
2083
  setupWatcher();
2084
+ loadPendingChanges();
2085
+ reconcilePendingWithGit();
1933
2086
  setupSourceWatcher();
2087
+ setupGitWatcher();
1934
2088
  console.error(`[archbyte] Serving ${config.name}`);
1935
2089
  console.error(`[archbyte] Diagram: ${config.diagramPath}`);
1936
2090
  // Listen for 'q' keypress to quit gracefully
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "archbyte",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "ArchByte - See what agents build. As they build it.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1 @@
1
+ @import"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600;700&display=swap";.react-flow{direction:ltr;--xy-edge-stroke-default: #b1b1b7;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #555;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(255, 255, 255, .5);--xy-minimap-background-color-default: #fff;--xy-minimap-mask-background-color-default: rgba(240, 240, 240, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #e2e2e2;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: transparent;--xy-background-pattern-dots-color-default: #91919a;--xy-background-pattern-lines-color-default: #eee;--xy-background-pattern-cross-color-default: #e2e2e2;background-color:var(--xy-background-color, var(--xy-background-color-default));--xy-node-color-default: inherit;--xy-node-border-default: 1px solid #1a192b;--xy-node-background-color-default: #fff;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(0, 0, 0, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #1a192b;--xy-node-border-radius-default: 3px;--xy-handle-background-color-default: #1a192b;--xy-handle-border-color-default: #fff;--xy-selection-background-color-default: rgba(0, 89, 220, .08);--xy-selection-border-default: 1px dotted rgba(0, 89, 220, .8);--xy-controls-button-background-color-default: #fefefe;--xy-controls-button-background-color-hover-default: #f4f4f4;--xy-controls-button-color-default: inherit;--xy-controls-button-color-hover-default: inherit;--xy-controls-button-border-color-default: #eee;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #ffffff;--xy-edge-label-color-default: inherit;--xy-resize-background-color-default: #3367d9}.react-flow.dark{--xy-edge-stroke-default: #3e3e3e;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #727272;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(150, 150, 150, .25);--xy-minimap-background-color-default: #141414;--xy-minimap-mask-background-color-default: rgba(60, 60, 60, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #2b2b2b;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: #141414;--xy-background-pattern-dots-color-default: #777;--xy-background-pattern-lines-color-default: #777;--xy-background-pattern-cross-color-default: #777;--xy-node-color-default: #f8f8f8;--xy-node-border-default: 1px solid #3c3c3c;--xy-node-background-color-default: #1e1e1e;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(255, 255, 255, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #999;--xy-handle-background-color-default: #bebebe;--xy-handle-border-color-default: #1e1e1e;--xy-selection-background-color-default: rgba(200, 200, 220, .08);--xy-selection-border-default: 1px dotted rgba(200, 200, 220, .8);--xy-controls-button-background-color-default: #2b2b2b;--xy-controls-button-background-color-hover-default: #3e3e3e;--xy-controls-button-color-default: #f8f8f8;--xy-controls-button-color-hover-default: #fff;--xy-controls-button-border-color-default: #5b5b5b;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #141414;--xy-edge-label-color-default: #f8f8f8}.react-flow__background{background-color:var(--xy-background-color-props, var(--xy-background-color, var(--xy-background-color-default)));pointer-events:none;z-index:-1}.react-flow__container{position:absolute;width:100%;height:100%;top:0;left:0}.react-flow__pane{z-index:1}.react-flow__pane.draggable{cursor:grab}.react-flow__pane.dragging{cursor:grabbing}.react-flow__pane.selection{cursor:pointer}.react-flow__viewport{transform-origin:0 0;z-index:2;pointer-events:none}.react-flow__renderer{z-index:4}.react-flow__selection{z-index:6}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible{outline:none}.react-flow__edge-path{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default));stroke-width:var(--xy-edge-stroke-width, var(--xy-edge-stroke-width-default));fill:none}.react-flow__connection-path{stroke:var(--xy-connectionline-stroke, var(--xy-connectionline-stroke-default));stroke-width:var(--xy-connectionline-stroke-width, var(--xy-connectionline-stroke-width-default));fill:none}.react-flow .react-flow__edges{position:absolute}.react-flow .react-flow__edges svg{overflow:visible;position:absolute;pointer-events:none}.react-flow__edge{pointer-events:visibleStroke}.react-flow__edge.selectable{cursor:pointer}.react-flow__edge.animated path{stroke-dasharray:5;animation:dashdraw .5s linear infinite}.react-flow__edge.animated path.react-flow__edge-interaction{stroke-dasharray:none;animation:none}.react-flow__edge.inactive{pointer-events:none}.react-flow__edge.selected,.react-flow__edge:focus,.react-flow__edge:focus-visible{outline:none}.react-flow__edge.selected .react-flow__edge-path,.react-flow__edge.selectable:focus .react-flow__edge-path,.react-flow__edge.selectable:focus-visible .react-flow__edge-path{stroke:var(--xy-edge-stroke-selected, var(--xy-edge-stroke-selected-default))}.react-flow__edge-textwrapper{pointer-events:all}.react-flow__edge .react-flow__edge-text{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__arrowhead polyline{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__arrowhead polyline.arrowclosed{fill:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__connection{pointer-events:none}.react-flow__connection .animated{stroke-dasharray:5;animation:dashdraw .5s linear infinite}svg.react-flow__connectionline{z-index:1001;overflow:visible;position:absolute}.react-flow__nodes{pointer-events:none;transform-origin:0 0}.react-flow__node{position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;pointer-events:all;transform-origin:0 0;box-sizing:border-box;cursor:default}.react-flow__node.selectable{cursor:pointer}.react-flow__node.draggable{cursor:grab;pointer-events:all}.react-flow__node.draggable.dragging{cursor:grabbing}.react-flow__nodesselection{z-index:3;transform-origin:left top;pointer-events:none}.react-flow__nodesselection-rect{position:absolute;pointer-events:all;cursor:grab}.react-flow__handle{position:absolute;pointer-events:none;min-width:5px;min-height:5px;width:6px;height:6px;background-color:var(--xy-handle-background-color, var(--xy-handle-background-color-default));border:1px solid var(--xy-handle-border-color, var(--xy-handle-border-color-default));border-radius:100%}.react-flow__handle.connectingfrom{pointer-events:all}.react-flow__handle.connectionindicator{pointer-events:all;cursor:crosshair}.react-flow__handle-bottom{top:auto;left:50%;bottom:0;transform:translate(-50%,50%)}.react-flow__handle-top{top:0;left:50%;transform:translate(-50%,-50%)}.react-flow__handle-left{top:50%;left:0;transform:translate(-50%,-50%)}.react-flow__handle-right{top:50%;right:0;transform:translate(50%,-50%)}.react-flow__edgeupdater{cursor:move;pointer-events:all}.react-flow__pane.selection .react-flow__panel{pointer-events:none}.react-flow__panel{position:absolute;z-index:5;margin:15px}.react-flow__panel.top{top:0}.react-flow__panel.bottom{bottom:0}.react-flow__panel.top.center,.react-flow__panel.bottom.center{left:50%;transform:translate(-15px) translate(-50%)}.react-flow__panel.left{left:0}.react-flow__panel.right{right:0}.react-flow__panel.left.center,.react-flow__panel.right.center{top:50%;transform:translateY(-15px) translateY(-50%)}.react-flow__attribution{font-size:10px;background:var(--xy-attribution-background-color, var(--xy-attribution-background-color-default));padding:2px 3px;margin:0}.react-flow__attribution a{text-decoration:none;color:#999}@keyframes dashdraw{0%{stroke-dashoffset:10}}.react-flow__edgelabel-renderer{position:absolute;width:100%;height:100%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;left:0;top:0}.react-flow__viewport-portal{position:absolute;width:100%;height:100%;left:0;top:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__minimap{background:var( --xy-minimap-background-color-props, var(--xy-minimap-background-color, var(--xy-minimap-background-color-default)) )}.react-flow__minimap-svg{display:block}.react-flow__minimap-mask{fill:var( --xy-minimap-mask-background-color-props, var(--xy-minimap-mask-background-color, var(--xy-minimap-mask-background-color-default)) );stroke:var( --xy-minimap-mask-stroke-color-props, var(--xy-minimap-mask-stroke-color, var(--xy-minimap-mask-stroke-color-default)) );stroke-width:var( --xy-minimap-mask-stroke-width-props, var(--xy-minimap-mask-stroke-width, var(--xy-minimap-mask-stroke-width-default)) )}.react-flow__minimap-node{fill:var( --xy-minimap-node-background-color-props, var(--xy-minimap-node-background-color, var(--xy-minimap-node-background-color-default)) );stroke:var( --xy-minimap-node-stroke-color-props, var(--xy-minimap-node-stroke-color, var(--xy-minimap-node-stroke-color-default)) );stroke-width:var( --xy-minimap-node-stroke-width-props, var(--xy-minimap-node-stroke-width, var(--xy-minimap-node-stroke-width-default)) )}.react-flow__background-pattern.dots{fill:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-dots-color-default)) )}.react-flow__background-pattern.lines{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-lines-color-default)) )}.react-flow__background-pattern.cross{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-cross-color-default)) )}.react-flow__controls{display:flex;flex-direction:column;box-shadow:var(--xy-controls-box-shadow, var(--xy-controls-box-shadow-default))}.react-flow__controls.horizontal{flex-direction:row}.react-flow__controls-button{display:flex;justify-content:center;align-items:center;height:26px;width:26px;padding:4px;border:none;background:var(--xy-controls-button-background-color, var(--xy-controls-button-background-color-default));border-bottom:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) );color:var( --xy-controls-button-color-props, var(--xy-controls-button-color, var(--xy-controls-button-color-default)) );cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__controls-button svg{width:100%;max-width:12px;max-height:12px;fill:currentColor}.react-flow__edge.updating .react-flow__edge-path{stroke:#777}.react-flow__edge-text{font-size:10px}.react-flow__node.selectable:focus,.react-flow__node.selectable:focus-visible{outline:none}.react-flow__node-input,.react-flow__node-default,.react-flow__node-output,.react-flow__node-group{padding:10px;border-radius:var(--xy-node-border-radius, var(--xy-node-border-radius-default));width:150px;font-size:12px;color:var(--xy-node-color, var(--xy-node-color-default));text-align:center;border:var(--xy-node-border, var(--xy-node-border-default));background-color:var(--xy-node-background-color, var(--xy-node-background-color-default))}.react-flow__node-input.selectable:hover,.react-flow__node-default.selectable:hover,.react-flow__node-output.selectable:hover,.react-flow__node-group.selectable:hover{box-shadow:var(--xy-node-boxshadow-hover, var(--xy-node-boxshadow-hover-default))}.react-flow__node-input.selectable.selected,.react-flow__node-input.selectable:focus,.react-flow__node-input.selectable:focus-visible,.react-flow__node-default.selectable.selected,.react-flow__node-default.selectable:focus,.react-flow__node-default.selectable:focus-visible,.react-flow__node-output.selectable.selected,.react-flow__node-output.selectable:focus,.react-flow__node-output.selectable:focus-visible,.react-flow__node-group.selectable.selected,.react-flow__node-group.selectable:focus,.react-flow__node-group.selectable:focus-visible{box-shadow:var(--xy-node-boxshadow-selected, var(--xy-node-boxshadow-selected-default))}.react-flow__node-group{background-color:var(--xy-node-group-background-color, var(--xy-node-group-background-color-default))}.react-flow__nodesselection-rect,.react-flow__selection{background:var(--xy-selection-background-color, var(--xy-selection-background-color-default));border:var(--xy-selection-border, var(--xy-selection-border-default))}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible,.react-flow__selection:focus,.react-flow__selection:focus-visible{outline:none}.react-flow__controls-button:hover{background:var( --xy-controls-button-background-color-hover-props, var(--xy-controls-button-background-color-hover, var(--xy-controls-button-background-color-hover-default)) );color:var( --xy-controls-button-color-hover-props, var(--xy-controls-button-color-hover, var(--xy-controls-button-color-hover-default)) )}.react-flow__controls-button:disabled{pointer-events:none}.react-flow__controls-button:disabled svg{fill-opacity:.4}.react-flow__controls-button:last-child{border-bottom:none}.react-flow__controls.horizontal .react-flow__controls-button{border-bottom:none;border-right:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) )}.react-flow__controls.horizontal .react-flow__controls-button:last-child{border-right:none}.react-flow__resize-control{position:absolute}.react-flow__resize-control.left,.react-flow__resize-control.right{cursor:ew-resize}.react-flow__resize-control.top,.react-flow__resize-control.bottom{cursor:ns-resize}.react-flow__resize-control.top.left,.react-flow__resize-control.bottom.right{cursor:nwse-resize}.react-flow__resize-control.bottom.left,.react-flow__resize-control.top.right{cursor:nesw-resize}.react-flow__resize-control.handle{width:5px;height:5px;border:1px solid #fff;border-radius:1px;background-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));translate:-50% -50%}.react-flow__resize-control.handle.left{left:0;top:50%}.react-flow__resize-control.handle.right{left:100%;top:50%}.react-flow__resize-control.handle.top{left:50%;top:0}.react-flow__resize-control.handle.bottom{left:50%;top:100%}.react-flow__resize-control.handle.top.left,.react-flow__resize-control.handle.bottom.left{left:0}.react-flow__resize-control.handle.top.right,.react-flow__resize-control.handle.bottom.right{left:100%}.react-flow__resize-control.line{border-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));border-width:0;border-style:solid}.react-flow__resize-control.line.left,.react-flow__resize-control.line.right{width:1px;transform:translate(-50%);top:0;height:100%}.react-flow__resize-control.line.left{left:0;border-left-width:1px}.react-flow__resize-control.line.right{left:100%;border-right-width:1px}.react-flow__resize-control.line.top,.react-flow__resize-control.line.bottom{height:1px;transform:translateY(-50%);left:0;width:100%}.react-flow__resize-control.line.top{top:0;border-top-width:1px}.react-flow__resize-control.line.bottom{border-bottom-width:1px;top:100%}.react-flow__edge-textbg{fill:var(--xy-edge-label-background-color, var(--xy-edge-label-background-color-default))}.react-flow__edge-text{fill:var(--xy-edge-label-color, var(--xy-edge-label-color-default))}:root{--bg-primary: hsl(222 47% 5%);--bg-secondary: hsl(222 47% 7%);--bg-tertiary: hsl(222 47% 10%);--bg-hover: hsl(222 47% 12%);--text-primary: hsl(210 40% 96%);--text-secondary: hsl(215 20% 55%);--text-muted: hsl(215 15% 40%);--border-color: hsl(220 25% 15%);--border-light: hsl(220 20% 12%);--shadow-color: rgba(0, 0, 0, .3);--canvas-bg: hsl(222 47% 5%);--canvas-dots: hsl(220 25% 15%);--watermark-color: rgba(255, 255, 255, .02);--accent-cyan: hsl(185 75% 50%);--accent-green: hsl(142 76% 42%);--accent-amber: hsl(38 92% 50%);--accent-red: hsl(0 90% 55%);--glow-cyan: 0 0 20px hsl(185 75% 50% / .15);--glow-green: 0 0 12px hsl(142 76% 42% / .3)}[data-theme=light]{--bg-primary: hsl(220 20% 97%);--bg-secondary: hsl(220 18% 94%);--bg-tertiary: hsl(220 16% 90%);--bg-hover: hsl(220 14% 86%);--text-primary: hsl(220 30% 12%);--text-secondary: hsl(220 15% 40%);--text-muted: hsl(220 10% 58%);--border-color: hsl(220 15% 82%);--border-light: hsl(220 12% 88%);--shadow-color: rgba(0, 0, 0, .08);--canvas-bg: hsl(220 20% 97%);--canvas-dots: hsl(220 15% 82%);--watermark-color: rgba(0, 0, 0, .02);--accent-cyan: hsl(185 80% 35%);--accent-green: hsl(142 72% 32%);--accent-amber: hsl(38 90% 42%);--accent-red: hsl(0 85% 45%);--glow-cyan: 0 0 12px hsl(185 80% 35% / .12);--glow-green: 0 0 8px hsl(142 72% 32% / .2)}*{margin:0;padding:0;box-sizing:border-box}html,body,#root{width:100%;height:100%;overflow:hidden;font-family:JetBrains Mono,monospace}.app{width:100%;height:100%;display:flex;flex-direction:column;background:var(--bg-primary)}::-webkit-scrollbar{width:6px}::-webkit-scrollbar-track{background:var(--bg-primary)}::-webkit-scrollbar-thumb{background:var(--border-color);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:#303a50}.branding-header{position:relative;z-index:10;background:#080c16d9;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);padding:10px 24px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid hsl(185 75% 50% / .1);box-shadow:0 1px 12px #20cfdf0d}.archbyte-brand{display:flex;align-items:center;gap:10px}.archbyte-logo{font-size:20px}.archbyte-logo-img{height:22px;width:auto}.archbyte-name{font-size:20px;font-weight:700;color:var(--text-primary);letter-spacing:-.3px}.archbyte-tagline{font-size:13px;color:var(--text-muted);padding-left:14px;margin-left:4px;border-left:1px solid var(--border-color)}.branding-account{display:flex;align-items:center;gap:10px}.account-tier-badge{font-size:11px;font-weight:600;padding:3px 10px;border-radius:4px;letter-spacing:.3px;text-transform:uppercase}.account-tier-badge.premium{background:#672eb8;color:#fff}.account-tier-badge.free{background:#182543;color:var(--text-muted)}.account-email{font-size:12px;color:var(--text-muted);position:relative}.account-pro-tag{margin-left:6px;font-size:9px;font-weight:700;letter-spacing:.5px;padding:1px 4px;border-radius:3px;background:#a65eed26;color:#a65eed;border:1px solid hsl(270 80% 65% / .4);vertical-align:middle}.project-info-wrapper{position:relative;display:inline-flex;align-items:center}.project-info-trigger{background:none;border:1px solid transparent;color:var(--text-secondary);font-family:JetBrains Mono,monospace;font-size:13px;font-weight:500;cursor:pointer;transition:all .2s;margin-left:10px;padding:3px 10px 3px 14px;border-left:1px solid var(--border-color);border-radius:0}.project-info-trigger:hover{color:var(--text-primary);background:var(--bg-tertiary)}.project-info-popup{position:absolute;top:calc(100% + 8px);left:0;background:#090e1af2;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);border:1px solid var(--border-color);border-radius:12px;padding:16px;width:340px;z-index:100;box-shadow:0 8px 32px var(--shadow-color);animation:popupFadeIn .15s ease-out}@keyframes popupFadeIn{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.project-info-header{display:flex;align-items:center;gap:8px;margin-bottom:10px}.project-info-name{font-size:15px;font-weight:700;color:var(--text-primary);letter-spacing:-.3px}.project-info-lang{font-size:10px;font-weight:600;color:#4cd9e6;background:#20cfdf1f;padding:2px 8px;border-radius:10px;text-transform:uppercase;letter-spacing:.5px}.project-info-desc{font-size:12px;color:var(--text-secondary);line-height:1.5;margin:0 0 14px;padding-bottom:14px;border-bottom:1px solid var(--border-color)}.project-info-stats{display:flex;gap:6px;flex-wrap:wrap}.project-info-stat{display:flex;flex-direction:column;align-items:center;background:var(--bg-tertiary);padding:8px 12px;border-radius:8px;min-width:56px;flex:1}.project-info-stat-value{font-size:16px;font-weight:700;color:var(--text-primary);font-family:JetBrains Mono,monospace}.project-info-stat-label{font-size:9px;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px;margin-top:2px}.project-info-badge{margin-top:10px;font-size:10px;font-weight:600;color:#f6c155;background:#f2a60d1a;padding:3px 10px;border-radius:10px;display:inline-block}.project-info-vscode{display:flex;align-items:center;gap:8px;margin-top:12px;padding:8px 12px;border-radius:8px;font-size:12px;font-weight:600;color:#75b3f0;background:#1980e61a;border:1px solid hsl(210 80% 50% / .2);text-decoration:none;cursor:pointer;transition:all .2s}.project-info-vscode:hover{background:#1980e633;border-color:#1980e666;color:#a3ccf5}.project-info-vscode svg{flex-shrink:0}[data-theme=light] .project-info-popup{background:#f9fafbf5}[data-theme=light] .project-info-vscode{color:#1466b8;background:#1980e614;border-color:#1980e633}[data-theme=light] .project-info-vscode:hover{background:#1980e626;border-color:#1980e659;color:#0f4d8a}.brand-attribution{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--text-secondary);text-decoration:none;transition:color .2s}.brand-attribution:hover{color:var(--text-primary)}.brand-avatar{width:28px;height:28px;border-radius:50%;object-fit:cover;border:2px solid hsl(185 75% 50% / .3);transition:border-color .2s,box-shadow .2s}.brand-attribution:hover .brand-avatar{border-color:var(--accent-cyan);box-shadow:0 0 12px #20cfdf4d}.brand-attribution-link{color:var(--accent-cyan);font-weight:600}.brand-attribution:hover .brand-attribution-link{color:#63dee9}.toolbar{display:flex;align-items:center;justify-content:space-between;padding:6px 16px;background:var(--bg-secondary);border-bottom:1px solid var(--border-color)}.toolbar-left,.toolbar-right{display:flex;align-items:center;gap:16px}.toolbar-right{gap:8px}.toolbar-right .dropdown-menu{left:auto;right:0}.toolbar-section{display:flex;flex-direction:column;gap:3px;padding-right:12px;border-right:1px solid hsl(222 30% 25%)}.toolbar-section:last-child{padding-right:0;border-right:none}.toolbar-section-label{font-size:9px;font-weight:600;text-transform:uppercase;letter-spacing:.08em;color:var(--text-muted);text-align:center;-webkit-user-select:none;user-select:none}.toolbar-section-items,.toolbar-group{display:flex;align-items:center;gap:6px}.toolbar-divider{width:1px;height:24px;background:var(--border-color);margin:0 8px}.toolbar-btn-icon{display:flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:6px;font-size:15px;font-weight:600;font-family:system-ui,sans-serif;line-height:1;text-align:center;color:var(--text-secondary);cursor:pointer;transition:all .2s}.toolbar-btn-icon:hover{background:var(--bg-hover);color:var(--text-primary);box-shadow:var(--glow-cyan)}.toolbar-btn-icon:disabled{opacity:.5;cursor:not-allowed}.toolbar-analyzing{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--accent-cyan, hsl(185, 75%, 50%));padding:4px 10px;background:#20cfdf1a;border:1px solid hsla(185,75%,50%,.3);border-radius:6px;font-family:JetBrains Mono,monospace}.analyzing-pulse{width:6px;height:6px;border-radius:50%;background:var(--accent-cyan, hsl(185, 75%, 50%));animation:pulse-analyzing 1.5s ease-in-out infinite}@keyframes pulse-analyzing{0%,to{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.8)}}.toolbar-error-btn{background:#ef444426!important;border-color:#ef444466!important;color:#ef4444!important;font-size:11px;animation:pulse-error 2s ease-in-out infinite}.toolbar-error-btn:hover{background:#ef444440!important}@keyframes pulse-error{0%,to{opacity:1}50%{opacity:.7}}.toolbar-btn{display:flex;align-items:center;gap:4px;height:32px;padding:0 10px;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:6px;font-size:12px;font-weight:500;color:var(--text-secondary);cursor:pointer;transition:all .2s}.toolbar-btn:hover{background:var(--bg-hover);color:var(--text-primary);box-shadow:var(--glow-cyan)}.toolbar-btn:disabled{opacity:.5;cursor:not-allowed}.toolbar-btn.active{background:#20cfdf26;border-color:var(--accent-cyan);color:var(--accent-cyan)}.premium-btn{position:relative;border:1px solid hsl(270 80% 65% / .5)!important}.premium-btn.premium-locked{opacity:.4;cursor:not-allowed}.premium-btn.premium-locked:hover{opacity:.55}.premium-btn:after{content:"PRO";position:absolute;top:3px;right:4px;font-size:7px;font-weight:700;letter-spacing:.5px;line-height:1;color:#a65eed}.dropdown-item{display:flex;align-items:center;gap:8px;width:100%;padding:8px 14px;font-size:12px;font-weight:500;color:var(--text-secondary);background:transparent;border:none;cursor:pointer;text-align:left;transition:all .15s}.dropdown-item:hover{background:var(--bg-hover);color:var(--text-primary)}.dropdown-item.active{color:var(--accent-cyan);background:var(--bg-hover)}.shortcut-item{display:flex;align-items:center;justify-content:space-between;padding:6px 14px;font-size:12px;color:var(--text-secondary)}.shortcut-item kbd{background:var(--bg-tertiary);padding:2px 6px;border-radius:4px;font-family:JetBrains Mono,monospace;font-size:11px;font-weight:600;color:var(--text-primary);margin-right:12px;border:1px solid var(--border-color)}.dropdown-wrapper{position:relative}.dropdown-menu{position:absolute;top:100%;left:0;margin-top:4px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:8px;padding:4px;z-index:50;min-width:160px;box-shadow:0 4px 16px var(--shadow-color);animation:fade-in-up .15s ease-out}.dropdown-label{padding:6px 10px 4px;font-size:9px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--text-muted)}.dropdown-separator{height:1px;background:var(--border-color);margin:4px 0}.panel-btn{display:inline-flex;align-items:center;justify-content:center;gap:4px;padding:6px 10px;font-size:11px;font-family:JetBrains Mono,monospace;font-weight:500;border-radius:6px;cursor:pointer;border:1px solid var(--border-color);background:var(--bg-tertiary);color:var(--text-secondary);transition:all .2s;white-space:nowrap}.panel-btn:hover{background:var(--bg-hover);color:var(--text-primary)}.panel-btn.cyan{border-color:#20cfdf4d;color:var(--accent-cyan);background:#20cfdf1a}.panel-btn.cyan:hover{background:#20cfdf33}.panel-btn.green{border-color:#1abc554d;color:var(--accent-green);background:#1abc551a}.panel-btn.green:hover{background:#1abc5533}.panel-btn.amber{border-color:#f59f0a4d;color:var(--accent-amber);background:#f59f0a1a}.panel-btn.amber:hover{background:#f59f0a33}.panel-btn.red{border-color:#f425254d;color:var(--accent-red);background:#f425251a}.panel-btn.red:hover{background:#f4252533}.panel-btn.small{flex:0;padding:3px 8px;font-size:10px}.panel-close-btn{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;background:transparent;color:var(--text-muted);cursor:pointer;border-radius:4px;font-size:14px;transition:all .2s}.panel-close-btn:hover{background:var(--bg-hover);color:var(--text-primary)}.save-btn{padding:6px 14px;background:var(--accent-cyan);color:var(--bg-primary);border:none;border-radius:6px;font-family:JetBrains Mono,monospace;font-size:12px;font-weight:600;cursor:pointer;transition:background .2s}.save-btn:hover{background:#4cd9e6}.save-btn:disabled{opacity:.5;cursor:not-allowed}.discard-btn{padding:6px 14px;background:transparent;color:var(--text-secondary);border:1px solid var(--border-color);border-radius:6px;font-family:JetBrains Mono,monospace;font-size:12px;cursor:pointer;transition:all .2s}.discard-btn:hover{background:var(--bg-hover);color:var(--text-primary)}.discard-btn:disabled{opacity:.5;cursor:not-allowed}.tech-badge{display:inline-flex;padding:2px 8px;font-size:10px;font-family:JetBrains Mono,monospace;border-radius:4px;background:#20cfdf1a;color:var(--accent-cyan);border:1px solid hsl(185 75% 50% / .3)}.active-badge{font-size:9px;font-weight:700;padding:2px 6px;border-radius:4px;background:#20cfdf26;color:var(--accent-cyan);border:1px solid hsl(185 75% 50% / .3)}.validation-badge{font-size:10px;font-weight:600;text-transform:uppercase;padding:2px 8px;border-radius:4px}.validation-badge.pass{background:#1abc5526;color:var(--accent-green);border:1px solid hsl(142 76% 42% / .3)}.validation-badge.fail{background:#f4252526;color:var(--accent-red);border:1px solid hsl(0 90% 55% / .3)}.ops-tabs{display:flex;gap:2px;background:var(--bg-tertiary);border-radius:6px;padding:2px}.ops-tab{padding:4px 12px;font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;border:none;background:transparent;color:var(--text-muted);cursor:pointer;border-radius:4px;font-family:JetBrains Mono,monospace;transition:all .2s}.ops-tab.active{background:var(--bg-hover);color:var(--text-primary)}.ops-tab:hover{color:var(--text-primary)}.dropdown-item.disabled{opacity:.4;cursor:default;pointer-events:none}.watermark{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:72px;font-weight:700;color:var(--watermark-color);pointer-events:none;z-index:0;-webkit-user-select:none;user-select:none;letter-spacing:-2px}.environment-tabs{display:flex;background:var(--bg-secondary);border-bottom:1px solid var(--border-color);padding:0 16px;gap:4px;height:48px;align-items:stretch}.env-tab{display:flex;align-items:center;gap:8px;padding:0 20px;background:transparent;border:none;border-bottom:3px solid transparent;cursor:pointer;font-size:13px;font-weight:500;color:var(--text-secondary);transition:all .2s;font-family:JetBrains Mono,monospace}.env-tab:hover{background:var(--bg-hover)}.env-tab.selected{border-bottom-color:var(--env-color);color:var(--text-primary);box-shadow:0 2px 12px color-mix(in srgb,var(--env-color) 20%,transparent)}.env-indicator{width:8px;height:8px;border-radius:50%;background:var(--env-color);opacity:.4;transition:opacity .2s}.env-tab.selected .env-indicator{opacity:1;animation:breathe 3s infinite}.env-label{font-weight:600}.env-meta{font-size:11px;color:var(--text-muted);font-weight:400;margin-left:8px;padding-left:8px;border-left:1px solid var(--border-color)}.component-info-panel{position:absolute;top:16px;left:16px;background:#090e1ae6;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);padding:16px;border-radius:12px;border:1px solid var(--border-color);font-size:12px;color:var(--text-primary);z-index:10;width:280px;box-shadow:0 2px 12px var(--shadow-color)}.node-details-panel{position:absolute;top:16px;left:16px;background:#090e1ae6;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);padding:16px;border-radius:12px;border:1px solid var(--border-color);font-size:12px;color:var(--text-primary);z-index:15;width:300px;max-height:calc(100vh - 200px);overflow-y:auto;box-shadow:0 2px 12px var(--shadow-color)}.node-details-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:12px;padding-bottom:12px;border-bottom:1px solid var(--border-color)}.node-details-title{font-size:14px;font-weight:600;color:var(--text-primary)}.node-details-type{font-size:10px;color:var(--text-muted);text-transform:uppercase;margin-top:2px}.node-details-type-row{display:flex;align-items:center;gap:8px;font-size:10px;color:var(--text-muted);text-transform:uppercase;margin-top:2px}.node-details-type-row .panel-btn{text-transform:none;font-size:10px;padding:2px 8px}.node-details-section{margin-bottom:12px}.node-details-section-title{font-size:10px;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px;margin-bottom:6px}.node-details-path{font-family:JetBrains Mono,monospace;font-size:11px;color:var(--text-secondary);background:var(--bg-tertiary);padding:6px 8px;border-radius:4px;word-break:break-all;border:1px solid var(--border-light)}.node-details-tech-stack{display:flex;flex-wrap:wrap;gap:4px}.node-details-connections{display:flex;flex-direction:column;gap:4px}.connection-item{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--text-secondary)}.connection-item-detailed{padding:8px 10px;background:var(--bg-tertiary);border-radius:6px;margin-bottom:6px;border:1px solid var(--border-light)}.connection-header{display:flex;align-items:center;gap:6px;font-size:12px;font-weight:500;color:var(--text-primary)}.connection-arrow{color:var(--text-muted)}.connection-target{color:var(--text-primary)}.connection-label{font-size:11px;color:var(--text-secondary);margin-top:4px;padding-left:18px;line-height:1.4}.node-details-actions{display:flex;gap:8px;margin-top:12px;padding-top:12px;border-top:1px solid var(--border-color)}.env-badge{display:inline-block;padding:4px 12px;border-radius:20px;color:var(--text-primary);font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;margin-bottom:12px}.env-details{padding:10px 0;border-top:1px solid var(--border-color);border-bottom:1px solid var(--border-color);margin-bottom:12px}.env-detail-row{display:flex;justify-content:space-between;align-items:center;padding:4px 0}.env-detail-label{font-size:10px;color:var(--text-muted);text-transform:uppercase}.env-detail-value{font-size:11px;font-weight:500;color:var(--text-secondary)}.component-list{display:flex;flex-direction:column;gap:6px}.component-list-title{font-weight:600;color:var(--text-muted);text-transform:uppercase;font-size:10px;letter-spacing:1px;margin-bottom:4px}.component-item{display:flex;flex-direction:column;align-items:flex-start;gap:2px;padding:8px 10px;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:8px;cursor:pointer;transition:all .2s;text-align:left;width:100%}.component-item:hover{background:var(--bg-hover);border-color:var(--accent-cyan);transform:translate(2px);box-shadow:var(--glow-cyan)}.component-name{font-weight:600;font-size:12px;color:var(--text-primary)}.component-path{font-size:10px;color:var(--text-muted);font-family:JetBrains Mono,monospace}.git-info{display:flex;align-items:center;gap:8px;margin-top:4px}.git-branch{display:inline-flex;align-items:center;padding:2px 6px;background:#20cfdf1a;border:1px solid hsl(185 75% 50% / .3);border-radius:4px;font-size:10px;font-family:JetBrains Mono,monospace;color:var(--accent-cyan)}.git-hash{display:inline-flex;align-items:center;padding:2px 6px;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;font-size:10px;font-family:JetBrains Mono,monospace;color:var(--text-secondary)}.no-git-info{color:var(--text-muted);font-style:italic;text-align:center;padding:12px}.canvas-container{flex:1;position:relative}.react-flow{background:var(--canvas-bg)!important}.react-flow__background{background:var(--canvas-bg)}.react-flow__controls{background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:8px;box-shadow:0 2px 8px var(--shadow-color)}.react-flow__controls-button{background:var(--bg-secondary);border-color:var(--border-color);fill:#fff;color:#fff}.react-flow__controls-button:hover{background:var(--bg-hover);fill:var(--text-primary)}.arch-node{padding:14px 16px;border-radius:12px;font-size:12px;font-weight:500;border:1.5px solid;min-width:130px;text-align:left;box-shadow:0 4px 16px #00000040,inset 0 1px #ffffff0d;transition:transform .2s,box-shadow .2s;display:flex;flex-direction:column;gap:6px;position:relative;overflow:hidden}.arch-node:before{content:"";position:absolute;top:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,rgba(255,255,255,.08),transparent)}.arch-node:hover{transform:translateY(-2px);box-shadow:0 8px 24px #00000059,inset 0 1px #ffffff0d}.arch-node .node-type-icon{position:absolute;top:10px;right:12px;font-size:16px;opacity:.35;line-height:1}.arch-node .node-content{flex:1;min-width:0}.arch-node .label{font-weight:700;font-size:13px;margin-bottom:2px;letter-spacing:-.2px;padding-right:20px}.arch-node .sublabel{font-size:10px;opacity:.7}.arch-node .node-desc{font-size:9px;opacity:.5;line-height:1.3;margin-top:2px;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}.arch-node .node-tech-row{display:flex;flex-wrap:wrap;gap:3px;margin-top:2px}.arch-node .node-tech-pill{font-size:8px;font-weight:600;padding:1px 6px;border-radius:3px;background:#ffffff0f;border:1px solid rgba(255,255,255,.08);opacity:.7;letter-spacing:.2px;text-transform:uppercase}.arch-node.presentation{background:linear-gradient(145deg,#122436,#152e47);border-color:#2680d999;color:#c6d9ec}.arch-node.presentation:hover{border-color:#3c8cdd;box-shadow:0 0 24px #2680d933,0 8px 24px #00000059}.arch-node.presentation .node-tech-pill{border-color:#2680d940;color:#99bfe6}.arch-node.application{background:linear-gradient(145deg,#322415,#432e19);border-color:#e88c3099;color:#ecd9c6}.arch-node.application:hover{border-color:#eb9947;box-shadow:0 0 24px #e88c3033,0 8px 24px #00000059}.arch-node.application .node-tech-pill{border-color:#e88c3040;color:#e6bf99}.arch-node.data{background:linear-gradient(145deg,#14291b,#183923);border-color:#2eb85c99;color:#c9e8d4}.arch-node.data:hover{border-color:#3c6;box-shadow:0 0 24px #2eb85c33,0 8px 24px #00000059}.arch-node.data .node-tech-pill{border-color:#2eb85c40;color:#9fdfb5}.arch-node.external{background:linear-gradient(145deg,#27192e,#331e3e);border-color:#9f53c699;color:#ddcde4}.arch-node.external:hover{border-color:#a6c;box-shadow:0 0 24px #9f53c633,0 8px 24px #00000059}.arch-node.external .node-tech-pill{border-color:#9f53c640;color:#c8a6d9}.arch-node.deployment{background:linear-gradient(145deg,#2e1919,#3e1e1e);border-color:#c339;color:#e4cdcd}.arch-node.deployment:hover{border-color:#d14747;box-shadow:0 0 24px #c333,0 8px 24px #00000059}.arch-node.deployment .node-tech-pill{border-color:#cc333340;color:#df9f9f}.react-flow__resize-control{border-radius:2px!important}.react-flow__resize-control.handle{width:8px!important;height:8px!important}.react-flow__node.selected .arch-node{box-shadow:0 0 0 2px #20cfdf66,0 4px 16px #0006}.arch-node.active{animation:pulse-border 2s infinite}@keyframes pulse-border{0%,to{box-shadow:0 0 #1abc5566}50%{box-shadow:0 0 0 8px #1abc5500}}.arch-node.highlighted{animation:highlight-glow 1.5s ease-in-out;box-shadow:0 0 20px #20cfdf99,0 0 40px #20cfdf4d;transform:scale(1.05);z-index:100}@keyframes highlight-glow{0%{box-shadow:0 0 #20cfdf00;transform:scale(1)}20%{box-shadow:0 0 30px #20cfdfcc,0 0 60px #20cfdf66;transform:scale(1.08)}to{box-shadow:0 0 20px #20cfdf99,0 0 40px #20cfdf4d;transform:scale(1.05)}}.node-actions-panel{position:absolute;top:60px;right:16px;background:#090e1ae6;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid var(--border-color);border-radius:10px;padding:12px;box-shadow:0 4px 12px var(--shadow-color);z-index:10;min-width:180px}.node-actions-title{font-size:11px;font-weight:600;color:var(--text-secondary);margin-bottom:10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:200px}.node-actions-buttons{display:flex;gap:8px;margin-bottom:8px}.node-actions-hint{font-size:10px;color:var(--text-muted);text-align:center;padding-top:8px;border-top:1px solid var(--border-color)}.lock-icon{margin-right:6px}.arch-node.locked{opacity:.7;cursor:not-allowed}.arch-node.locked:after{content:"🔒";position:absolute;top:4px;right:4px;font-size:10px}.hidden-nodes-panel{position:absolute;bottom:60px;right:16px;background:#090e1ae6;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid var(--border-color);border-radius:10px;padding:12px;box-shadow:0 4px 12px var(--shadow-color);z-index:10;min-width:200px;max-width:280px;max-height:300px;overflow-y:auto}.hidden-nodes-title{display:flex;justify-content:space-between;align-items:center;font-size:12px;font-weight:600;color:var(--text-secondary);margin-bottom:10px;padding-bottom:8px;border-bottom:1px solid var(--border-color)}.hidden-nodes-list{display:flex;flex-direction:column;gap:6px}.hidden-node-item{display:flex;justify-content:space-between;align-items:center;padding:6px 8px;background:var(--bg-tertiary);border-radius:6px}.hidden-node-name{font-size:11px;color:var(--text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:140px}.status-bar{background:var(--bg-secondary);border-top:1px solid var(--border-color);padding:10px 20px;display:grid;grid-template-columns:1fr auto 1fr;align-items:center;font-size:12px;color:var(--text-secondary)}.status-left{display:flex;align-items:center;gap:16px;justify-self:start}.status-center{display:flex;align-items:center;justify-self:center}.status-indicator{display:flex;align-items:center;gap:8px}.status-dot{width:8px;height:8px;border-radius:50%;background:var(--accent-green);animation:breathe 2s infinite}.status-dot.disconnected{background:var(--accent-red);animation:none}@keyframes breathe{0%,to{opacity:1;transform:scale(1)}50%{opacity:.6;transform:scale(.95)}}.status-right{display:flex;align-items:center;gap:20px;justify-self:end}.layer-dropdown-item{gap:10px!important;transition:opacity .2s}.layer-dropdown-item.hidden-layer{opacity:.4}.layer-toggle-indicator{margin-left:auto;font-size:10px;color:var(--text-muted)}.legend-color{width:16px;height:16px;border-radius:4px;border:2px solid}.legend-color.presentation{background:#132639;border-color:#2680d9}.legend-color.application{background:#362617;border-color:#e88c30}.legend-color.data{background:#162d1d;border-color:#2eb85c}.legend-color.external{background:#2a1b32;border-color:#9f53c6}.legend-color.deployment{background:#321b1b;border-color:#c33}.loading{display:flex;align-items:center;justify-content:center;height:100%;color:var(--text-secondary);font-size:14px}.loading-spinner{width:24px;height:24px;border:3px solid var(--border-color);border-top-color:var(--accent-cyan);border-radius:50%;animation:spin 1s linear infinite;margin-right:12px}@keyframes spin{to{transform:rotate(360deg)}}.agent-panel{position:absolute;bottom:60px;left:16px;background:#090e1ae6;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);padding:12px 16px;border-radius:10px;border:1px solid var(--border-color);font-size:11px;color:var(--text-primary);z-index:10;max-width:300px;box-shadow:0 2px 12px var(--shadow-color)}.agent-panel-title{font-weight:600;margin-bottom:8px;color:var(--text-muted);text-transform:uppercase;font-size:10px}.agent-item{display:flex;align-items:center;gap:8px;padding:6px 0;border-bottom:1px solid var(--border-color)}.agent-item:last-child{border-bottom:none}.agent-dot{width:6px;height:6px;border-radius:50%}.agent-dot.active{background:var(--accent-green);animation:breathe 1.5s infinite}.agent-name{font-weight:500;color:var(--text-primary)}.agent-target{color:var(--text-muted);margin-left:auto}.flow-dropdown{min-width:240px}.flow-dot-inline{display:inline-block;width:8px;height:8px;border-radius:50%;flex-shrink:0}.toolbar-btn.has-active-flow{background:#20cfdf1a;border-color:#20cfdf4d;color:var(--accent-cyan);gap:6px}.toolbar-btn.has-new-flow{position:relative}.flow-new-indicator{display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--accent-green);margin-left:5px;vertical-align:middle;animation:flow-new-blink 1.2s ease-in-out infinite}@keyframes flow-new-blink{0%,to{opacity:1}50%{opacity:.2}}.toolbar-btn.has-hidden{color:var(--accent-amber)}.flow-category-header{display:flex;align-items:center;gap:6px;padding:6px 10px 4px;font-size:9px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--text-muted)}.flow-dropdown-item{gap:10px!important}.flow-dropdown-item.active{background:#20cfdf1a!important;color:var(--accent-cyan)!important}.flow-dropdown-name{flex:1}.flow-clear{color:var(--accent-red)!important}.flow-progress-bar{position:absolute;bottom:16px;left:50%;transform:translate(-50%);display:flex;align-items:center;gap:12px;background:#090e1af2;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid var(--border-color);border-radius:12px;padding:10px 16px;z-index:15;max-width:90vw;box-shadow:0 4px 20px var(--shadow-color),var(--glow-cyan);animation:slide-up .3s ease-out}.flow-progress-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0;animation:breathe 2s infinite}.flow-progress-name{font-size:12px;font-weight:600;color:var(--text-primary);white-space:nowrap;flex-shrink:0}.flow-progress-steps{display:flex;gap:4px;overflow-x:auto;max-width:500px}.flow-progress-step{padding:4px 8px;background:var(--bg-tertiary);border-radius:4px;font-size:10px;border-left:2px solid transparent;transition:all .3s;opacity:.4;color:var(--text-secondary);white-space:nowrap;flex-shrink:0}.flow-progress-step.active{opacity:1;background:var(--bg-hover);color:var(--text-primary)}.flow-progress-step.current{font-weight:600;box-shadow:0 1px 4px var(--shadow-color)}.flow-progress-controls{display:flex;gap:4px;flex-shrink:0;margin-left:4px}.flow-progress-btn{width:28px;height:28px;display:flex;align-items:center;justify-content:center;border:1px solid var(--border-color);background:var(--bg-tertiary);border-radius:6px;cursor:pointer;font-size:12px;color:var(--text-secondary);transition:all .2s}.flow-progress-btn:hover{background:var(--bg-hover);color:var(--text-primary)}.flow-progress-btn.stop{border-color:#f425254d;color:var(--accent-red)}.flow-progress-btn.stop:hover{background:#f4252526}.flow-hud-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:100;display:flex;align-items:center;justify-content:center;background:#070a13d9;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);animation:flowHudFadeIn .2s ease-out}@keyframes flowHudFadeIn{0%{opacity:0}to{opacity:1}}.flow-hud-panel{width:90vw;height:85vh;max-width:1400px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:16px;display:flex;flex-direction:column;overflow:hidden;box-shadow:0 0 60px #20cfdf14,0 8px 32px #0006}.flow-hud-header{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid var(--border-color);flex-shrink:0}.flow-hud-title{display:flex;align-items:center;gap:10px;font-size:15px;font-weight:700;color:var(--text-primary);letter-spacing:.3px}.flow-hud-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}.flow-hud-controls{display:flex;align-items:center;gap:6px}.flow-hud-btn{background:var(--bg-tertiary);border:1px solid var(--border-color);color:var(--text-primary);width:32px;height:32px;border-radius:8px;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:14px;transition:all .15s}.flow-hud-btn:hover{background:var(--bg-hover);border-color:var(--accent-cyan)}.flow-hud-close{background:var(--bg-tertiary);border:1px solid var(--border-color);color:var(--text-muted);width:32px;height:32px;border-radius:8px;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:16px;font-weight:600;transition:all .15s}.flow-hud-close:hover{background:#f4252526;border-color:var(--accent-red);color:var(--accent-red)}.flow-hud-description{padding:10px 20px;font-size:12px;color:var(--text-muted);border-bottom:1px solid var(--border-color);flex-shrink:0}.flow-hud-canvas{flex:1;min-height:0;position:relative}.flow-hud-canvas .react-flow__controls{bottom:10px;left:10px}.flow-hud-steps{display:flex;align-items:center;gap:8px;padding:14px 20px;border-top:1px solid var(--border-color);overflow-x:auto;flex-shrink:0}.flow-hud-step{display:flex;align-items:center;gap:6px;padding:6px 12px;border-radius:8px;font-size:11px;color:var(--text-muted);background:var(--bg-tertiary);border:1px solid var(--border-color);white-space:nowrap;transition:all .3s}.flow-hud-step.active{color:var(--text-primary);border-color:currentColor}.flow-hud-step.current{box-shadow:0 0 12px currentColor}.flow-hud-step-num{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;font-size:10px;font-weight:700;color:var(--text-primary);background:var(--border-color);flex-shrink:0;transition:background .3s}.git-repo-badge{display:inline-flex;align-items:center;padding:2px 8px;background:#2a1b32;border:1px solid hsl(280 50% 55% / .3);border-radius:4px;font-size:11px;font-family:JetBrains Mono,monospace;font-weight:500;color:#bf8cd9;text-decoration:none;transition:all .2s}.git-repo-badge:hover{background:#382442;border-color:#9f53c680}.save-panel{position:fixed;bottom:55px;left:50%;transform:translate(-50%);background:#20cfdf26;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);color:var(--text-primary);padding:12px 20px;border-radius:10px;border:1px solid var(--accent-cyan);display:flex;gap:16px;align-items:center;box-shadow:var(--glow-cyan);z-index:100;animation:slide-up .3s ease-out}@keyframes slide-up{0%{opacity:0;transform:translate(-50%) translateY(20px)}to{opacity:1;transform:translate(-50%) translateY(0)}}.save-panel-text{font-size:13px;font-weight:500}.react-flow__node.selected{outline:2px solid var(--accent-cyan);outline-offset:2px}.react-flow__handle{width:10px;height:10px;background:var(--accent-cyan);border:2px solid var(--bg-primary);opacity:0;transition:opacity .2s}.react-flow__node:hover .react-flow__handle,.react-flow__node.selected .react-flow__handle{opacity:1}.react-flow__handle:hover{transform:scale(1.2)}.clipboard-indicator{position:fixed;bottom:120px;left:50%;transform:translate(-50%);background:var(--bg-hover);color:var(--text-primary);padding:8px 16px;border-radius:6px;font-size:12px;border:1px solid var(--border-color);z-index:100;animation:fade-in-out 2s ease-in-out;pointer-events:none}@keyframes fade-in-out{0%,to{opacity:0;transform:translate(-50%) translateY(10px)}20%,80%{opacity:1;transform:translate(-50%) translateY(0)}}@keyframes fade-in-up{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes scan-line{0%{top:-100%}to{top:200%}}.stats-overlay{position:absolute;top:60px;right:16px;background:var(--bg-secondary);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);padding:12px;border-radius:12px;border:1px solid var(--border-color);z-index:10;width:200px;box-shadow:var(--glow-cyan)}[data-drag-handle]{cursor:grab}[data-drag-handle]:active{cursor:grabbing}.stats-overlay-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px}.stats-overlay-title{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:1px;color:var(--accent-cyan)}.stats-scan-info{display:flex;flex-wrap:wrap;gap:6px 12px;padding:8px 0;margin-bottom:8px;border-bottom:1px solid var(--border-color);font-size:11px;color:var(--text-muted)}.scan-info-item{white-space:nowrap}.scan-info-item:not(:last-child):after{content:"|";margin-left:12px;opacity:.3}.stats-grid{display:grid;grid-template-columns:1fr 1fr;gap:6px}.stat-card{padding:6px 8px;background:var(--bg-tertiary);border-radius:6px;border:1px solid var(--border-color);overflow:hidden}.stat-value{font-size:16px;font-weight:700;color:var(--text-primary)}.stat-label{font-size:9px;text-transform:uppercase;letter-spacing:.5px;color:var(--text-muted);margin-top:2px}.stat-card.highlight{border-color:var(--accent-cyan);box-shadow:var(--glow-cyan)}.validation-panel{position:absolute;top:60px;right:16px;background:var(--bg-secondary);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);padding:16px;border-radius:12px;border:1px solid var(--border-color);z-index:10;width:280px;max-height:calc(100vh - 200px);overflow-y:auto;box-shadow:0 2px 12px var(--shadow-color)}.validation-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px}.validation-title{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:1px;color:var(--text-muted)}.violation-item{padding:10px;background:var(--bg-tertiary);border-radius:8px;margin-bottom:6px;border-left:3px solid;cursor:pointer;transition:all .2s}.violation-item:hover{background:var(--bg-hover)}.violation-item.error{border-left-color:var(--accent-red)}.violation-item.warn{border-left-color:var(--accent-amber)}.violation-rule{font-size:10px;font-weight:600;text-transform:uppercase;color:var(--text-muted);margin-bottom:4px}.violation-message{font-size:11px;color:var(--text-secondary)}.ops-panel{position:absolute;top:60px;right:16px;background:var(--bg-secondary);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border-radius:12px;border:1px solid var(--border-color);z-index:10;width:280px;max-height:calc(100vh - 200px);overflow-y:auto;box-shadow:0 2px 12px var(--shadow-color)}.audit-panel{position:absolute;top:60px;right:16px;background:var(--bg-secondary);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);padding:0;border-radius:12px;border:1px solid var(--border-color);z-index:10;width:340px;max-height:calc(100vh - 200px);overflow-y:auto;box-shadow:0 2px 12px var(--shadow-color);display:flex;flex-direction:column}.audit-header{display:flex;justify-content:space-between;align-items:center;padding:12px 16px 0}.audit-title{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:1px;color:var(--text-muted)}.audit-tabs{display:flex;border-bottom:1px solid var(--border-color);margin:12px 0 0;padding:0 8px;gap:4px}.audit-tab{flex:1;padding:8px 12px;background:transparent;border:none;color:var(--text-muted);font-size:10px;font-weight:600;text-transform:uppercase;cursor:pointer;border-bottom:2px solid transparent;transition:all .2s;white-space:nowrap}.audit-tab:hover{color:var(--text-secondary)}.audit-tab.active{color:var(--accent-cyan);border-bottom-color:var(--accent-cyan)}.audit-panel>:not(.audit-header):not(.audit-tabs){padding:0 16px}.audit-summary{padding:10px;background:var(--bg-tertiary);border-radius:8px;margin:12px 0;text-align:center}.audit-metrics{padding:10px;background:var(--bg-tertiary);border-radius:8px;margin-bottom:12px}.audit-metric-row{display:flex;justify-content:space-between;font-size:11px;padding:6px 0;color:var(--text-secondary)}.audit-metric-label{flex:1}.audit-section{margin-bottom:12px}.audit-section-title{font-size:10px;font-weight:600;text-transform:uppercase;color:var(--text-muted);margin-bottom:8px;padding:0 4px}.audit-section-header{display:flex;align-items:center;gap:6px;cursor:pointer;padding:8px 4px;border-radius:4px;-webkit-user-select:none;user-select:none;transition:all .2s ease}.audit-section-header:hover{background:#b9bf7f14}.audit-section-toggle{display:inline-flex;align-items:center;justify-content:center;width:12px;font-size:8px;color:#20cfdf;transition:transform .2s ease}.audit-section-content{display:flex;flex-direction:column;gap:6px;padding:0 4px 8px;animation:slideDown .2s ease}@keyframes slideDown{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.audit-issue{padding:10px;background:var(--bg-tertiary);border-radius:8px;margin-bottom:6px;border-left:3px solid;cursor:pointer;transition:all .2s}.audit-issue:hover{background:var(--bg-hover)}.audit-issue.error{border-left-color:var(--accent-red)}.audit-issue.warn{border-left-color:var(--accent-amber)}.audit-issue-rule{font-size:11px;font-weight:600;margin-bottom:4px;color:var(--text-primary)}.audit-issue-message{font-size:10px;color:var(--text-secondary);line-height:1.4}.audit-components{margin-top:12px}.audit-component-item{display:flex;align-items:center;gap:8px;padding:10px;background:var(--bg-tertiary);border-radius:8px;margin-bottom:6px;cursor:pointer;transition:all .2s;font-size:11px}.audit-component-item:hover{background:var(--bg-hover)}.audit-component-info{flex:1;min-width:0}.audit-component-name{font-weight:500;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.audit-badge{display:inline-block;padding:4px 8px;border-radius:4px;font-size:9px;font-weight:600;margin-left:8px}.audit-badge.pass{background:var(--accent-green);color:#000}.audit-badge.fail{background:var(--accent-red);color:#fff}.ops-header{display:flex;justify-content:space-between;align-items:center;padding:10px 12px 0}.ops-section{padding:12px}.ops-empty{color:var(--text-muted);font-size:11px;text-align:center;padding:20px 12px}.ops-hint{display:block;margin-top:6px;font-family:JetBrains Mono,monospace;font-size:10px;color:var(--accent-cyan);opacity:.7}.wf-item{border:1px solid var(--border-color);border-radius:8px;margin-bottom:6px;overflow:hidden}.wf-header{display:flex;justify-content:space-between;align-items:center;padding:8px 10px;cursor:pointer;transition:background .15s}.wf-header:hover{background:var(--bg-hover)}.wf-header-left{display:flex;align-items:center;gap:6px;overflow:hidden}.wf-expand{font-size:11px;color:var(--text-muted);width:12px;flex-shrink:0}.wf-name{font-size:11px;font-weight:600;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wf-tag{font-size:8px;color:var(--text-muted);background:var(--bg-tertiary);padding:1px 5px;border-radius:3px;flex-shrink:0}.wf-status{font-size:9px;font-weight:600;flex-shrink:0}.wf-status.completed{color:var(--accent-green)}.wf-status.running{color:var(--accent-amber)}.wf-status.failed{color:var(--accent-red)}.wf-detail{padding:0 10px 10px;border-top:1px solid var(--border-color)}.wf-desc{font-size:10px;color:var(--text-muted);padding:8px 0 6px}.wf-steps{display:flex;flex-direction:column;gap:3px}.wf-step{display:flex;align-items:center;gap:6px;font-size:10px;padding:3px 0}.wf-step-icon{font-size:10px;width:14px;text-align:center}.wf-step.completed .wf-step-icon{color:var(--accent-green)}.wf-step.running .wf-step-icon{color:var(--accent-amber)}.wf-step.failed .wf-step-icon{color:var(--accent-red)}.wf-step.pending .wf-step-icon{color:var(--text-muted)}.wf-step-id{color:var(--text-secondary)}.wf-step.completed .wf-step-id{color:var(--text-muted)}.wf-progress{display:flex;align-items:center;gap:8px;margin-top:6px}.wf-progress-bar{flex:1;height:4px;background:var(--bg-tertiary);border-radius:2px;overflow:hidden}.wf-progress-fill{height:100%;background:var(--accent-cyan);border-radius:2px;transition:width .3s ease}.wf-progress-label{font-size:10px;font-weight:600;color:var(--text-muted);min-width:28px;text-align:right}.wf-steps-preview{font-size:10px;color:var(--text-muted);font-family:JetBrains Mono,monospace;padding:4px 0}.wf-run-hint{font-size:9px;font-family:JetBrains Mono,monospace;color:var(--accent-cyan);opacity:.6;margin-top:6px}.wf-actions{display:flex;gap:6px;margin-top:8px}.wf-actions .panel-btn{flex:1}.wf-error{font-size:11px;color:var(--accent-red);background:#f425251a;border:1px solid hsl(0 90% 55% / .25);border-radius:6px;padding:6px 10px;margin-bottom:8px}.change-indicator{position:absolute;top:-6px;right:-6px;width:16px;height:16px;border-radius:50%;font-size:10px;font-weight:700;display:flex;align-items:center;justify-content:center;z-index:10;animation:change-pulse 2s ease-in-out infinite}.change-indicator.change-added{background:var(--accent-green);color:#fff}.change-indicator.change-modified{background:var(--accent-amber);color:#000}.change-indicator.change-removed{background:var(--accent-red);color:#fff}.arch-node.change-added{box-shadow:0 0 0 2px var(--accent-green),0 0 12px #1abc554d}.arch-node.change-modified{box-shadow:0 0 0 2px var(--accent-amber),0 0 12px #f59f0a4d}.arch-node.change-removed{box-shadow:0 0 0 2px var(--accent-red),0 0 12px #f425254d;opacity:.6}@keyframes change-pulse{0%,to{transform:scale(1)}50%{transform:scale(1.3)}}.chat-panel{position:absolute;bottom:16px;right:16px;width:350px;height:400px;background:#090e1af2;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);border:1px solid var(--border-color);border-radius:12px;display:flex;flex-direction:column;z-index:20;box-shadow:0 4px 24px var(--shadow-color),var(--glow-cyan);animation:slide-up-chat .2s ease-out}@keyframes slide-up-chat{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}.chat-header{display:flex;justify-content:space-between;align-items:center;padding:10px 14px;border-bottom:1px solid var(--border-color);flex-shrink:0}.chat-title{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;color:var(--accent-cyan)}.chat-messages{flex:1;overflow-y:auto;padding:12px;display:flex;flex-direction:column;gap:8px;min-height:0}.chat-empty{color:var(--text-muted);font-size:12px;text-align:center;padding:40px 20px}.chat-message{max-width:85%;padding:8px 12px;border-radius:10px;font-size:12px;line-height:1.5;word-wrap:break-word;white-space:pre-wrap}.chat-message.user{align-self:flex-end;background:#20cfdf26;border:1px solid hsl(185 75% 50% / .25);color:var(--text-primary)}.chat-message.assistant{align-self:flex-start;background:var(--bg-tertiary);border:1px solid var(--border-color);color:var(--text-secondary)}.chat-message-content{font-family:JetBrains Mono,monospace}.chat-cursor{display:inline-block;width:6px;height:14px;background:var(--accent-cyan);margin-left:2px;vertical-align:text-bottom;animation:chat-blink .8s step-end infinite}@keyframes chat-blink{0%,to{opacity:1}50%{opacity:0}}.chat-input-bar{display:flex;gap:6px;padding:10px 12px;border-top:1px solid var(--border-color);flex-shrink:0}.chat-input{flex:1;height:32px;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:6px;padding:0 10px;font-size:12px;font-family:JetBrains Mono,monospace;color:var(--text-primary);outline:none;transition:border-color .2s}.chat-input::placeholder{color:var(--text-muted)}.chat-input:focus{border-color:var(--accent-cyan);box-shadow:0 0 0 2px #20cfdf26}.chat-send-btn,.chat-stop-btn{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:6px;border:1px solid var(--border-color);cursor:pointer;font-size:14px;font-weight:700;transition:all .2s;flex-shrink:0}.chat-send-btn{background:#20cfdf26;color:var(--accent-cyan);border-color:#20cfdf4d}.chat-send-btn:hover:not(:disabled){background:#20cfdf40}.chat-send-btn:disabled{opacity:.3;cursor:not-allowed}.chat-stop-btn{background:#f4252526;color:var(--accent-red);border-color:#f425254d;font-size:10px}.chat-stop-btn:hover{background:#f4252540}[data-theme=light] .arch-node{box-shadow:0 2px 12px #00000014,inset 0 1px #fff9}[data-theme=light] .arch-node:hover{box-shadow:0 4px 20px #0000001f,inset 0 1px #fff9}[data-theme=light] .arch-node:before{background:linear-gradient(90deg,transparent,rgba(255,255,255,.4),transparent)}[data-theme=light] .arch-node .node-tech-pill{background:#0000000a;border-color:#0000001a}[data-theme=light] .arch-node.presentation{background:linear-gradient(145deg,#e9f0f7,#d7e6f4);border-color:#428cd780;color:#19334d}[data-theme=light] .arch-node.presentation:hover{border-color:#428cd7;box-shadow:0 0 20px #428cd726,0 4px 20px #0000001f}[data-theme=light] .arch-node.presentation .node-tech-pill{color:#2e669e}[data-theme=light] .arch-node.application{background:linear-gradient(145deg,#f7f0e8,#f5e6d6);border-color:#df802080;color:#452e17}[data-theme=light] .arch-node.application:hover{border-color:#df8020;box-shadow:0 0 20px #df802026,0 4px 20px #0000001f}[data-theme=light] .arch-node.application .node-tech-pill{color:#8f5924}[data-theme=light] .arch-node.data{background:linear-gradient(145deg,#e6f4eb,#d5f1de);border-color:#2e9e5380;color:#1c4028}[data-theme=light] .arch-node.data:hover{border-color:#2e9e53;box-shadow:0 0 20px #2e9e5326,0 4px 20px #0000001f}[data-theme=light] .arch-node.data .node-tech-pill{color:#2a6f41}[data-theme=light] .arch-node.external{background:linear-gradient(145deg,#f1eaf5,#e9daf1);border-color:#9540bf80;color:#392145}[data-theme=light] .arch-node.external:hover{border-color:#9540bf;box-shadow:0 0 20px #9540bf26,0 4px 20px #0000001f}[data-theme=light] .arch-node.external .node-tech-pill{color:#743d8f}[data-theme=light] .arch-node.deployment{background:linear-gradient(145deg,#f7eded,#f4dddd);border-color:#be373780;color:#452121}[data-theme=light] .arch-node.deployment:hover{border-color:#be3737;box-shadow:0 0 20px #be373726,0 4px 20px #0000001f}[data-theme=light] .arch-node.deployment .node-tech-pill{color:#813131}[data-theme=light] .legend-color.presentation{background:#d9e6f2;border-color:#428cd7}[data-theme=light] .legend-color.application{background:#f2e6d9;border-color:#df8020}[data-theme=light] .legend-color.data{background:#dbf0e2;border-color:#2e9e53}[data-theme=light] .legend-color.external{background:#e8ddee;border-color:#9540bf}[data-theme=light] .legend-color.deployment{background:#f0dbdb;border-color:#be3737}[data-theme=light] .branding-header{background:#f6f7f9eb;border-bottom-color:#1295a126;box-shadow:0 1px 12px #1295a10f}[data-theme=light] .component-info-panel,[data-theme=light] .node-details-panel,[data-theme=light] .node-actions-panel,[data-theme=light] .hidden-nodes-panel,[data-theme=light] .agent-panel,[data-theme=light] .chat-panel{background:#f6f7f9eb;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}[data-theme=light] .flow-progress-bar{background:#f6f7f9f2;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}[data-theme=light] .save-panel{background:#1295a11a}[data-theme=light] ::-webkit-scrollbar-track{background:var(--bg-secondary)}[data-theme=light] ::-webkit-scrollbar-thumb{background:#bec4cf}[data-theme=light] ::-webkit-scrollbar-thumb:hover{background:#a1a9ba}[data-theme=light] .git-repo-badge{background:#efe7f3;border-color:#9540bf4d;color:#739}[data-theme=light] .git-repo-badge:hover{background:#e4d6eb;border-color:#9540bf80}[data-theme=light] .toolbar-btn.active{background:#1295a11a}[data-theme=light] .flow-progress-btn.stop{border-color:#d4111140}[data-theme=light] .flow-progress-btn.stop:hover{background:#d411111a}[data-theme=light] .react-flow__controls-button{background:var(--bg-secondary);border-color:var(--border-color);fill:var(--text-primary);color:var(--text-primary)}[data-theme=light] .react-flow__controls-button:hover{background:var(--bg-hover)}[data-theme=light] .react-flow__handle{border-color:var(--bg-primary)}[data-theme=light] .react-flow__node.selected .arch-node{box-shadow:0 0 0 2px #1295a159,0 4px 12px #0000001f}.health-panel{position:absolute;top:16px;right:16px;width:320px;max-height:70vh;overflow-y:auto;background:#090e1aeb;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid var(--border-color);border-radius:12px;z-index:10;box-shadow:0 4px 24px var(--shadow-color)}.health-header{display:flex;align-items:center;justify-content:space-between;padding:12px 14px;border-bottom:1px solid var(--border-color)}.health-title{font-size:13px;font-weight:700;color:var(--text-primary)}.health-graph-summary{display:flex;gap:4px;padding:10px 14px;border-bottom:1px solid var(--border-color)}.health-stat{display:flex;flex-direction:column;align-items:center;flex:1;padding:6px;background:var(--bg-tertiary);border-radius:6px}.health-stat-value{font-size:16px;font-weight:700;font-family:JetBrains Mono,monospace}.health-stat-label{font-size:9px;color:var(--text-muted);text-transform:uppercase;letter-spacing:.3px;margin-top:2px}.health-list{padding:4px 0;max-height:350px;overflow-y:auto}.health-item{display:flex;align-items:center;gap:10px;padding:8px 14px;cursor:pointer;transition:background .15s}.health-item:hover{background:var(--bg-hover)}.health-item-score{font-size:16px;font-weight:700;font-family:JetBrains Mono,monospace;min-width:32px;text-align:center}.health-item-info{flex:1;min-width:0}.health-item-name{font-size:12px;font-weight:600;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.health-item-badges{display:flex;gap:4px;margin-top:2px}.health-flag{font-size:9px;font-weight:600;padding:1px 5px;border-radius:3px;text-transform:uppercase;letter-spacing:.3px}.health-flag.orphan{background:#f59f0a26;color:var(--accent-amber);border:1px solid hsl(38 92% 50% / .3)}.health-flag.hub{background:#a65eed26;color:#a65eed;border:1px solid hsl(270 80% 65% / .3)}.health-flag.cycle{background:#f4252526;color:var(--accent-red);border:1px solid hsl(0 90% 55% / .3)}.health-flag.ok{background:#1abc5526;color:var(--accent-green);border:1px solid hsl(142 76% 42% / .3)}.health-item-connections{font-size:10px;color:var(--text-muted);font-family:JetBrains Mono,monospace;white-space:nowrap}.arch-node.health-green{border-color:var(--accent-green)!important;box-shadow:0 0 8px #1abc554d!important}.arch-node.health-amber{border-color:var(--accent-amber)!important;box-shadow:0 0 8px #f59f0a4d!important}.arch-node.health-red{border-color:var(--accent-red)!important;box-shadow:0 0 12px #f4252566!important}.arch-node.health-orphan{border-style:dashed!important}.arch-node.health-cycle{animation:health-pulse 2s ease-in-out infinite!important}@keyframes health-pulse{0%,to{box-shadow:0 0 8px #f425254d}50%{box-shadow:0 0 20px #f4252599}}.health-hub-badge{position:absolute;top:-8px;right:-8px;font-size:8px;font-weight:700;padding:2px 5px;border-radius:4px;background:#a65eed;color:#fff;letter-spacing:.3px;z-index:2}.pending-change-badge{position:absolute;top:-6px;right:-6px;font-size:9px;font-weight:700;padding:1px 5px;border-radius:8px;background:var(--accent-amber);color:#070a13;font-family:JetBrains Mono,monospace;cursor:pointer;z-index:2}.pending-sticky-note{background:#fceec5;border:1px solid hsl(40 60% 70%);border-radius:4px;padding:8px 10px;margin:0 -2px 4px;font-family:JetBrains Mono,monospace;font-size:10px;line-height:1.5;color:#38332e}.pending-sticky-header{font-weight:700;font-size:8px;text-transform:uppercase;letter-spacing:.3px;color:#74593e;margin-bottom:3px;padding-bottom:3px;border-bottom:1px solid hsl(40 50% 75%)}.pending-file-row{display:flex;align-items:center;gap:3px}.pending-file-event{font-weight:700;width:8px;flex-shrink:0}.pending-file-row.add .pending-file-event{color:#1f7a40}.pending-file-row.change .pending-file-event{color:#ad661f}.pending-file-row.unlink .pending-file-event{color:#c32222}.pending-file-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#464039}.pending-file-more{color:#998066;font-size:7px;margin-top:2px}.arch-node.has-pending-changes{box-shadow:0 0 0 2px #f59f0a66,0 0 12px #f59f0a26}.changelog-panel{position:absolute;top:16px;right:16px;width:340px;max-height:65vh;overflow-y:auto;background:#090e1aeb;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid var(--border-color);border-radius:12px;z-index:10;box-shadow:0 4px 24px var(--shadow-color)}.changelog-header{display:flex;align-items:center;justify-content:space-between;padding:12px 14px;border-bottom:1px solid var(--border-color)}.changelog-title{font-size:13px;font-weight:700;color:var(--text-primary)}.changelog-summary{display:flex;align-items:center;gap:8px;padding:8px 14px;border-bottom:1px solid var(--border-color);font-size:11px}.changelog-summary-total{color:var(--text-secondary);font-weight:600}.changelog-badge{font-size:10px;font-weight:700;padding:1px 6px;border-radius:4px;font-family:JetBrains Mono,monospace}.changelog-badge.added{background:#1abc5526;color:var(--accent-green)}.changelog-badge.modified{background:#f59f0a26;color:var(--accent-amber)}.changelog-badge.removed{background:#f4252526;color:var(--accent-red)}.changelog-list{padding:4px 0}.changelog-entry{border-bottom:1px solid var(--border-light)}.changelog-entry:last-child{border-bottom:none}.changelog-entry-header{display:flex;align-items:center;gap:8px;padding:8px 14px;cursor:pointer;transition:background .15s}.changelog-entry-header:hover{background:var(--bg-hover)}.changelog-entry-time{font-size:11px;color:var(--text-muted);min-width:50px;font-family:JetBrains Mono,monospace}.changelog-entry-stats{display:flex;align-items:center;gap:6px;flex:1}.changelog-entry-files{font-size:11px;color:var(--text-secondary)}.changelog-expand{font-size:10px;color:var(--text-muted)}.changelog-entry-details{padding:4px 14px 10px;border-top:1px solid var(--border-light);margin:0 8px}.changelog-diff-section{margin-top:6px}.changelog-diff-label{font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;margin-bottom:2px}.changelog-diff-label.added{color:var(--accent-green)}.changelog-diff-label.modified{color:var(--accent-amber)}.changelog-diff-label.removed{color:var(--accent-red)}.changelog-diff-item{font-size:11px;color:var(--text-secondary);padding:2px 0 2px 8px;border-left:2px solid var(--border-color)}.changelog-entry-meta{font-size:10px;color:var(--text-muted);margin-top:6px;text-align:right}.changelog-dot{display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--accent-green);margin-left:4px;animation:breathe 2s infinite}@keyframes breathe{0%,to{opacity:1}50%{opacity:.4}}.rules-config-toggle{display:flex;justify-content:center;padding:8px 14px;border-top:1px solid var(--border-color)}.rules-config{padding:8px 14px 12px;border-top:1px solid var(--border-color)}.rules-section-title{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--text-muted);margin-bottom:6px}.rule-config-item{display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding:6px 8px;border-radius:6px;margin-bottom:4px;background:var(--bg-tertiary);position:relative}.rule-config-item.custom{border-left:3px solid hsl(185 75% 50% / .5)}.rule-config-name{font-size:11px;font-weight:600;color:var(--text-primary);display:flex;align-items:center;gap:6px}.rule-config-desc{font-size:10px;color:var(--text-muted);width:100%}.rule-config-matcher{font-size:10px;color:var(--text-secondary);font-family:JetBrains Mono,monospace}.rule-level-badge{font-size:8px;font-weight:700;padding:1px 5px;border-radius:3px;text-transform:uppercase}.rule-level-badge.error{background:#f4252526;color:var(--accent-red)}.rule-level-badge.warn{background:#f59f0a26;color:var(--accent-amber)}.rule-type-badge{font-size:8px;font-weight:700;padding:1px 5px;border-radius:3px;text-transform:uppercase;margin-left:4px}.rule-type-badge.custom{background:#20cfdf26;color:var(--accent-cyan)}.rule-delete-btn{position:absolute;right:4px;top:50%;transform:translateY(-50%);flex:0!important;padding:2px 6px!important;min-width:auto}.rule-add-form{margin-top:10px;padding:10px;background:var(--bg-tertiary);border-radius:8px;border:1px solid var(--border-color)}.rule-add-title{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--text-muted);margin-bottom:6px}.rule-input{width:100%;height:28px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:4px;padding:0 8px;font-size:11px;font-family:JetBrains Mono,monospace;color:var(--text-primary);outline:none;margin-bottom:4px}.rule-input:focus{border-color:var(--accent-cyan)}.rule-input::placeholder{color:var(--text-muted)}.rule-add-row{display:flex;align-items:center;gap:6px}.rule-arrow{font-size:12px;color:var(--text-muted);flex-shrink:0}.rule-select{height:28px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:4px;padding:0 8px;font-size:11px;font-family:JetBrains Mono,monospace;color:var(--text-primary);outline:none;flex:1}.rules-save-row{display:flex;justify-content:flex-end;margin-top:10px}[data-theme=light] .health-panel,[data-theme=light] .changelog-panel{background:#f9fafbf5}[data-theme=light] .arch-node.health-green{box-shadow:0 0 6px #178c4240!important}.rules-config-modal{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:var(--bg-primary);border:1px solid var(--border-color);border-radius:12px;box-shadow:0 25px 80px #000c;z-index:10000;max-width:650px;width:95%;max-height:75vh;overflow:hidden;display:flex;flex-direction:column}.rules-modal-header{display:flex;justify-content:space-between;align-items:center;padding:16px;border-bottom:1px solid var(--border-color);flex-shrink:0;background:var(--bg-secondary)}.rules-modal-title{font-weight:600;color:var(--text-primary);font-size:14px;letter-spacing:.5px}.rules-modal-tabs{display:flex;border-bottom:1px solid var(--border-color);background:var(--bg-secondary);flex-shrink:0}.rules-modal-tab{flex:1;padding:8px 12px;border:none;background:transparent;color:var(--text-secondary);font-size:11px;cursor:pointer;transition:all .2s ease;border-bottom:2px solid transparent}.rules-modal-tab:hover{color:var(--text-primary);background:#b9bf7f0d}.rules-modal-tab.active{color:#20cfdf;border-bottom-color:#20cfdf}.rules-modal-content{flex:1;overflow-y:auto;padding:16px;scrollbar-width:thin;scrollbar-color:var(--border-color) transparent}[data-theme=light] .arch-node.health-amber{box-shadow:0 0 6px #cb850b40!important}[data-theme=light] .arch-node.health-red{box-shadow:0 0 8px #d411114d!important}.changes-banner{display:flex;align-items:center;gap:10px;padding:6px 14px;background:#f59f0a14;border-bottom:1px solid hsl(38 92% 50% / .25);font-family:JetBrains Mono,monospace;font-size:12px;animation:changes-banner-slide-in .25s ease-out}@keyframes changes-banner-slide-in{0%{opacity:0;transform:translateY(-100%)}to{opacity:1;transform:translateY(0)}}.changes-banner-pulse{width:7px;height:7px;border-radius:50%;background:var(--accent-amber);flex-shrink:0;animation:changes-pulse 1.8s ease-in-out infinite}@keyframes changes-pulse{0%,to{opacity:1;box-shadow:0 0 #f59f0a66}50%{opacity:.6;box-shadow:0 0 0 4px #f59f0a00}}.changes-banner-text{color:var(--accent-amber);font-weight:600;letter-spacing:.02em;white-space:nowrap}.changes-banner-actions{display:flex;gap:6px;margin-left:4px}.changes-banner-btn{padding:3px 10px;border-radius:4px;border:1px solid transparent;font-family:JetBrains Mono,monospace;font-size:11px;font-weight:500;cursor:pointer;transition:all .15s ease}.changes-banner-btn.quick{background:#20cfdf1f;border-color:#20cfdf4d;color:var(--accent-cyan)}.changes-banner-btn.quick:hover{background:#20cfdf38;border-color:#20cfdf80}.changes-banner-btn.full{background:#8d52e01f;border-color:#8d52e04d;color:#aa7de8}.changes-banner-btn.full:hover{background:#8d52e038;border-color:#8d52e080}.changes-banner-dismiss{margin-left:auto;background:none;border:none;color:var(--text-muted);font-size:16px;cursor:pointer;padding:0 4px;line-height:1;transition:color .15s ease}.changes-banner-dismiss:hover{color:var(--text-primary)}.changes-banner-file-count{font-weight:400;color:var(--text-muted);margin-left:4px;font-size:11px}.changes-banner-components{display:flex;flex-wrap:wrap;gap:4px}.changes-component-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;background:#f59f0a1a;border:1px solid hsl(38 92% 50% / .25);border-radius:4px;font-family:JetBrains Mono,monospace;font-size:10px;font-weight:500;color:var(--accent-amber);cursor:pointer;transition:background .15s;white-space:nowrap}.changes-component-chip:hover{background:#f59f0a33}.changes-component-chip.unmapped{color:var(--text-muted);background:var(--bg-tertiary);border-color:var(--border-color);cursor:default}.changes-component-count{font-size:9px;font-weight:700;background:#f59f0a33;padding:0 4px;border-radius:3px;min-width:14px;text-align:center}.changes-event-dot{width:6px;height:6px;border-radius:50%;flex-shrink:0}.changes-event-dot.new{background:var(--accent-green)}.changes-event-dot.mod{background:var(--accent-amber)}.changes-event-dot.del{background:var(--accent-red)}[data-theme=light] .changes-banner{background:#cb850b0f;border-bottom-color:#cb850b33}[data-theme=light] .changes-banner-text{color:var(--accent-amber)}[data-theme=light] .changes-banner-btn.quick{background:#1295a11a;border-color:#1295a140;color:var(--accent-cyan)}[data-theme=light] .changes-banner-btn.full{background:#7333cc1a;border-color:#7333cc40;color:#672eb8}.deep-drill-panel{position:absolute;top:16px;left:16px;background:#090e1aeb;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);padding:0;border-radius:12px;border:1px solid hsl(142 76% 42% / .2);font-size:12px;color:var(--text-primary);z-index:16;width:400px;max-width:calc(100vw - 32px);max-height:80vh;overflow-y:auto;box-shadow:0 4px 24px #0006,0 0 0 1px #1abc5514}.deep-drill-header{display:flex;justify-content:space-between;align-items:flex-start;padding:14px 16px;border-bottom:1px solid hsl(142 76% 42% / .15);background:#1abc550d;border-radius:12px 12px 0 0}.deep-drill-title{font-size:14px;font-weight:600;color:var(--accent-green)}.deep-drill-subtitle{font-size:10px;color:var(--text-muted);font-family:JetBrains Mono,monospace;margin-top:2px}.deep-drill-loading{display:flex;align-items:center;justify-content:center;gap:10px;padding:40px 16px;color:var(--text-secondary);font-size:12px}.deep-drill-body{padding:8px 0}.deep-drill-meta{padding:4px 16px 8px;font-size:10px;color:var(--text-muted)}.dd-section{border-top:1px solid var(--border-light)}.dd-section-header{display:flex;align-items:center;gap:6px;width:100%;padding:10px 16px;background:transparent;border:none;color:var(--text-secondary);font-size:11px;font-weight:600;font-family:JetBrains Mono,monospace;text-transform:uppercase;letter-spacing:.5px;cursor:pointer;transition:color .15s}.dd-section-header:hover{color:var(--text-primary)}.dd-section-chevron{font-size:10px;color:var(--text-muted)}.dd-section-content{padding:0 16px 12px}.dd-metric-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:8px}.dd-metric-card{background:var(--bg-tertiary);border:1px solid var(--border-light);border-radius:8px;padding:10px;text-align:center}.dd-metric-value{font-size:18px;font-weight:700;color:var(--accent-cyan);line-height:1.2}.dd-metric-label{font-size:9px;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px;margin-top:4px}.dd-lang-badges{display:flex;flex-wrap:wrap;gap:4px}.dd-lang-badge{display:inline-block;padding:2px 8px;background:#20cfdf1a;border:1px solid hsl(185 75% 50% / .2);border-radius:4px;font-size:10px;color:var(--accent-cyan)}.dd-key-files{display:flex;flex-direction:column;gap:4px;margin-bottom:8px}.dd-key-file-item{display:flex;align-items:center;gap:8px;padding:4px 0}.dd-role-badge{display:inline-block;padding:1px 6px;background:#1abc551a;border:1px solid hsl(142 76% 42% / .2);border-radius:3px;font-size:9px;font-weight:600;color:var(--accent-green);text-transform:uppercase;white-space:nowrap;min-width:60px;text-align:center}.dd-file-path{font-family:JetBrains Mono,monospace;font-size:10px;color:var(--text-secondary);word-break:break-all}.dd-subsection-title{font-size:10px;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px;margin:8px 0 6px}.dd-exports{display:flex;flex-wrap:wrap;gap:4px}.dd-export-name{display:inline-block;padding:2px 8px;background:#f59f0a1a;border:1px solid hsl(38 92% 50% / .2);border-radius:4px;font-size:10px;font-family:JetBrains Mono,monospace;color:var(--accent-amber)}.dd-dep-list{display:flex;flex-wrap:wrap;gap:4px}.dd-dep-badge{display:inline-block;padding:2px 8px;background:var(--bg-tertiary);border:1px solid var(--border-light);border-radius:4px;font-size:10px;color:var(--text-secondary)}.dd-dep-badge.categorized{background:#20cfdf14;border-color:#20cfdf26;color:var(--accent-cyan)}.dd-dep-badge.dev{opacity:.7}.dd-dep-more{font-size:10px;color:var(--text-muted);padding:2px 4px}.dd-pattern-group{margin-bottom:10px}.dd-pattern-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:4px}.dd-pattern-label{font-size:11px;font-weight:500;color:var(--text-primary)}.dd-pattern-count{font-size:10px;color:var(--text-muted);background:var(--bg-tertiary);padding:1px 6px;border-radius:3px}.dd-pattern-matches{display:flex;flex-direction:column;gap:2px}.dd-pattern-match{display:flex;flex-direction:column;padding:4px 8px;background:var(--bg-tertiary);border-radius:4px;border:1px solid var(--border-light)}.dd-match-file{font-size:9px;color:var(--text-muted);font-family:JetBrains Mono,monospace}.dd-match-content{font-size:10px;color:var(--text-secondary);font-family:JetBrains Mono,monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dd-connection-item{display:flex;align-items:center;gap:6px;padding:4px 8px;background:var(--bg-tertiary);border-radius:4px;border:1px solid var(--border-light);margin-bottom:4px}.dd-conn-arrow{font-size:11px;color:var(--text-muted);font-family:JetBrains Mono,monospace}.dd-conn-name{font-size:11px;font-weight:500;color:var(--text-primary)}.dd-conn-type{font-size:9px;color:var(--text-muted);background:var(--bg-hover);padding:1px 5px;border-radius:3px;margin-left:auto}.dd-file-tree{font-family:JetBrains Mono,monospace;font-size:10px;max-height:200px;overflow-y:auto}.dd-tree-entry{padding:1px 0;color:var(--text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dd-tree-entry.dir{color:var(--accent-cyan)}.dd-tree-icon{font-size:10px;margin-right:2px}[data-theme=light] .deep-drill-panel{background:#f6f7f9f2;border-color:#178c4233}[data-theme=light] .deep-drill-header{background:#178c420d;border-bottom-color:#178c4226}[data-theme=light] .dd-metric-value{color:var(--accent-cyan)}