@deltarobotics/uhd-viewer 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +22 -0
  4. package/README.md +168 -2
  5. package/bin/serve.d.mts +62 -0
  6. package/bin/serve.mjs +257 -0
  7. package/bin/uhd-viewer.mjs +75 -0
  8. package/dist/app/assets/KodeMono-Bold-DdIivhPN.woff2 +0 -0
  9. package/dist/app/assets/KodeMono-Medium-CVnTuv5A.ttf +0 -0
  10. package/dist/app/assets/KodeMono-Regular-Bdr_-rJX.woff2 +0 -0
  11. package/dist/app/assets/KodeMono-SemiBold-JAfn5Dpm.ttf +0 -0
  12. package/dist/app/assets/index-Boi2erhd.css +2 -0
  13. package/dist/app/assets/index-CkpIRYgM.js +3853 -0
  14. package/dist/app/index.html +16 -0
  15. package/dist/components/components.css +6108 -0
  16. package/dist/components/index.d.ts +1 -0
  17. package/dist/components/index.js +26048 -0
  18. package/dist/components/index.js.map +1 -0
  19. package/dist/components/types/uhd-viewer/src/api.d.ts +286 -0
  20. package/dist/components/types/uhd-viewer/src/cad/CadView.d.ts +52 -0
  21. package/dist/components/types/uhd-viewer/src/cad/ModelView.d.ts +28 -0
  22. package/dist/components/types/uhd-viewer/src/cad/explode.d.ts +110 -0
  23. package/dist/components/types/uhd-viewer/src/cad/explodeSample.d.ts +25 -0
  24. package/dist/components/types/uhd-viewer/src/cad/findings.d.ts +41 -0
  25. package/dist/components/types/uhd-viewer/src/cad/labels.d.ts +76 -0
  26. package/dist/components/types/uhd-viewer/src/cad/model.d.ts +132 -0
  27. package/dist/components/types/uhd-viewer/src/cad/row.d.ts +15 -0
  28. package/dist/components/types/uhd-viewer/src/cad/scene.d.ts +95 -0
  29. package/dist/components/types/uhd-viewer/src/cad/scope.d.ts +89 -0
  30. package/dist/components/types/uhd-viewer/src/canvas/Canvas.d.ts +86 -0
  31. package/dist/components/types/uhd-viewer/src/canvas/Icon.d.ts +5 -0
  32. package/dist/components/types/uhd-viewer/src/canvas/LinkEdge.d.ts +40 -0
  33. package/dist/components/types/uhd-viewer/src/canvas/Port.d.ts +18 -0
  34. package/dist/components/types/uhd-viewer/src/canvas/actions.d.ts +5 -0
  35. package/dist/components/types/uhd-viewer/src/canvas/geometry.d.ts +72 -0
  36. package/dist/components/types/uhd-viewer/src/canvas/interaction.d.ts +162 -0
  37. package/dist/components/types/uhd-viewer/src/canvas/nodes.d.ts +43 -0
  38. package/dist/components/types/uhd-viewer/src/canvas/reveal.d.ts +37 -0
  39. package/dist/components/types/uhd-viewer/src/canvas/rightDrag.d.ts +51 -0
  40. package/dist/components/types/uhd-viewer/src/canvas/routing.d.ts +28 -0
  41. package/dist/components/types/uhd-viewer/src/chrome/ArtifactCards.d.ts +30 -0
  42. package/dist/components/types/uhd-viewer/src/chrome/Artifacts.d.ts +44 -0
  43. package/dist/components/types/uhd-viewer/src/chrome/BoardInspector.d.ts +53 -0
  44. package/dist/components/types/uhd-viewer/src/chrome/Chrome.d.ts +116 -0
  45. package/dist/components/types/uhd-viewer/src/chrome/Evidence.d.ts +20 -0
  46. package/dist/components/types/uhd-viewer/src/chrome/InterfaceCards.d.ts +56 -0
  47. package/dist/components/types/uhd-viewer/src/chrome/PairView.d.ts +37 -0
  48. package/dist/components/types/uhd-viewer/src/chrome/Sections.d.ts +107 -0
  49. package/dist/components/types/uhd-viewer/src/components.d.ts +60 -0
  50. package/dist/components/types/uhd-viewer/src/host/channel.d.ts +49 -0
  51. package/dist/components/types/uhd-viewer/src/host/context.d.ts +29 -0
  52. package/dist/components/types/uhd-viewer/src/host/protocol.d.ts +22 -0
  53. package/dist/components/types/uhd-viewer/src/host/targets.d.ts +85 -0
  54. package/dist/components/types/uhd-viewer/src/layout/board-layout.d.ts +69 -0
  55. package/dist/components/types/uhd-viewer/src/layout/card-body.d.ts +64 -0
  56. package/dist/components/types/uhd-viewer/src/layout/layout.d.ts +94 -0
  57. package/dist/components/types/uhd-viewer/src/layout/module-layout.d.ts +32 -0
  58. package/dist/components/types/uhd-viewer/src/layout/router.d.ts +55 -0
  59. package/dist/components/types/uhd-viewer/src/layout/taps.d.ts +20 -0
  60. package/dist/components/types/uhd-viewer/src/model/artifacts.d.ts +129 -0
  61. package/dist/components/types/uhd-viewer/src/model/classification.d.ts +38 -0
  62. package/dist/components/types/uhd-viewer/src/model/diagnostics.d.ts +27 -0
  63. package/dist/components/types/uhd-viewer/src/model/evidence.d.ts +63 -0
  64. package/dist/components/types/uhd-viewer/src/model/from-uhd.d.ts +57 -0
  65. package/dist/components/types/uhd-viewer/src/model/hierarchy.d.ts +169 -0
  66. package/dist/components/types/uhd-viewer/src/model/isolate.d.ts +33 -0
  67. package/dist/components/types/uhd-viewer/src/model/nets.d.ts +53 -0
  68. package/dist/components/types/uhd-viewer/src/model/outputs.d.ts +79 -0
  69. package/dist/components/types/uhd-viewer/src/model/slots.d.ts +182 -0
  70. package/dist/components/types/uhd-viewer/src/model/types.d.ts +213 -0
  71. package/dist/components/types/uhd-viewer/src/options.d.ts +27 -0
  72. package/dist/components/types/uhd-viewer/src/source/source.d.ts +109 -0
  73. package/dist/components/types/uhd-viewer/src/source/tolerant.d.ts +45 -0
  74. package/dist/components/types/uhd-viewer/src/theme/ThemeProvider.d.ts +33 -0
  75. package/dist/components/types/uhd-viewer/src/theme/adapters.d.ts +28 -0
  76. package/dist/components/types/uhd-viewer/src/theme/resolve.d.ts +19 -0
  77. package/dist/components/types/uhd-viewer/src/theme/themes.d.ts +67 -0
  78. package/dist/components/types/uhd-viewer/src/theme/tokens.d.ts +175 -0
  79. package/dist/components/types/uhd-viewer/src/ui/Inspector.d.ts +45 -0
  80. package/dist/components/types/uhd-viewer/src/ui/Legend.d.ts +40 -0
  81. package/dist/components/types/uhd-viewer/src/ui/ScrollArea.d.ts +16 -0
  82. package/dist/components/types/uhd-viewer/src/ui/Toolbar.d.ts +49 -0
  83. package/dist/components/types/uhd-viewer/src/ui/Tooltips.d.ts +3 -0
  84. package/dist/components/types/uhd-viewer/src/ui/cx.d.ts +2 -0
  85. package/dist/components/types/uhd-viewer/src/ui/legendFit.d.ts +42 -0
  86. package/dist/components/types/uhd-viewer/src/viewer/controller.d.ts +218 -0
  87. package/dist/components/types/uhd-viewer/src/viewer/details.d.ts +81 -0
  88. package/dist/components/types/uhd-viewer/src/viewer/hierarchy.d.ts +60 -0
  89. package/dist/components/types/uhd-viewer/src/viewer/mount.d.ts +12 -0
  90. package/dist/components/types/uhd-viewer/src/viewer/views.d.ts +156 -0
  91. package/dist/headless/index.d.ts +71 -0
  92. package/dist/headless/index.js +7425 -0
  93. package/dist/headless/index.js.map +1 -0
  94. package/dist/lib/api.d.ts +252 -0
  95. package/dist/lib/uhd-viewer.css +3 -0
  96. package/dist/lib/uhd-viewer.d.ts +4 -0
  97. package/dist/lib/uhd-viewer.js +97469 -0
  98. package/package.json +110 -4
  99. package/src/styles/fonts/OFL.txt +93 -0
  100. package/src/styles/tailwind-theme.css +48 -0
package/bin/serve.mjs ADDED
@@ -0,0 +1,257 @@
1
+ /**
2
+ * `uhd-viewer serve`: a small static server for the built viewer (dist/app),
3
+ * one UHD bundle, and the artifact files that bundle references.
4
+ *
5
+ * Bundles written by a producer carry absolute filesystem artifact bases
6
+ * (`UhdBundle.artifactBases`). Each base is mounted at a URL prefix,
7
+ * `/artifacts/<name>/`, and the served bundle names those URLs instead, so no
8
+ * local path reaches the browser. Only files the bundle references as
9
+ * artifacts are served from a base, and only if their real path stays inside
10
+ * it (no `..`, no symlink out). Each goes out with a sandboxing
11
+ * Content-Security-Policy and `nosniff`; an HTML file as a download.
12
+ *
13
+ * Bound to 127.0.0.1 by default, and then only answers requests addressed to a
14
+ * loopback name (a page on another site cannot reach it by DNS rebinding).
15
+ */
16
+ import { createReadStream } from "node:fs";
17
+ import { readFile, realpath, stat } from "node:fs/promises";
18
+ import { createServer } from "node:http";
19
+ import { basename, dirname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
20
+ import { fileURLToPath } from "node:url";
21
+
22
+ export const BUNDLE_SCHEMA = "uhd.bundle/v0";
23
+ /** URL path of the served (rewritten) bundle, relative to the app. */
24
+ export const BUNDLE_URL = "uhd-bundle.json";
25
+ export const DEFAULT_PORT = 5179;
26
+ export const APP_DIR = fileURLToPath(new URL("../dist/app", import.meta.url));
27
+
28
+ const LOOPBACK = new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
29
+
30
+ const TYPES = {
31
+ ".html": "text/html; charset=utf-8",
32
+ ".js": "text/javascript; charset=utf-8",
33
+ ".mjs": "text/javascript; charset=utf-8",
34
+ ".css": "text/css; charset=utf-8",
35
+ ".json": "application/json; charset=utf-8",
36
+ ".txt": "text/plain; charset=utf-8",
37
+ ".md": "text/markdown; charset=utf-8",
38
+ ".svg": "image/svg+xml",
39
+ ".png": "image/png",
40
+ ".jpg": "image/jpeg",
41
+ ".jpeg": "image/jpeg",
42
+ ".webp": "image/webp",
43
+ ".gif": "image/gif",
44
+ ".pdf": "application/pdf",
45
+ ".glb": "model/gltf-binary",
46
+ ".gltf": "model/gltf+json",
47
+ ".step": "model/step",
48
+ ".stp": "model/step",
49
+ ".stl": "model/stl",
50
+ ".dxf": "image/vnd.dxf",
51
+ ".woff2": "font/woff2",
52
+ ".woff": "font/woff",
53
+ ".ttf": "font/ttf",
54
+ };
55
+
56
+ /**
57
+ * Headers on every artifact response (PB-1048): an artifact is a file from a
58
+ * part or a project, not part of the app, so it runs no script, loads nothing
59
+ * but its own images, and is never sniffed into another type. An HTML file is
60
+ * downloaded, not shown.
61
+ */
62
+ export const ARTIFACT_HEADERS = {
63
+ "content-security-policy": "default-src 'none'; img-src 'self' data:; style-src 'unsafe-inline'; sandbox",
64
+ "x-content-type-options": "nosniff",
65
+ };
66
+ const DOWNLOADED = /\.(html?|xhtml|xht|shtml|mht|mhtml)$/i;
67
+
68
+ /** The headers an artifact file is sent with. */
69
+ export function artifactHeaders(file) {
70
+ return DOWNLOADED.test(file) ? { ...ARTIFACT_HEADERS, "content-disposition": `attachment; filename="${basename(file).replace(/[^\x20-\x7e]|["\\]/g, "_")}"` } : { ...ARTIFACT_HEADERS };
71
+ }
72
+
73
+ const typeOf = (file) => TYPES[file.slice(file.lastIndexOf(".")).toLowerCase()] ?? "application/octet-stream";
74
+ const isUrl = (s) => /^https?:\/\//.test(s);
75
+
76
+ /** `dir` contains `file` (both absolute, normalised). */
77
+ const inside = (dir, file) => file === dir || file.startsWith(dir.endsWith(sep) ? dir : dir + sep);
78
+
79
+ /**
80
+ * What to serve for one bundle.
81
+ *
82
+ * @param {any} bundle a parsed `uhd.bundle/v0`
83
+ * @param {string} bundleFile its path on disk (relative bases and definitions without a base resolve against its folder)
84
+ * @returns {{ mounts: Map<string, string>, files: Map<string, string>, bases: Record<string, string>, rewrite: (origin: string) => any }}
85
+ * mounts: URL name → base folder; files: "<name>/<artifact path>" → file;
86
+ * bases: definition id → mount name or URL; rewrite: the bundle as served from `origin`.
87
+ */
88
+ export function planBundle(bundle, bundleFile) {
89
+ if (bundle?.schema !== BUNDLE_SCHEMA) throw new Error(`${bundleFile} is not a UHD bundle (schema ${String(bundle?.schema)})`);
90
+ const bundleDir = dirname(resolve(bundleFile));
91
+ const mounts = new Map();
92
+ const byDir = new Map();
93
+ const mount = (dir) => {
94
+ if (byDir.has(dir)) return byDir.get(dir);
95
+ const stem = basename(dir).replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^[.-]+/, "") || "base";
96
+ let name = stem;
97
+ for (let i = 2; mounts.has(name); i++) name = `${stem}-${i}`;
98
+ mounts.set(name, dir);
99
+ byDir.set(dir, name);
100
+ return name;
101
+ };
102
+ const sourceBases = bundle.artifactBases ?? {};
103
+ const bases = {};
104
+ const files = new Map();
105
+ for (const [id, base] of Object.entries(sourceBases)) bases[id] = isUrl(base) ? base : mount(isAbsolute(base) ? normalize(base) : resolve(bundleDir, base));
106
+ const definitions = [
107
+ ...(bundle.definitions ?? []),
108
+ ...(bundle.scenarios ?? []).flatMap((s) => [s.root, ...(s.definitions ?? [])]).filter(Boolean),
109
+ ];
110
+ for (const def of definitions) {
111
+ for (const a of def.artifacts ?? []) {
112
+ if (!a.filePath || isUrl(a.filePath)) continue;
113
+ if (isUrl(bases[def.id] ?? "")) continue;
114
+ // a definition without a base resolves against the bundle's own folder
115
+ bases[def.id] ??= mount(bundleDir);
116
+ const rel = normalize(a.filePath);
117
+ if (isAbsolute(rel) || rel === ".." || rel.startsWith(`..${sep}`)) continue;
118
+ const name = bases[def.id];
119
+ files.set(`${name}/${rel.split(sep).join("/")}`, join(mounts.get(name), rel));
120
+ }
121
+ }
122
+ const rewrite = (origin) => ({
123
+ ...bundle,
124
+ artifactBases: Object.fromEntries(Object.entries(bases).map(([id, b]) => [id, isUrl(b) ? b : `${origin}/artifacts/${b}`])),
125
+ });
126
+ return { mounts, files, bases, rewrite };
127
+ }
128
+
129
+ /**
130
+ * The app's index.html with its config injected (read by src/main.tsx): the
131
+ * bundle URL and the parent origins it may talk to when framed. The page that
132
+ * frames the app writes its URL, so the origins come from here, not the query.
133
+ */
134
+ export function injectConfig(html, config) {
135
+ const json = JSON.stringify(config).replace(/</g, "\\u003c");
136
+ return html.replace("</head>", ` <script type="application/json" id="uhd-viewer-config">${json}</script>\n </head>`);
137
+ }
138
+
139
+ /** Re-reads the bundle when its file changes (a rebuild while the server runs). */
140
+ function bundleState(bundleFile) {
141
+ let cached;
142
+ return async () => {
143
+ const { mtimeMs, size } = await stat(bundleFile);
144
+ if (!cached || cached.mtimeMs !== mtimeMs || cached.size !== size) {
145
+ const bundle = JSON.parse(await readFile(bundleFile, "utf8"));
146
+ cached = { mtimeMs, size, plan: planBundle(bundle, bundleFile) };
147
+ }
148
+ return cached.plan;
149
+ };
150
+ }
151
+
152
+ function send(res, status, body, type = "text/plain; charset=utf-8", headers = {}) {
153
+ res.writeHead(status, { "content-type": type, "cache-control": "no-cache", ...headers });
154
+ res.end(res.req.method === "HEAD" ? undefined : body);
155
+ }
156
+
157
+ async function sendFile(res, file, cache, headers = {}) {
158
+ const info = await stat(file).catch(() => undefined);
159
+ if (!info?.isFile()) return send(res, 404, "not found", undefined, headers);
160
+ res.writeHead(200, { "content-type": typeOf(file), "content-length": info.size, "cache-control": cache, ...headers });
161
+ if (res.req.method === "HEAD") return res.end();
162
+ createReadStream(file).pipe(res);
163
+ }
164
+
165
+ /**
166
+ * A request handler for the viewer, a bundle and its artifacts. Hosts that
167
+ * serve more (their own pages) can call it for the rest: it answers every
168
+ * request it is given.
169
+ *
170
+ * @param {{ bundleFile: string, appDir?: string, allowHost?: (hostname: string) => boolean, hostOrigins?: string[] }} options
171
+ * hostOrigins: parent origins the app takes host messages from when framed (exact, `scheme://*` or `*`)
172
+ */
173
+ export function viewerHandler({ bundleFile, appDir: app = APP_DIR, allowHost = (h) => LOOPBACK.has(h), hostOrigins = [] }) {
174
+ const appDir = resolve(app);
175
+ const plan = bundleState(resolve(bundleFile));
176
+ const realBase = new Map();
177
+ const realOf = async (dir) => {
178
+ if (!realBase.has(dir)) {
179
+ const real = await realpath(dir).catch(() => undefined);
180
+ if (!real) return undefined;
181
+ realBase.set(dir, real);
182
+ }
183
+ return realBase.get(dir);
184
+ };
185
+ return async (req, res) => {
186
+ try {
187
+ const host = req.headers.host ?? "";
188
+ const hostname = host.replace(/:\d+$/, "");
189
+ if (!allowHost(hostname)) return send(res, 403, `host ${hostname} not allowed`);
190
+ if (req.method !== "GET" && req.method !== "HEAD") return send(res, 405, "method not allowed", undefined, { allow: "GET, HEAD" });
191
+ let path;
192
+ try {
193
+ path = decodeURIComponent(new URL(req.url ?? "/", "http://x").pathname);
194
+ } catch {
195
+ return send(res, 400, "bad request");
196
+ }
197
+ if (path === "/" || path === "/index.html") {
198
+ const html = await readFile(join(appDir, "index.html"), "utf8");
199
+ return send(res, 200, injectConfig(html, hostOrigins.length ? { bundleUrl: BUNDLE_URL, hostOrigins } : { bundleUrl: BUNDLE_URL }), TYPES[".html"]);
200
+ }
201
+ if (path === `/${BUNDLE_URL}`) {
202
+ const p = await plan();
203
+ return send(res, 200, JSON.stringify(p.rewrite(`http://${host}`)), TYPES[".json"]);
204
+ }
205
+ if (path.startsWith("/artifacts/")) {
206
+ const p = await plan();
207
+ const key = path.slice("/artifacts/".length);
208
+ const file = p.files.get(key);
209
+ if (!file) return send(res, 404, "not an artifact of this bundle", undefined, ARTIFACT_HEADERS);
210
+ const base = await realOf(p.mounts.get(key.split("/")[0]));
211
+ const real = await realpath(file).catch(() => undefined);
212
+ if (!base || !real) return send(res, 404, "not found", undefined, ARTIFACT_HEADERS);
213
+ if (!inside(base, real)) return send(res, 403, "outside the artifact base", undefined, ARTIFACT_HEADERS);
214
+ return sendFile(res, real, "no-cache", artifactHeaders(real));
215
+ }
216
+ // the built app: hashed assets are immutable
217
+ const file = resolve(appDir, `.${path}`);
218
+ if (!inside(appDir, file)) return send(res, 404, "not found");
219
+ return sendFile(res, file, relative(appDir, file).startsWith(`assets${sep}`) ? "public, max-age=31536000, immutable" : "no-cache");
220
+ } catch (e) {
221
+ return send(res, 500, String(e instanceof Error ? e.message : e));
222
+ }
223
+ };
224
+ }
225
+
226
+ /**
227
+ * Starts the server. Fails before listening if the bundle or the built app is missing.
228
+ *
229
+ * @param {{ bundleFile: string, port?: number, host?: string, appDir?: string, hostOrigins?: string[] }} options
230
+ * @returns {Promise<{ url: string, server: import("node:http").Server, close: () => Promise<void> }>}
231
+ */
232
+ export async function startServer({ bundleFile, port = DEFAULT_PORT, host = "127.0.0.1", appDir = APP_DIR, hostOrigins = [] }) {
233
+ planBundle(JSON.parse(await readFile(bundleFile, "utf8")), bundleFile);
234
+ await stat(join(appDir, "index.html")).catch(() => {
235
+ throw new Error(`no built viewer at ${appDir}: run \`npm run build\` first`);
236
+ });
237
+ const loopback = LOOPBACK.has(host);
238
+ // exposed on purpose (--host 0.0.0.0): any Host header is accepted
239
+ const server = createServer(viewerHandler({ bundleFile, appDir, hostOrigins, allowHost: loopback ? (h) => LOOPBACK.has(h) : () => true }));
240
+ await new Promise((ok, fail) => {
241
+ server.once("error", fail);
242
+ server.listen(port, host, () => ok(undefined));
243
+ });
244
+ const address = server.address();
245
+ const actual = typeof address === "object" && address ? address.port : port;
246
+ const shown = host === "0.0.0.0" || host === "::" ? "127.0.0.1" : host;
247
+ const name = shown.includes(":") ? `[${shown}]` : shown;
248
+ return {
249
+ url: `http://${name}:${actual}/`,
250
+ server,
251
+ close: () =>
252
+ new Promise((ok) => {
253
+ server.close(() => ok());
254
+ server.closeIdleConnections();
255
+ }),
256
+ };
257
+ }
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * uhd-viewer serve <bundle.json> [--port 5179] [--host 127.0.0.1] [--host-origin <origin>]… [--open]
4
+ *
5
+ * Serves the built viewer with one UHD bundle and its artifacts (bin/serve.mjs).
6
+ */
7
+ import { spawn } from "node:child_process";
8
+ import { parseArgs } from "node:util";
9
+ import { DEFAULT_PORT, startServer } from "./serve.mjs";
10
+
11
+ const USAGE = `usage: uhd-viewer serve <bundle.json> [--port ${DEFAULT_PORT}] [--host 127.0.0.1] [--host-origin <origin>]… [--open]
12
+
13
+ Serves the viewer, the bundle and the artifact files it references.
14
+ --port port to listen on (0: any free port)
15
+ --host address to bind; anything but a loopback address exposes the files to the network
16
+ --host-origin an origin that may frame the viewer and drive it with host messages
17
+ (exact, scheme://* or *; repeat or separate with commas)
18
+ --open open the viewer in the default browser`;
19
+
20
+ /** The platform's "open this URL" command. */
21
+ function openBrowser(url) {
22
+ const [cmd, args] =
23
+ process.platform === "darwin" ? ["open", [url]] : process.platform === "win32" ? ["cmd", ["/c", "start", "", url]] : ["xdg-open", [url]];
24
+ const child = spawn(cmd, args, { stdio: "ignore", detached: true });
25
+ child.on("error", () => console.error(`could not open a browser: open ${url} yourself`));
26
+ child.unref();
27
+ }
28
+
29
+ async function main() {
30
+ let parsed;
31
+ try {
32
+ parsed = parseArgs({
33
+ allowPositionals: true,
34
+ options: {
35
+ port: { type: "string" },
36
+ host: { type: "string" },
37
+ "host-origin": { type: "string", multiple: true },
38
+ open: { type: "boolean" },
39
+ help: { type: "boolean", short: "h" },
40
+ },
41
+ });
42
+ } catch (e) {
43
+ console.error(`${e instanceof Error ? e.message : e}\n\n${USAGE}`);
44
+ return 2;
45
+ }
46
+ const { values, positionals } = parsed;
47
+ const [command, bundleFile, ...extra] = positionals;
48
+ if (values.help) {
49
+ console.log(USAGE);
50
+ return 0;
51
+ }
52
+ if (command !== "serve" || !bundleFile || extra.length) {
53
+ console.error(USAGE);
54
+ return 2;
55
+ }
56
+ const port = values.port === undefined ? DEFAULT_PORT : Number(values.port);
57
+ if (!Number.isInteger(port) || port < 0 || port > 65535) {
58
+ console.error(`--port must be a port number, not ${values.port}`);
59
+ return 2;
60
+ }
61
+ try {
62
+ const hostOrigins = (values["host-origin"] ?? []).flatMap((v) => v.split(",").map((s) => s.trim()).filter(Boolean));
63
+ const { url } = await startServer({ bundleFile, port, host: values.host, hostOrigins });
64
+ console.log(`uhd-viewer: serving ${bundleFile} at ${url}`);
65
+ if (values.open) openBrowser(url);
66
+ } catch (e) {
67
+ const err = /** @type {NodeJS.ErrnoException} */ (e);
68
+ console.error(`uhd-viewer: ${err.code === "EADDRINUSE" ? `port ${port} is in use (try --port 0)` : err.code === "ENOENT" ? `no such file ${err.path}` : err.message}`);
69
+ return 1;
70
+ }
71
+ return undefined;
72
+ }
73
+
74
+ const code = await main();
75
+ if (code !== undefined) process.exitCode = code;
@@ -0,0 +1,2 @@
1
+ /*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial;--tw-content:"";--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0}}}@layer theme{:root,:host{--color-white:#fff;--spacing:.25rem;--font-weight-normal:400;--font-weight-semibold:600;--font-weight-bold:700;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-md:.375rem;--ease-out:cubic-bezier(0, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}}@layer base{.react-flow{--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:#ffffff80;--xy-minimap-background-color-default:#fff;--xy-minimap-mask-background-color-default:#f0f0f099;--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:#f0f0f040;--xy-node-boxshadow-hover-default:0 1px 4px 1px #00000014;--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:#0059dc14;--xy-selection-border-default:1px dotted #0059dccc;--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 #00000014;--xy-edge-label-background-color-default:#fff;--xy-edge-label-color-default:inherit;--xy-resize-background-color-default:#3367d9;direction:ltr}.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:#96969640;--xy-minimap-background-color-default:#141414;--xy-minimap-mask-background-color-default:#3c3c3c99;--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:#555;--xy-background-pattern-lines-color-default:#333;--xy-background-pattern-cross-color-default:#333;--xy-node-color-default:#f8f8f8;--xy-node-border-default:1px solid #3c3c3c;--xy-node-background-color-default:#1e1e1e;--xy-node-group-background-color-default:#f0f0f040;--xy-node-boxshadow-hover-default:0 1px 4px 1px #ffffff14;--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:#c8c8dc14;--xy-selection-border-default:1px dotted #c8c8dccc;--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 #00000014;--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{width:100%;height:100%;position:absolute;top:0;left:0}.react-flow__pane{z-index:1;touch-action:none}.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{pointer-events:none;position:absolute;overflow:visible}.react-flow__edge{pointer-events:visibleStroke}.react-flow__edge.selectable{cursor:pointer}.react-flow__edge.animated path{stroke-dasharray:5;animation:.5s linear infinite dashdraw}.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;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:.5s linear infinite dashdraw}svg.react-flow__connectionline{z-index:1001;position:absolute;overflow:visible}.react-flow__nodes{pointer-events:none;transform-origin:0 0}.react-flow__node{-webkit-user-select:none;user-select:none;pointer-events:all;transform-origin:0 0;box-sizing:border-box;cursor:default;position:absolute}.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:0 0;pointer-events:none}.react-flow__nodesselection-rect{pointer-events:all;cursor:grab;position:absolute}.react-flow__handle{pointer-events:none;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%;width:6px;min-width:5px;height:6px;min-height:5px;position:absolute}.react-flow__handle.connectingfrom{pointer-events:all}.react-flow__handle.connectionindicator{pointer-events:all;cursor:crosshair}.react-flow__handle-bottom{top:auto;bottom:0;left:50%;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{z-index:5;margin:15px;position:absolute}.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{background:var(--xy-attribution-background-color,var(--xy-attribution-background-color-default));margin:0;padding:2px 3px;font-size:10px}.react-flow__attribution a{color:#999;text-decoration:none}@keyframes dashdraw{0%{stroke-dashoffset:10px}}.react-flow__edgelabel-renderer{pointer-events:none;-webkit-user-select:none;user-select:none;width:100%;height:100%;position:absolute;top:0;left:0}.react-flow__viewport-portal{-webkit-user-select:none;user-select:none;width:100%;height:100%;position:absolute;top:0;left:0}.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{box-shadow:var(--xy-controls-box-shadow,var(--xy-controls-box-shadow-default));flex-direction:column;display:flex}.react-flow__controls.horizontal{flex-direction:row}.react-flow__controls-button{background:var(--xy-controls-button-background-color,var(--xy-controls-button-background-color-default));border:none;border-bottom:1px solid var(--xy-controls-button-border-color-props,var(--xy-controls-button-border-color,var(--xy-controls-button-border-color-default)));width:26px;height:26px;color:var(--xy-controls-button-color-props,var(--xy-controls-button-color,var(--xy-controls-button-color-default)));cursor:pointer;-webkit-user-select:none;user-select:none;justify-content:center;align-items:center;padding:4px;display:flex}.react-flow__controls-button svg{fill:currentColor;width:100%;max-width:12px;max-height:12px}.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{border-radius:var(--xy-node-border-radius,var(--xy-node-border-radius-default));width:150px;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));padding:10px;font-size:12px}.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{background-color:var(--xy-resize-background-color,var(--xy-resize-background-color-default));border:1px solid #fff;border-radius:1px;width:5px;height:5px;translate:-50% -50%}.react-flow__resize-control.handle.left{top:50%;left:0}.react-flow__resize-control.handle.right{top:50%;left:100%}.react-flow__resize-control.handle.top{top:0;left:50%}.react-flow__resize-control.handle.bottom{top:100%;left:50%}.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-style:solid;border-width:0}.react-flow__resize-control.line.left,.react-flow__resize-control.line.right{width:1px;height:100%;top:0;transform:translate(-50%)}.react-flow__resize-control.line.left{border-left-width:1px;left:0}.react-flow__resize-control.line.right{border-right-width:1px;left:100%}.react-flow__resize-control.line.top,.react-flow__resize-control.line.bottom{width:100%;height:1px;left:0;transform:translateY(-50%)}.react-flow__resize-control.line.top{border-top-width:1px;top:0}.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))}@font-face{font-family:Kode Mono;src:url(./KodeMono-Regular-Bdr_-rJX.woff2)format("woff2");font-weight:400;size-adjust:90%}@font-face{font-family:Kode Mono;src:url(./KodeMono-Medium-CVnTuv5A.ttf)format("truetype");font-weight:500;size-adjust:90%}@font-face{font-family:Kode Mono;src:url(./KodeMono-SemiBold-JAfn5Dpm.ttf)format("truetype");font-weight:600;size-adjust:90%}@font-face{font-family:Kode Mono;src:url(./KodeMono-Bold-DdIivhPN.woff2)format("woff2");font-weight:700;size-adjust:90%}@font-face{font-family:Kode Mono Bold;src:url(./KodeMono-Bold-DdIivhPN.woff2)format("woff2");font-weight:100 900;size-adjust:90%}:where(:root){--uhd-background:oklch(21.78% 0 0);--uhd-canvas:oklch(21.78% 0 0);--uhd-canvas-dot:#2e2e2e;--uhd-surface:oklch(25.1% 0 0);--uhd-surface-raised:oklch(24.35% 0 0);--uhd-surface-sunken:#191919;--uhd-overlay:#1f1f1fee;--uhd-scrim:#0d0d0dcc;--uhd-muted:oklch(28.5% 0 0);--uhd-hover:var(--uhd-text)}@supports (color:color-mix(in lab, red, red)){:where(:root){--uhd-hover:color-mix(in oklab, var(--uhd-text) 6%, transparent)}}:where(:root){--uhd-active:oklch(37.15% 0 0);--uhd-node:#2f2f2f;--uhd-node-selected:#1f1f1f;--uhd-group:#94a3b808;--uhd-preview:#fff;--uhd-drawing:#141414;--uhd-text:oklch(88.53% 0 0);--uhd-text-muted:oklch(68% 0 0);--uhd-text-faint:#6b6560;--uhd-text-on-accent:oklch(98% 0 0);--uhd-text-link:var(--uhd-accent);--uhd-border:oklch(32.9% 0 0);--uhd-border-subtle:#2a2a2a;--uhd-border-strong:#57534e;--uhd-node-border:#44403c;--uhd-node-border-hover:#d6d3d1;--uhd-group-border:#6b7280;--uhd-contrast-border:transparent;--uhd-contrast-active-border:transparent;--uhd-accent:oklch(68% .15 245);--uhd-accent-hover:var(--uhd-accent)}@supports (color:color-mix(in lab, red, red)){:where(:root){--uhd-accent-hover:color-mix(in oklab, var(--uhd-accent) 88%, var(--uhd-text))}}:where(:root){--uhd-accent-tint:var(--uhd-accent)}@supports (color:color-mix(in lab, red, red)){:where(:root){--uhd-accent-tint:color-mix(in oklab, var(--uhd-accent) 15%, transparent)}}:where(:root){--uhd-accent-glow:var(--uhd-accent)}@supports (color:color-mix(in lab, red, red)){:where(:root){--uhd-accent-glow:color-mix(in oklab, var(--uhd-accent) 25%, transparent)}}:where(:root){--uhd-highlight:#22d3ee;--uhd-focus-ring:var(--uhd-accent);--uhd-selection:var(--uhd-accent)}@supports (color:color-mix(in lab, red, red)){:where(:root){--uhd-selection:color-mix(in oklab, var(--uhd-accent) 15%, transparent)}}:where(:root){--uhd-selection-text:var(--uhd-text);--uhd-domain-electrical:#f5a524;--uhd-domain-mechanical:#94a3b8;--uhd-domain-pneumatic:#22d3ee;--uhd-domain-hydraulic:#6366f1;--uhd-domain-thermal:#f43f5e;--uhd-domain-network:#a78bfa;--uhd-domain-software:#34d399;--uhd-domain-other:#3a3a3a;--uhd-signal-power:#f97316;--uhd-signal-ground:#78716c;--uhd-signal-digital:#38bdf8;--uhd-signal-analog:#a3e635;--uhd-signal-i2c:#a78bfa;--uhd-signal-spi:#f472b6;--uhd-signal-uart:#2dd4bf;--uhd-signal-can:#facc15;--uhd-signal-pwm:#fde68a;--uhd-signal-phase:#e11d48;--uhd-signal-rf:#e879f9;--uhd-signal-other:#8b8680;--uhd-drc-configured:#22c55e;--uhd-drc-partial:#eed202;--uhd-drc-incompatible:#ef4444;--uhd-drc-unconfigured:#6e7681;--uhd-severity-error:#ef4444;--uhd-severity-warning:#eed202;--uhd-severity-info:#38bdf8;--uhd-severity-ok:#22c55e;--uhd-scrollbar-thumb:var(--uhd-text)}@supports (color:color-mix(in lab, red, red)){:where(:root){--uhd-scrollbar-thumb:color-mix(in oklab, var(--uhd-text) 22%, transparent)}}:where(:root){--uhd-scrollbar-thumb-hover:var(--uhd-text)}@supports (color:color-mix(in lab, red, red)){:where(:root){--uhd-scrollbar-thumb-hover:color-mix(in oklab, var(--uhd-text) 38%, transparent)}}:where(:root){--uhd-scene-background:#1a1a1a;--uhd-scene-grid:#3a3a3a;--uhd-scene-grid-minor:#262626;--uhd-radius:8px;--uhd-shadow-sm:0px 2px 0px 0px #33333326, 0px 1px 2px -1px #33333326;--uhd-shadow-md:0px 2px 0px 0px #00000059, 0px 2px 4px -1px #00000059;--uhd-shadow-lg:0px 2px 0px 0px #00000059, 0px 4px 6px -1px #00000059;--uhd-font-ui:"Kode Mono", ui-monospace, monospace;--uhd-font-label:"Kode Mono Bold", "Kode Mono", ui-monospace, monospace;--uhd-font-mono:ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace}}@layer components{:where(.uhd-root){background:var(--uhd-background);height:100%;color:var(--uhd-text);font-family:var(--uhd-font-ui);-webkit-font-smoothing:antialiased;font-size:12px;position:relative}:where(.uhd-root),:where(.uhd-root) *,:where(.uhd-root) :before,:where(.uhd-root) :after{box-sizing:border-box}:where(.uhd-root) button{color:inherit;cursor:pointer;background:0 0;border:none;font-family:inherit}:where(.uhd-root) button:disabled{cursor:default}:where(.uhd-root) :focus-visible{outline:1px solid var(--uhd-focus-ring);outline-offset:-1px}.app{flex-direction:column;height:100%;display:flex}.workspace{flex:1;min-height:0;display:flex}.canvas{flex:1;min-width:0;position:relative}.header{background:var(--uhd-surface);border-bottom:1px solid var(--uhd-border);align-items:center;gap:18px;height:44px;padding:0 14px;display:flex}.brand{font-family:var(--uhd-font-label);letter-spacing:1px;align-items:center;gap:8px;display:flex}.breadcrumb{flex:1;align-items:center;gap:4px;min-width:0;display:flex}.crumb-wrap{align-items:center;gap:4px;display:flex}.crumb{font-family:var(--uhd-font-label);letter-spacing:.6px;color:var(--uhd-text-muted);border-radius:4px;padding:4px 6px;font-size:11px}.crumb:hover{color:var(--uhd-text);background:var(--uhd-text)}@supports (color:color-mix(in lab, red, red)){.crumb:hover{background:color-mix(in oklab, var(--uhd-text) 4%, transparent)}}.crumb.current{color:var(--uhd-text)}.crumb-sep{color:var(--uhd-text-faint)}.header-controls{align-items:center;gap:10px;display:flex}.segmented{border:1px solid var(--uhd-border);border-radius:6px;display:flex;overflow:hidden}.segmented button,.chip-toggle{letter-spacing:.5px;color:var(--uhd-text-faint);background:var(--uhd-surface-sunken);padding:5px 9px;font-size:9.5px}.segmented button.on{color:var(--uhd-text);background:var(--uhd-node)}.chip-toggle{border:1px solid var(--uhd-border);border-radius:6px}.chip-toggle.on{color:var(--uhd-text);background:var(--uhd-node)}.activity-bar{background:var(--uhd-surface);border-right:1px solid var(--uhd-border);flex-direction:column;align-items:center;gap:6px;width:44px;padding-top:10px;display:flex}.activity{width:32px;height:32px;color:var(--uhd-text-faint);border-radius:7px;place-items:center;display:grid}.activity:not(:disabled):hover{color:var(--uhd-text);background:var(--uhd-text)}@supports (color:color-mix(in lab, red, red)){.activity:not(:disabled):hover{background:color-mix(in oklab, var(--uhd-text) 5%, transparent)}.activity.on{background:color-mix(in oklab, var(--uhd-accent) 8%, transparent)}}.inspector{background:var(--uhd-surface);border-left:1px solid var(--uhd-border);flex-direction:column;width:320px;min-height:0;display:flex}.inspector-header{font-family:var(--uhd-font-label);letter-spacing:1px;border-bottom:1px solid var(--uhd-border);justify-content:space-between;align-items:center;padding:12px 14px;font-size:12px;display:flex}.inspector-scroll{flex:1;min-height:0}.mini{letter-spacing:.5px;color:var(--uhd-text-muted);border:1px solid var(--uhd-border);border-radius:4px;padding:2px 6px;font-size:9px}.mini:hover{color:var(--uhd-text)}.section-title{letter-spacing:.9px;color:var(--uhd-text-faint);justify-content:space-between;align-items:center;padding:14px 14px 6px;font-size:9.5px;display:flex}.tree-item{width:100%;color:var(--uhd-text-muted);text-align:left;align-items:center;gap:8px;padding:5px 14px;font-size:10.5px;display:flex}.tree-item:hover{background:var(--uhd-text)}@supports (color:color-mix(in lab, red, red)){.tree-item:hover{background:color-mix(in oklab, var(--uhd-text) 3%, transparent)}}.tree-item:hover{color:var(--uhd-text)}.tree-item.on{background:var(--uhd-accent)}@supports (color:color-mix(in lab, red, red)){.tree-item.on{background:color-mix(in oklab, var(--uhd-accent) 8%, transparent)}}.tree-item.on{color:var(--uhd-text)}.tree-tag{color:var(--uhd-text-faint);letter-spacing:.4px;margin-left:auto;font-size:8.5px}.state-dot{border-radius:50%;flex:none;width:7px;height:7px}.state-dot.configured{background:var(--uhd-drc-configured)}.state-dot.partial{background:var(--uhd-drc-partial)}.state-dot.incompatible{background:var(--uhd-drc-incompatible)}.state-dot.unconfigured{background:var(--uhd-drc-unconfigured)}.details{padding:8px 0}.details-title{font-family:var(--uhd-font-label);letter-spacing:.6px;align-items:center;gap:8px;padding:6px 14px 12px;font-size:13px;display:flex}.kv{justify-content:space-between;gap:12px;padding:3px 14px;font-size:10.5px;display:flex}.kv .k{color:var(--uhd-text-faint);letter-spacing:.6px}.kv .v{color:var(--uhd-text);text-align:right;word-break:break-all}.uhd-selection-details{container:uhd-details/inline-size}.uhd-selection-details .kv .v{word-break:normal;overflow-wrap:anywhere}@container uhd-details not (width>=248px){.kv{flex-direction:column;gap:1px}.kv .v{text-align:left}}.description{color:var(--uhd-text-muted);margin:0;padding:6px 14px 0;font-size:10.5px;line-height:1.5}.actions{gap:8px;padding:12px 14px 0;display:flex}.actions button{letter-spacing:.5px;border:1px solid var(--uhd-border);color:var(--uhd-text-muted);border-radius:6px;flex:1;padding:6px 0;font-size:9.5px}.actions button:hover{color:var(--uhd-text);border-color:var(--uhd-accent)}.port-list{padding:0 8px}.port-row{align-items:center;gap:8px;padding:4px 6px;font-size:10px;display:flex}.swatch{border-radius:2px;flex:none;width:8px;height:8px}.port-name{color:var(--uhd-text)}.port-proto{color:var(--uhd-text-faint)}.port-linked{color:var(--uhd-text-muted);margin-left:auto;font-size:9.5px}.child-table{border-collapse:collapse;width:calc(100% - 28px);margin:0 14px;font-size:10.5px}.child-table td{border-bottom:1px solid var(--uhd-border-subtle);padding:4px}.child-table .muted,.muted{color:var(--uhd-text-faint)}.diagnostic{color:var(--uhd-drc-partial);margin:0;padding:3px 14px;font-size:10.5px}.toolbar{background:var(--uhd-overlay);border:1px solid var(--uhd-border);z-index:10;border-radius:10px;gap:2px;padding:4px;display:flex;position:absolute;bottom:16px;left:50%;transform:translate(-50%)}.legend{z-index:10;background:var(--uhd-overlay);border:1px solid var(--uhd-border);border-radius:8px;flex-direction:column;gap:6px;padding:10px 12px;display:flex;position:absolute;bottom:16px;right:14px}.legend-title{font-family:var(--uhd-font-label);letter-spacing:.8px;color:var(--uhd-text-muted);margin-bottom:2px;font-size:10px}.legend-item{color:var(--uhd-text-muted);align-items:center;gap:8px;font-size:9.5px;display:flex}.legend-swatch{border-radius:2px;width:16px;height:3px}.react-flow__node{font-family:var(--uhd-font-ui)}.canvas-empty{z-index:4;padding:calc(var(--uhd-inset-top,0px) + 16px) 24px 72px;text-align:center;font:12px/1.5 var(--uhd-font-ui);color:var(--uhd-text-muted);pointer-events:none;flex-direction:column;justify-content:center;align-items:center;gap:6px;display:flex;position:absolute;inset:0}.canvas-empty.covered-right{padding-right:min(396px,50%)}.canvas-empty>*{max-width:min(420px,100%);margin:0}.canvas-empty-title{color:var(--uhd-text);font-size:13px}.react-flow__node{transition:opacity .15s}.react-flow__node.isolated-out{opacity:.22}[data-uhd-scheme^=high-contrast] .react-flow__node.isolated-out{opacity:.35}@media (prefers-reduced-motion:reduce){.react-flow__node{transition:none}}.module-card{background:var(--uhd-node);border:2px solid var(--uhd-node-border);box-shadow:var(--uhd-shadow-md);color:var(--uhd-text);border-radius:10px;transition:border-color .12s;position:relative}.module-card:hover{border-color:var(--uhd-node-border-hover)}.module-card.selected{background:var(--uhd-node-selected);border-color:var(--uhd-accent);box-shadow:0 0 0 1px var(--uhd-accent), 0 0 14px var(--uhd-accent)}@supports (color:color-mix(in lab, red, red)){.module-card.selected{box-shadow:0 0 0 1px color-mix(in oklab, var(--uhd-accent) 20%, transparent), 0 0 14px color-mix(in oklab, var(--uhd-accent) 25%, transparent)}}.module-card.circle{border-radius:50%}.module-body{pointer-events:none;flex-direction:column;justify-content:center;align-items:center;gap:7px;padding:0 34px;display:flex;position:absolute;inset:0}.module-card.circle .module-body{gap:4px;padding:0 8px}.module-title{font-family:var(--uhd-font-label);letter-spacing:.4px;text-align:center;font-size:10.5px;line-height:1.25}.module-card.circle .module-title{font-size:8px}.status-dot{border-radius:50%;width:7px;height:7px;position:absolute;top:7px;right:8px}.status-dot.mark{pointer-events:auto;--mark:var(--uhd-mark-neutral,var(--uhd-text-faint));background:var(--mark);outline:1px solid var(--uhd-contrast-border,transparent);outline-offset:1px;width:9px;height:9px;top:6px;right:7px}.status-dot.mark[data-tone=info]{--mark:var(--uhd-mark-info,var(--uhd-severity-info))}.status-dot.mark[data-tone=ok]{--mark:var(--uhd-mark-ok,var(--uhd-severity-ok))}.status-dot.mark[data-tone=warning]{--mark:var(--uhd-mark-warning,var(--uhd-severity-warning))}.status-dot.mark[data-tone=error]{--mark:var(--uhd-mark-error,var(--uhd-severity-error))}.status-dot.mark[data-shape=ring]{border:1.5px dashed var(--mark);background:0 0;outline:none;width:11px;height:11px;top:5px;right:6px}.module-card.circle .status-dot{top:10%;right:14%}.port-groups{pointer-events:none;flex-wrap:wrap;justify-content:center;gap:3px;max-width:100%;display:flex}.port-group{letter-spacing:.3px;color:var(--uhd-text-muted);background:var(--uhd-node);border:1px solid;border-radius:7px;padding:1px 5px;font-size:7.5px}.port-group.muted{border-color:var(--uhd-border)}.module-container{background:var(--uhd-node);border-radius:12px}@supports (color:color-mix(in lab, red, red)){.module-container{background:color-mix(in oklab, var(--uhd-node) 25%, transparent)}}.module-container{border:2px solid var(--uhd-node-border)}.module-container.is-group{background:var(--uhd-group);border:1.5px dashed var(--uhd-group-border);border-radius:6px}.module-container.selected{border-color:var(--uhd-accent)}.container-label{font-family:var(--uhd-font-label);letter-spacing:.5px;color:var(--uhd-text);pointer-events:none;align-items:center;gap:6px;font-size:9.5px;display:flex;position:absolute;top:8px;left:10px}.container-kind{font-family:var(--uhd-font-ui);color:var(--uhd-text-faint);border:1px solid var(--uhd-border);border-radius:4px;padding:0 4px;font-size:7.5px}.sheet-port{background:var(--uhd-surface);font-family:var(--uhd-font-label);letter-spacing:.4px;border:1px solid;border-radius:5px;align-items:center;gap:6px;padding:0 10px;font-size:9.5px;display:flex;position:relative}.sheet-port.selected{box-shadow:0 0 10px var(--uhd-accent)}@supports (color:color-mix(in lab, red, red)){.sheet-port.selected{box-shadow:0 0 10px color-mix(in oklab, var(--uhd-accent) 25%, transparent)}}.react-flow__handle.port{border:2px solid var(--uhd-canvas);place-items:center;min-width:0;min-height:0;display:grid;position:absolute;transform:translate(-50%,-50%)}.react-flow__handle.port-exported{border-width:2px}.port-core{width:4px;height:4px}.react-flow__handle.port-selected{box-shadow:0 0 0 2px var(--uhd-accent)}.react-flow__handle.port-target{opacity:0;pointer-events:none;width:1px;min-width:0;height:1px;min-height:0;position:absolute;transform:translate(-50%,-50%)}.port-label{letter-spacing:.3px;color:var(--uhd-text-muted);white-space:nowrap;pointer-events:none;text-overflow:ellipsis;max-width:76px;font-size:8px;position:absolute;overflow:hidden}.ground-glyph{pointer-events:none;position:absolute;overflow:visible}.edge-glow{fill:none;stroke-opacity:.22;filter:blur(3px)}.link-label{background:var(--uhd-canvas);letter-spacing:.4px;pointer-events:all;cursor:pointer;white-space:nowrap;border:1px solid;border-radius:4px;flex-wrap:wrap;align-items:center;gap:5px;max-width:170px;padding:2px 6px;font-size:8.5px;display:flex;position:absolute}.link-label.selected{box-shadow:0 0 8px}.link-count{color:var(--uhd-text-muted)}.link-toggle{border:1px solid;border-radius:50%;place-items:center;width:14px;height:14px;padding:0;display:grid}.child-links{border-top:1px solid var(--uhd-text);flex-direction:column;flex-basis:100%;gap:1px;padding:2px 0 1px;display:flex}@supports (color:color-mix(in lab, red, red)){.child-links{border-top:1px solid color-mix(in oklab, var(--uhd-text) 8%, transparent)}}.child-link{justify-content:space-between;gap:10px;display:flex}.child-name{color:var(--uhd-text)}.child-pins{color:var(--uhd-text-muted)}.react-flow__edge.selected .react-flow__edge-path{filter:none}.react-flow__edgelabel-renderer{z-index:1001!important}.harness-node{background:var(--uhd-canvas);font-family:var(--uhd-font-label);letter-spacing:.4px;color:var(--uhd-text);border:1.5px solid;border-radius:18px;justify-content:center;align-items:center;gap:6px;padding:0 10px;font-size:8.5px;display:flex;position:relative}.harness-node.selected{box-shadow:0 0 10px var(--uhd-accent)}@supports (color:color-mix(in lab, red, red)){.harness-node.selected{box-shadow:0 0 10px color-mix(in oklab, var(--uhd-accent) 33%, transparent)}}.harness-node.selected{border-color:var(--uhd-accent)!important}.harness-name{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.harness-kind{font-family:var(--uhd-font-ui);color:var(--uhd-text-faint);font-size:6.5px}.net-node{background:var(--uhd-canvas);font-family:var(--uhd-font-label);letter-spacing:.4px;border:1.5px solid;border-radius:6px;justify-content:center;align-items:center;font-size:9.5px;display:flex;position:relative}.net-node.ground{border-style:dashed}.net-node.selected{box-shadow:0 0 10px var(--uhd-accent)}@supports (color:color-mix(in lab, red, red)){.net-node.selected{box-shadow:0 0 10px color-mix(in oklab, var(--uhd-accent) 33%, transparent)}}.net-node.selected{border-color:var(--uhd-accent)!important}.net-node .net-name{white-space:nowrap}.net-node .status-dot{position:absolute;top:-4px;right:-4px}.scenario{color:var(--uhd-text-muted);border:1px solid var(--uhd-border);background:var(--uhd-surface-sunken);border-radius:6px;align-items:center;gap:6px;padding:0 4px 0 8px;display:flex}.scenario select,.child-table select{font-family:var(--uhd-font-ui);color:var(--uhd-text);background:var(--uhd-surface-sunken);border:none;outline:none;padding:5px 2px;font-size:9.5px}.child-table select{border:1px solid var(--uhd-border);border-radius:4px}.scenario-banner{z-index:10;color:var(--uhd-text-muted);background:var(--uhd-overlay);border:1px solid var(--uhd-drc-partial);border-radius:8px;align-items:center;gap:14px;padding:7px 14px;font-size:10px;display:flex;position:absolute;top:12px;left:50%;transform:translate(-50%)}.scenario-banner.error{border-color:var(--uhd-drc-incompatible)}.scenario-banner b{color:var(--uhd-text);font-family:var(--uhd-font-label);letter-spacing:.6px;font-weight:400}.missing-notice{top:calc(var(--uhd-inset-top,0px) + 8px);left:calc(var(--uhd-inset-left,0px) + 8px);width:fit-content;max-width:min(560px, calc(100% - 16px - var(--uhd-inset-left,0px)));z-index:10;font:11px/1.45 var(--uhd-font-ui);color:var(--uhd-text-muted);background:var(--uhd-surface);border:1px solid var(--uhd-drc-partial);border-radius:var(--uhd-radius,8px);box-shadow:var(--uhd-shadow-md);align-items:flex-start;gap:8px;margin-inline:auto;padding:7px 8px 7px 10px;display:flex;position:absolute;right:8px}.missing-notice.below-banner{top:calc(var(--uhd-inset-top,0px) + 48px)}.missing-notice-icon{color:var(--uhd-drc-partial);flex:none;margin-top:2px}.missing-notice-text{overflow-wrap:anywhere;min-width:0}.missing-notice b{color:var(--uhd-text);font-weight:600}.missing-notice-ids{font-family:var(--uhd-font-mono,var(--uhd-font-label))}.missing-notice-hint{color:var(--uhd-text);margin-top:3px}.missing-notice-hint .cmd{font-family:var(--uhd-font-mono,var(--uhd-font-label));-webkit-user-select:all;user-select:all}.module-card.missing{background:var(--uhd-node);border-style:dashed}@supports (color:color-mix(in lab, red, red)){.module-card.missing{background:color-mix(in oklab, var(--uhd-node) 70%, transparent)}}.module-missing{font:9px/1.2 var(--uhd-font-ui);color:var(--uhd-text-muted);text-align:center}.activity{position:relative}.badge{background:var(--uhd-drc-incompatible);color:#fff;border-radius:7px;min-width:14px;height:14px;padding:0 3px;font-size:8.5px;line-height:14px;position:absolute;top:2px;right:1px}.section-actions{gap:6px;display:flex}.mini.on{color:var(--uhd-text);border-color:var(--uhd-accent)}.checks{flex-direction:column;gap:6px;padding:8px 10px;display:flex}.check-summary{letter-spacing:.5px;gap:10px;padding:2px 4px 6px;font-size:9px;display:flex}.sev.error{color:var(--uhd-drc-incompatible)}.sev.warning{color:var(--uhd-drc-partial)}.sev.info{color:var(--uhd-text-muted)}.check{text-align:left;border:1px solid var(--uhd-border-subtle);background:var(--uhd-surface-sunken);border-left-width:3px;border-radius:6px;align-items:flex-start;gap:8px;padding:8px 9px;display:flex}.check:hover{background:var(--uhd-hover)}.check.error{border-left-color:var(--uhd-drc-incompatible);color:var(--uhd-drc-incompatible)}.check.warning{border-left-color:var(--uhd-drc-partial);color:var(--uhd-drc-partial)}.check.info{border-left-color:var(--uhd-border);color:var(--uhd-text-muted)}.check-body{flex-direction:column;gap:3px;display:flex}.check-rule{letter-spacing:.6px;font-size:8.5px}.check-msg{color:var(--uhd-text);font-size:10px;line-height:1.45}.diagnostic.incompatible{color:var(--uhd-drc-incompatible)}.manual-tag{color:var(--uhd-accent);align-items:center;gap:3px;margin-left:8px;display:inline-flex}.evidence{flex-direction:column;gap:10px;padding:0 14px;display:flex}.audit{letter-spacing:.4px;background:var(--uhd-drc-configured);border-radius:6px;flex-wrap:wrap;align-items:center;gap:4px 7px;padding:6px 8px;font-size:10px;display:flex}@supports (color:color-mix(in lab, red, red)){.audit{background:color-mix(in oklab, var(--uhd-drc-configured) 8%, transparent)}}.audit{color:var(--uhd-drc-configured)}.audit.repaired{background:var(--uhd-drc-partial)}@supports (color:color-mix(in lab, red, red)){.audit.repaired{background:color-mix(in oklab, var(--uhd-drc-partial) 6%, transparent)}}.audit.repaired{color:var(--uhd-drc-partial)}.audit.pending{background:var(--uhd-text)}@supports (color:color-mix(in lab, red, red)){.audit.pending{background:color-mix(in oklab, var(--uhd-text) 3%, transparent)}}.audit.pending{color:var(--uhd-text-muted)}.facts .kv{padding:2px 0}.facts-title{letter-spacing:.7px;color:var(--uhd-text-faint);margin-bottom:3px;font-size:9px}.facts-title.warn{color:var(--uhd-drc-partial)}.note{color:var(--uhd-text-muted);margin:2px 0;font-size:10px;line-height:1.45}.note b{color:var(--uhd-text);font-weight:400}.source{color:var(--uhd-text-muted);align-items:baseline;gap:7px;padding:3px 0;font-size:10px;text-decoration:none;display:flex}.source:hover{color:var(--uhd-text)}.authority{border:1px solid var(--uhd-border);color:var(--uhd-text-faint);border-radius:3px;flex:none;padding:1px 4px;font-size:7.5px}.authority.manufacturer{border-color:var(--uhd-drc-configured);color:var(--uhd-drc-configured)}.pair-overlay{z-index:20;background:var(--uhd-scrim);place-items:center;padding:24px;display:grid;position:absolute;inset:0}.pair-view{background:var(--uhd-surface);border:1px solid var(--uhd-border);border-radius:12px;flex-direction:column;width:min(980px,100%);max-height:100%;display:flex;overflow:hidden}.pair-scroll{flex:auto;min-height:0}.pair-content{padding:18px 22px 20px}.pair-header{align-items:center;gap:14px;margin-bottom:14px;display:flex}.pair-title{font-family:var(--uhd-font-label);letter-spacing:1px;font-size:13px}.pair-sub{color:var(--uhd-text-muted);flex:1;font-size:10.5px}.pair-grid{position:relative}.pair-col{background:var(--uhd-node);border:1.5px solid var(--uhd-node-border);border-radius:10px;width:38%;position:absolute;top:0;bottom:0}.pair-col.left{left:0}.pair-col.right{right:0}.pair-col-title{font-family:var(--uhd-font-label);letter-spacing:.5px;align-items:center;gap:7px;padding:10px 14px;font-size:10.5px;display:flex}.pair-wires{pointer-events:none;z-index:2;position:absolute;inset:0}.pair-region{background:var(--uhd-text);border:1px solid;border-radius:8px;position:absolute;left:1.5%;right:1.5%}@supports (color:color-mix(in lab, red, red)){.pair-region{background:color-mix(in oklab, var(--uhd-text) 2%, transparent)}}.pair-region{z-index:1}.pair-pill{letter-spacing:.4px;background:var(--uhd-surface);white-space:nowrap;border:1px solid;border-radius:999px;align-items:center;gap:5px;padding:1px 8px;font-size:8.5px;display:inline-flex;position:absolute;top:-9px;left:50%;transform:translate(-50%)}.pair-row{padding:0 12px;font-size:10px;line-height:16px;position:absolute;top:8px}.pair-row.head{font-family:var(--uhd-font-label);color:var(--uhd-text);font-size:10.5px}.pair-row:not(.head){margin-top:0}.pair-row.left{width:36%;padding-left:22px;left:0}.pair-row.right{text-align:right;width:36%;padding-right:22px;right:0}.pair-row.head.left{padding-left:12px}.pair-row.head.right{padding-right:12px}.pair-census{grid-template-columns:1fr 1fr;gap:18px;margin-top:8px;display:grid}.pair-census .section-title{padding:10px 0 6px}.census-list{color:var(--uhd-text-muted);flex-wrap:wrap;gap:4px 12px;font-size:9.5px;display:flex}.pair-verdict{border-left:3px solid var(--uhd-drc-configured);background:var(--uhd-surface-sunken);letter-spacing:.5px;margin-top:14px;padding:7px 12px;font-size:10.5px}.pair-verdict.partial{border-left-color:var(--uhd-drc-partial)}.pair-verdict.incompatible{border-left-color:var(--uhd-drc-incompatible)}.audit .muted{flex-basis:100%;padding-left:20px;font-size:9px}.cad-view{flex:1;min-width:0;min-height:0;display:flex}.cad-canvas{flex:1;min-width:0;position:relative;overflow:hidden}.cad-canvas canvas{display:block}.cad-slider{font:500 10px var(--uhd-font-ui);color:var(--uhd-text-muted);background:var(--uhd-surface);border:1px solid var(--uhd-border);border-radius:4px;align-items:center;gap:6px;padding:4px 8px;display:flex}.cad-slider input{width:110px;accent-color:var(--uhd-accent)}.cad-loading{color:var(--uhd-text-muted);font:12px var(--uhd-font-ui);place-items:center;display:grid;position:absolute;inset:0}.cad-scope{top:calc(var(--uhd-inset-top,0px) + 10px);left:calc(var(--uhd-inset-left,0px) + 10px);z-index:2;background:var(--uhd-surface);border:1px solid var(--uhd-border);border-radius:var(--uhd-radius);max-width:min(46%,320px);box-shadow:var(--uhd-shadow-md);outline:1px solid var(--uhd-contrast-border,transparent);outline-offset:-1px;font:11px/1.4 var(--uhd-font-ui);color:var(--uhd-text-muted);flex-direction:column;gap:2px;padding:6px 10px;display:flex;position:absolute}.cad-scope-name{font-family:var(--uhd-font-label);letter-spacing:.6px;text-transform:uppercase;color:var(--uhd-text);text-overflow:ellipsis;white-space:nowrap;font-size:10.5px;overflow:hidden}.cad-scope-what{text-overflow:ellipsis;-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.cad-empty{z-index:2;padding:calc(var(--uhd-inset-top,0px) + 16px) 24px 72px;text-align:center;font:12px/1.5 var(--uhd-font-ui);color:var(--uhd-text-muted);pointer-events:none;flex-direction:column;justify-content:center;align-items:center;gap:8px;display:flex;position:absolute;inset:0}.cad-empty>*{max-width:min(440px,100%);margin:0}.cad-empty-title{color:var(--uhd-text);font-size:13px}.cad-empty-how{pointer-events:auto}.cad-empty-how>summary{cursor:pointer;color:var(--uhd-text-muted);text-underline-offset:3px;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;list-style:none}.cad-empty-how>summary::-webkit-details-marker{display:none}.cad-empty-how>summary:hover{color:var(--uhd-text)}.cad-empty-how>p{margin:6px 0 0}.cad-empty code,.cad-empty .cmd{font-family:var(--uhd-font-mono);color:var(--uhd-text);-webkit-user-select:text;user-select:text;pointer-events:auto;font-size:11.5px}.cad-notes{background:var(--uhd-overlay);border:1px solid var(--uhd-border);border-left:2px solid var(--uhd-accent);max-width:62%;font:11px/1.5 var(--uhd-font-ui);color:var(--uhd-text-muted);z-index:2;padding:8px 10px;position:absolute;bottom:12px;left:12px}.cad-title{font:600 13px var(--uhd-font-ui);color:var(--uhd-text);margin:4px 0 2px}.cad-sub{font:11px/1.5 var(--uhd-font-ui);color:var(--uhd-text-muted);margin-bottom:4px}.cad-rows{flex-direction:column;gap:2px;margin-bottom:8px;display:flex}.cad-row{color:var(--uhd-text);font:11px var(--uhd-font-ui);cursor:pointer;text-align:left;background:0 0;border:1px solid #0000;border-radius:3px;justify-content:space-between;align-items:center;gap:8px;padding:4px 6px;display:flex}.cad-row:hover{background:var(--uhd-hover)}.cad-row.on{border-color:var(--uhd-accent);background:var(--uhd-accent-tint)}.cad-row-name{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.cad-row-via{color:var(--uhd-text-faint);font-size:10px}.gchips{flex-shrink:0;gap:3px;display:flex}.gchip{font:600 9px var(--uhd-font-ui);border:1px solid var(--uhd-border);color:var(--uhd-text-faint);letter-spacing:.03em;border-radius:2px;padding:1px 4px}.gchip.bound,.gchip.ok{color:var(--uhd-drc-configured);border-color:var(--uhd-drc-configured)}@supports (color:color-mix(in lab, red, red)){.gchip.bound,.gchip.ok{border-color:color-mix(in srgb, var(--uhd-drc-configured) 50%, transparent)}}.gchip.stale,.gchip.missing{color:var(--uhd-drc-incompatible);border-color:var(--uhd-drc-incompatible)}.gchip.unchecked{color:var(--uhd-drc-partial);border-color:var(--uhd-drc-partial)}@supports (color:color-mix(in lab, red, red)){.gchip.unchecked{border-color:color-mix(in srgb, var(--uhd-drc-partial) 50%, transparent)}}.gchip.via{color:var(--uhd-signal-digital);border-color:var(--uhd-signal-digital)}@supports (color:color-mix(in lab, red, red)){.gchip.via{border-color:color-mix(in srgb, var(--uhd-signal-digital) 50%, transparent)}}.gchip.unmapped{color:var(--uhd-text-faint);border-style:dashed}.gchip.logical{color:var(--uhd-domain-network);border-color:var(--uhd-domain-network)}@supports (color:color-mix(in lab, red, red)){.gchip.logical{border-color:color-mix(in srgb, var(--uhd-domain-network) 50%, transparent)}}.gchip.role-body{color:var(--uhd-domain-mechanical)}.gchip.role-interface{color:var(--uhd-accent);border-color:var(--uhd-accent)}@supports (color:color-mix(in lab, red, red)){.gchip.role-interface{border-color:color-mix(in srgb, var(--uhd-accent) 50%, transparent)}}.gchip.role-source{color:var(--uhd-domain-software)}.cad-detail{border-top:1px solid var(--uhd-border);margin-bottom:8px;padding-top:6px}.kv-grid{font:11px var(--uhd-font-ui);grid-template-columns:70px 1fr;gap:2px 8px;margin:4px 0 8px;display:grid}.kv-grid .k{color:var(--uhd-text-faint)}.kv-grid .v{color:var(--uhd-text)}.cad-dir{border-left:2px solid var(--uhd-border);margin:3px 0;padding:5px 6px}.cad-dir.on{border-left-color:var(--uhd-accent);background:var(--uhd-accent-tint)}.cad-dir-label{font:600 10px var(--uhd-font-ui);color:var(--uhd-text-muted);margin-bottom:3px;display:block}.cad-dir-none{color:var(--uhd-text-faint);font-size:11px}.cad-ref{font:11px var(--uhd-font-ui);flex-wrap:wrap;align-items:center;gap:4px 6px;margin:2px 0;display:flex}.cad-ref code{color:var(--uhd-text);font:11px var(--uhd-font-ui)}.cad-sig{color:var(--uhd-text-faint);flex-basis:100%;font-size:10px}.cad-issue{font:11px/1.5 var(--uhd-font-ui);color:var(--uhd-text-muted);margin:3px 0}.cad-issue.error{color:var(--uhd-drc-incompatible)}.cad-issue.warning{color:var(--uhd-drc-partial)}.cad-artifacts{flex-direction:column;gap:3px;display:flex}.cad-artifact{font:11px var(--uhd-font-ui);color:var(--uhd-text);align-items:center;gap:6px;display:flex}.cad-artifact-fmt,.cad-artifact-if{color:var(--uhd-text-faint)}.cad-end{margin:6px 0}.linklike{color:var(--uhd-accent);font:inherit;cursor:pointer;background:0 0;border:none;padding:0;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}body{letter-spacing:-.02em;background:var(--uhd-background);font-size:13px}.app{--uhd-inset-top:44px;--uhd-inset-left:44px;position:relative}.workspace{inset:0;left:var(--uhd-dock-left,0px);position:absolute}.workspace>.canvas,.workspace>.cad-view{position:absolute;inset:0}.card{background:var(--uhd-surface);border:1px solid var(--uhd-border);border-radius:var(--uhd-radius);box-shadow:var(--uhd-shadow-md)}.sep{background:var(--uhd-border);flex-shrink:0;width:1px;height:24px}.sep-h{background:var(--uhd-border);width:100%;height:1px}.header{z-index:50;background:var(--uhd-surface);border:1px solid var(--uhd-border);border-radius:var(--uhd-radius);height:40px;box-shadow:var(--uhd-shadow-md);gap:4px;padding:0 4px;position:absolute;top:4px;left:4px;right:4px}.brand{gap:6px;height:32px;padding:0 8px}.brand-mark{color:var(--uhd-accent);font-size:15px}.brand-name{color:var(--uhd-text);font-size:13px}.crumb{letter-spacing:.02em;border-radius:6px;height:32px;padding:0 8px;font-size:12px}.crumb:hover{background:var(--uhd-muted)}.header-controls{gap:4px}.segmented{border:none;border-radius:0;gap:2px;overflow:visible}.segmented button,.chip-toggle{letter-spacing:0;min-width:32px;height:32px;color:var(--uhd-text);white-space:nowrap;background:0 0;border:1px solid #0000;border-radius:6px;align-items:center;gap:6px;padding:0 10px;font-size:12px;transition:background .12s,border-color .12s,color .12s;display:inline-flex}.segmented button:hover,.chip-toggle:hover{background:var(--uhd-active);border-color:var(--uhd-border)}.segmented button.on,.chip-toggle.on{background:var(--uhd-accent);border-color:var(--uhd-accent);color:var(--uhd-text-on-accent)}.chip-toggle:disabled{opacity:.4;pointer-events:none}.scenario{height:32px;color:var(--uhd-text-muted);border-radius:6px;align-items:center;gap:6px;padding:0 8px;display:inline-flex}.scenario:hover{background:var(--uhd-muted)}.scenario select{font:12px var(--uhd-font-ui);color:var(--uhd-text);background:0 0;border:none;outline:none}.activity-bar{z-index:40;background:var(--uhd-surface);border:1px solid var(--uhd-border);border-radius:var(--uhd-radius);width:40px;box-shadow:var(--uhd-shadow-md);gap:4px;padding:4px;position:absolute;top:48px;left:4px}.activity{width:30px;height:30px;color:var(--uhd-text);border:1px solid #0000;border-radius:6px}.activity:not(:disabled):hover{background:var(--uhd-active);border-color:var(--uhd-border)}.activity.on{color:var(--uhd-text-on-accent);background:var(--uhd-accent)}.activity:disabled{opacity:.35}.inspector{top:calc(var(--uhd-inset-top,0px) + 4px);z-index:40;background:var(--uhd-surface);border:1px solid var(--uhd-border);border-radius:var(--uhd-radius);width:340px;box-shadow:var(--uhd-shadow-md);position:absolute;bottom:4px;right:4px;overflow:hidden}.inspector-header{letter-spacing:.02em;border-bottom:1px solid var(--uhd-border);padding:10px 12px;font-size:14px}.inspector-body{padding:4px 12px 16px}.section-title{font-family:var(--uhd-font-label);letter-spacing:.06em;text-transform:uppercase;color:var(--uhd-text-muted);padding:14px 0 6px;font-size:11px}.mini{letter-spacing:0;border:1px solid var(--uhd-border);height:26px;color:var(--uhd-text);border-radius:6px;padding:0 8px;font-size:11px}.mini:hover{background:var(--uhd-active)}.toolbar,.cad-toolbar{top:auto;bottom:8px;left:calc(var(--uhd-inset-left,0px) + (100% - var(--uhd-inset-left,0px) - var(--uhd-inset-right,360px)) / 2);background:var(--uhd-surface);border:1px solid var(--uhd-border);border-radius:var(--uhd-radius);height:40px;box-shadow:var(--uhd-shadow-lg);z-index:30;flex-wrap:nowrap;align-items:center;gap:4px;padding:0 4px;display:flex;position:absolute;transform:translate(-50%)}.legend{left:calc(var(--uhd-inset-left,0px) + 8px);background:var(--uhd-surface);border:1px solid var(--uhd-border);border-radius:var(--uhd-radius);box-shadow:var(--uhd-shadow-md);bottom:8px;right:auto}.legend-measure{left:calc(var(--uhd-inset-left,0px) + 8px);visibility:hidden;pointer-events:none;z-index:-1;width:max-content;position:absolute;bottom:8px}.legend-popover{z-index:45;width:max-content;max-width:calc(100% - 16px);position:absolute}.scenario-banner{top:calc(var(--uhd-inset-top,0px) + 8px)}.cad-view.present .cad-canvas{inset:0}.chip-toggle.icon{justify-content:center;width:32px;padding:0}.chip-toggle.caret{min-width:22px;margin-left:-4px;padding:0 4px}.cad-menu-wrap{align-items:center;gap:2px;display:flex;position:relative}.cad-menu{background:var(--uhd-surface-raised);border:1px solid var(--uhd-border);min-width:230px;box-shadow:var(--uhd-shadow-md);z-index:60;border-radius:6px;padding:4px;position:absolute;bottom:calc(100% + 10px);left:0}.cad-menu-label{color:var(--uhd-text-muted);padding:6px 8px;font-size:12px;font-weight:600}.cad-menu-item{width:100%;color:var(--uhd-text);text-align:left;border-radius:4px;align-items:center;gap:8px;padding:6px 8px;font-size:13px;display:flex}.cad-menu-item:hover{background:var(--uhd-border)}.cad-check{border:1px solid var(--uhd-border);border-radius:4px;place-items:center;width:16px;height:16px;display:grid}.cad-check.on{background:var(--uhd-accent);border-color:var(--uhd-accent);color:var(--uhd-text-on-accent)}.cad-kind-dot{border-radius:50%;width:8px;height:8px}.cad-notes{left:calc(var(--uhd-inset-left,0px) + 8px);background:var(--uhd-surface);border:1px solid var(--uhd-border);border-radius:var(--uhd-radius);box-shadow:var(--uhd-shadow-md);font-size:12px;bottom:56px}.cad-labels{pointer-events:none;z-index:20;position:absolute;inset:0}.cad-leaders{position:absolute;inset:0;overflow:visible}.cad-leaders path{fill:none;stroke-width:1.25px;stroke-linejoin:round}.cad-leaders circle{stroke:var(--uhd-background);stroke-width:1.5px}.cad-label{background:var(--uhd-surface);flex-direction:column;gap:1px;padding:5px 9px 6px 10px;display:flex;position:absolute;top:0;left:0}@supports (color:color-mix(in lab, red, red)){.cad-label{background:color-mix(in oklab, var(--uhd-surface) 92%, transparent)}}.cad-label{border:1px solid var(--uhd-border);box-shadow:var(--uhd-shadow-md);pointer-events:auto;cursor:pointer;white-space:nowrap;will-change:transform;border-left-width:3px;border-radius:6px}.cad-label-title{font-family:var(--uhd-font-label);letter-spacing:.02em;color:var(--uhd-text);font-size:12px}.cad-label-sub{color:var(--uhd-text-muted);font-size:11px}.cad-label.kind-module{border-left-color:var(--uhd-node-border-hover)}.cad-label.kind-harness{border-left-color:var(--uhd-accent)}.cad-label.kind-interface{border-left-color:var(--uhd-highlight)}.cad-leaders path.kind-module{stroke:var(--uhd-node-border-hover)}@supports (color:color-mix(in lab, red, red)){.cad-leaders path.kind-module{stroke:color-mix(in oklab, var(--uhd-node-border-hover) 80%, transparent)}}.cad-leaders path.kind-harness{stroke:var(--uhd-accent)}@supports (color:color-mix(in lab, red, red)){.cad-leaders path.kind-harness{stroke:color-mix(in oklab, var(--uhd-accent) 85%, transparent)}}.cad-leaders path.kind-interface{stroke:var(--uhd-highlight)}@supports (color:color-mix(in lab, red, red)){.cad-leaders path.kind-interface{stroke:color-mix(in oklab, var(--uhd-highlight) 80%, transparent)}}.cad-leaders circle.kind-module,.cad-kind-dot.kind-module{fill:var(--uhd-node-border-hover);background:var(--uhd-node-border-hover)}.cad-leaders circle.kind-harness,.cad-kind-dot.kind-harness{fill:var(--uhd-accent);background:var(--uhd-accent)}.cad-leaders circle.kind-interface,.cad-kind-dot.kind-interface{fill:var(--uhd-highlight);background:var(--uhd-highlight)}.cad-label.kind-finding{white-space:normal;max-width:280px}.cad-label.kind-finding .cad-label-title{letter-spacing:.06em;font-size:10.5px}.cad-label.kind-finding .cad-label-sub{font-size:10.5px;line-height:1.35}.cad-label.tone-error{border-left-color:var(--uhd-drc-incompatible)}.cad-label.tone-warning{border-left-color:var(--uhd-drc-partial)}.cad-leaders path.tone-error{stroke:var(--uhd-drc-incompatible)}@supports (color:color-mix(in lab, red, red)){.cad-leaders path.tone-error{stroke:color-mix(in oklab, var(--uhd-drc-incompatible) 85%, transparent)}}.cad-leaders path.tone-warning{stroke:var(--uhd-drc-partial)}@supports (color:color-mix(in lab, red, red)){.cad-leaders path.tone-warning{stroke:color-mix(in oklab, var(--uhd-drc-partial) 85%, transparent)}}.cad-leaders circle.tone-error{fill:var(--uhd-drc-incompatible);r:4.5px}.cad-leaders circle.tone-warning{fill:var(--uhd-drc-partial);r:4.5px}.cad-kind-dot.kind-finding{background:var(--uhd-drc-incompatible)}.cad-section{flex-direction:column;gap:8px;min-width:220px;display:flex}.cad-section input[type=range]{width:100%;accent-color:var(--uhd-accent)}.cad-finding{text-align:left;width:100%;color:var(--uhd-text);cursor:pointer;background:0 0;border:1px solid #0000;border-radius:6px;gap:8px;padding:6px 8px;font-size:10.5px;line-height:1.35;display:flex}.cad-finding:hover{background:var(--uhd-muted);border-color:var(--uhd-border)}.cad-finding.error svg{color:var(--uhd-drc-incompatible);flex:none}.cad-finding.warning svg{color:var(--uhd-drc-partial);flex:none}.cad-finding b{font-family:var(--uhd-font-label);letter-spacing:.06em;color:var(--uhd-text-muted);font-weight:400;display:block}:is(.app:has(.cad-view.present) .header,.app:has(.cad-view.present) .activity-bar){display:none}.cad-caption{z-index:25;pointer-events:none;flex-direction:column;gap:6px;display:flex;position:absolute;bottom:36px;left:40px}.cad-caption-brand{font-family:var(--uhd-font-label);letter-spacing:.08em;color:var(--uhd-text-muted);font-size:13px}.cad-caption-brand span{color:var(--uhd-accent)}.cad-caption-title{font-family:var(--uhd-font-label);color:var(--uhd-text);font-size:28px}.cad-caption-sub{color:var(--uhd-text-muted);font-size:15px}.load-state{color:var(--uhd-text-muted);place-items:center;font-size:13px;display:grid;position:fixed;inset:0}.load-state.error{color:var(--uhd-drc-incompatible)}.draw-error{text-align:center;font:12px/1.5 var(--uhd-font-ui);padding:24px}.draw-error>div{overflow-wrap:anywhere;max-width:min(520px,100%)}.draw-error b{font-weight:600}.draw-error p{color:var(--uhd-text);margin:6px 0 0}.draw-error .draw-error-note{color:var(--uhd-text-muted)}.harness-tab{background:var(--uhd-text);align-items:center;gap:5px;padding:2px 6px;display:flex;position:absolute}@supports (color:color-mix(in lab, red, red)){.harness-tab{background:color-mix(in oklab, var(--uhd-text) 7%, transparent)}}.harness-tab{font-family:var(--uhd-font-ui);letter-spacing:.5px;color:var(--uhd-text);white-space:nowrap;pointer-events:all;cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none;border-radius:4px 4px 0 0;font-size:8.5px}.lane-name{background:var(--uhd-canvas);height:12px;font-family:var(--uhd-font-ui);letter-spacing:.3px;color:var(--uhd-text-muted);white-space:nowrap;pointer-events:none;border-radius:3px;align-items:center;gap:4px;padding:0 4px;font-size:7.5px;display:flex;position:absolute}.lane-swatch{border-radius:50%;width:5px;height:5px}.link-label{-webkit-user-select:none;user-select:none;touch-action:none}.harness-tab.below{border-radius:0 0 4px 4px}.react-flow__handle.port-anchor{opacity:0;pointer-events:none;border:0;width:1px;min-width:0;height:1px;min-height:0;position:absolute;transform:translate(-50%,-50%)}.port-dot{z-index:1;pointer-events:none;position:absolute}.port-dot.selected{box-shadow:0 0 0 2px var(--uhd-canvas), 0 0 0 3.5px var(--uhd-accent)}.link-reset{width:13px;height:13px;color:inherit;cursor:pointer;background:0 0;border:none;border-radius:3px;place-items:center;margin-right:-3px;padding:0;display:grid}.link-reset:hover{background:var(--uhd-text)}@supports (color:color-mix(in lab, red, red)){.link-reset:hover{background:color-mix(in oklab, var(--uhd-text) 12%, transparent)}}.artifact-thumb{background:var(--uhd-preview);border-radius:6px;place-items:center;height:140px;margin-bottom:8px;padding:8px;display:grid;overflow:hidden}.artifact-thumb img{object-fit:contain;max-width:100%;max-height:100%}.artifact-cad{border:1px solid var(--uhd-border);border-radius:6px;margin-bottom:8px;position:relative;overflow:hidden}.artifact-cad-canvas{cursor:grab;height:200px}.artifact-cad-canvas:active{cursor:grabbing}.artifact-cad-hint{font-family:var(--uhd-font-ui);letter-spacing:.4px;color:var(--uhd-text-muted);pointer-events:none;font-size:8px;position:absolute;bottom:6px;left:8px}.artifact-files{flex-direction:column;gap:4px;margin-bottom:8px;display:flex}.artifact-file{background:var(--uhd-text);border-radius:4px;align-items:center;gap:6px;padding:4px 6px;display:flex}@supports (color:color-mix(in lab, red, red)){.artifact-file{background:color-mix(in oklab, var(--uhd-text) 3%, transparent)}}.artifact-file{color:var(--uhd-text);font-size:10px;text-decoration:none}.artifact-file:hover{background:var(--uhd-text)}@supports (color:color-mix(in lab, red, red)){.artifact-file:hover{background:color-mix(in oklab, var(--uhd-text) 8%, transparent)}}.artifact-name{text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}.artifact-format{color:var(--uhd-text-muted);font-size:9px}.artifact-parts{flex-wrap:wrap;gap:4px;margin-bottom:8px;display:flex}.sample-tag{border:1px solid var(--uhd-accent);color:var(--uhd-accent);letter-spacing:.08em;border-radius:4px;margin-left:6px;padding:0 5px;font-size:8px}.board-tabs{margin-bottom:6px}.board-drawing{margin-bottom:8px;position:relative}.board-drawing-view{border:1px solid var(--uhd-border);background:var(--uhd-drawing);cursor:grab;touch-action:none;overscroll-behavior:contain;border-radius:8px;height:220px;position:relative;overflow:hidden}.board-drawing-view:active{cursor:grabbing}.board-drawing-stage{transform-origin:0 0;position:absolute;inset:0}.board-drawing-stage img,.board-drawing-marks{object-fit:contain;-webkit-user-select:none;user-select:none;pointer-events:none;width:100%;height:100%;position:absolute;inset:0}.board-drawing-marks .mark{fill:#0000;stroke:#0000;stroke-width:1.5px}.board-drawing-marks .mark.hover{stroke:var(--uhd-text)}@supports (color:color-mix(in lab, red, red)){.board-drawing-marks .mark.hover{stroke:color-mix(in oklab, var(--uhd-text) 60%, transparent)}}.board-drawing-marks .mark.on{fill:var(--uhd-accent)}@supports (color:color-mix(in lab, red, red)){.board-drawing-marks .mark.on{fill:color-mix(in oklab, var(--uhd-accent) 22%, transparent)}}.board-drawing-marks .mark.on{stroke:var(--uhd-accent);stroke-width:2px}.pin-table-wrap{border:1px solid var(--uhd-border);border-radius:6px;max-height:260px}.pin-table{width:100%}.pin-table th{background:var(--uhd-surface);text-align:left;color:var(--uhd-text-muted);letter-spacing:.06em;font-size:8.5px;font-weight:400;position:sticky;top:0}.pin-table tr.on-net td:last-child{color:var(--uhd-domain-electrical)}.package-facts .note{margin-top:4px}.tree-item.member .tree-tag{text-overflow:ellipsis;white-space:nowrap;max-width:55%;overflow:hidden}.check-scope{color:var(--uhd-accent)}.context-menu{z-index:60;background:var(--uhd-surface-raised);border:1px solid var(--uhd-border);border-radius:var(--uhd-radius);min-width:160px;box-shadow:var(--uhd-shadow-lg);flex-direction:column;padding:4px;display:flex;position:fixed}.context-menu button{text-align:left;letter-spacing:.06em;color:var(--uhd-text);border-radius:5px;padding:6px 10px;font-size:10px}.context-menu button:hover{background:var(--uhd-active)}.breadcrumb{flex:1 1 0;min-width:96px;overflow:hidden}.crumb-wrap{flex-shrink:1;min-width:0}.crumb-wrap:not(:last-child){flex-shrink:0}.crumb{text-overflow:ellipsis;white-space:nowrap;min-width:0;max-width:100%;overflow:hidden}.header-controls{scrollbar-width:none;flex:0 auto;min-width:0;overflow-x:auto}.header-controls::-webkit-scrollbar{display:none}.header-controls>*{flex-shrink:0}.inspector{width:min(340px,100% - 64px)}.cad-inspector{width:min(360px,100% - 64px)}@media (width<=760px){.brand-name,.brand+.sep{display:none}.brand{padding:0 4px 0 6px}}.cad-toolbar{left:calc(var(--uhd-inset-left,0px) + 8px);width:fit-content;max-width:calc(100% - 16px - var(--uhd-inset-left,0px));scrollbar-width:none;margin-inline:auto;right:8px;overflow-x:auto;transform:none}.cad-view:has(.cad-inspector) .cad-toolbar{right:calc(min(360px,100% - 64px) + 12px)}@media (width<=700px){.cad-toolbar{max-width:calc(100% - 16px);left:8px}}@media (width<=900px){.inspector,.cad-inspector{width:min(300px,100% - 96px)}.toolbar{left:calc(var(--uhd-inset-left,0px) + 8px);width:fit-content;max-width:calc(100% - 16px - var(--uhd-inset-left,0px));scrollbar-width:none;margin-inline:auto;right:8px;overflow-x:auto;transform:none}.toolbar>*{flex-shrink:0}.toolbar::-webkit-scrollbar{display:none}.cad-toolbar::-webkit-scrollbar{display:none}:is(.toolbar.covered-right,.cad-view:has(.cad-inspector) .cad-toolbar){right:calc(min(300px,100% - 96px) + 12px)}}.react-flow.uhd-tool-select .react-flow__pane{cursor:default}.react-flow.uhd-grab .react-flow__pane,.react-flow.uhd-tool-pan .react-flow__node{cursor:grab}.react-flow.uhd-grab .react-flow__pane.dragging,.react-flow.uhd-tool-pan .react-flow__pane.dragging{cursor:grabbing}.react-flow.uhd-right-panning,.react-flow.uhd-right-panning *{cursor:grabbing!important}.react-flow{-webkit-user-select:none;user-select:none}.react-flow__selection{background:var(--uhd-accent-tint);border:1px solid var(--uhd-accent);border-radius:4px}[data-uhd-scheme^=high-contrast] .react-flow__selection{border:1px dashed var(--uhd-contrast-active-border,var(--uhd-accent));background:0 0}.react-flow__nodesselection{display:none}.node-chevron{z-index:2;width:18px;height:18px;color:var(--uhd-text-muted);pointer-events:auto;border-radius:5px;place-items:center;display:grid;position:absolute;top:3px;left:3px}:where(.uhd-root) button.node-chevron{border:1px solid #0000}.node-chevron:hover{color:var(--uhd-text);background:var(--uhd-active);border-color:var(--uhd-contrast-active-border,transparent)}.container-label .node-chevron{margin:-4px -2px -4px -6px;position:static}.node-info{width:12px;height:12px;color:var(--uhd-text-faint);pointer-events:auto;place-items:center;display:grid;position:absolute;top:5px;right:21px}.node-info:hover{color:var(--uhd-text)}.port-label.cut{pointer-events:auto}.details.uhd-details-a{padding:0}.uhd-sections .section-title{letter-spacing:.06em;color:var(--uhd-text-faint);padding:8px 0 4px;font-size:10px}.uhd-sections .kv,.uhd-sections .facts .kv,.uhd-sections .description,.uhd-sections .actions,.uhd-sections .tree-item{padding-left:0;padding-right:0}.uhd-sections .child-table{width:100%;margin:0}.uhd-scroll-y>div{min-width:0!important;display:block!important}[data-uhd-scheme^=high-contrast] :is(.card,.module-card,.inspector,.legend,.toolbar,.cad-toolbar,.activity-bar,.header){outline:1px solid var(--uhd-contrast-border);outline-offset:-1px}[data-uhd-scheme^=high-contrast] :is(.module-card.selected,.tree-item.selected,.check:hover,.cad-row.on,.crumb:hover){outline:1px dashed var(--uhd-contrast-active-border);outline-offset:-1px}[data-uhd-scheme^=high-contrast] .uhd-icon-button[aria-pressed=true]{color:var(--uhd-text);outline:1px solid var(--uhd-contrast-active-border);background:0 0}@media (prefers-reduced-motion:reduce){.uhd-scrollbar{transition:none}}.uhd-artifact-grid{container-type:inline-size}.uhd-artifact-grid-cards{grid-template-columns:repeat(auto-fill,minmax(124px,1fr));gap:6px;display:grid}.uhd-artifact-card{flex-direction:column;min-width:0;display:flex}.uhd-artifact-picture{aspect-ratio:4/3;width:100%}.uhd-artifact-text{border-top-style:solid;border-top-width:1px}@container not (width>=264px){.uhd-artifact-grid-cards{grid-template-columns:minmax(0,1fr)}.uhd-artifact-card{flex-direction:row;align-items:stretch}.uhd-artifact-picture{aspect-ratio:auto;width:56px;min-height:52px}.uhd-artifact-text{border-top-width:0;border-left-style:solid;border-left-width:1px}}.uhd-tree-mark{--mark:var(--uhd-mark-neutral,var(--uhd-text-faint));background:var(--mark);outline:1px solid var(--uhd-contrast-border,transparent);outline-offset:1px;border-radius:50%;width:8px;height:8px}.uhd-tree-mark[data-tone=info]{--mark:var(--uhd-mark-info,var(--uhd-severity-info))}.uhd-tree-mark[data-tone=ok]{--mark:var(--uhd-mark-ok,var(--uhd-severity-ok))}.uhd-tree-mark[data-tone=warning]{--mark:var(--uhd-mark-warning,var(--uhd-severity-warning))}.uhd-tree-mark[data-tone=error]{--mark:var(--uhd-mark-error,var(--uhd-severity-error))}.uhd-tree-mark[data-shape=ring]{border:1.5px dashed var(--mark);background:0 0;outline:none;width:9px;height:9px}.uhd-hierarchy-dock input{font:inherit;appearance:none}}@layer utilities{.pointer-events-none{pointer-events:none}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:0}.inset-y-0{inset-block:0}.-top-0\.5{top:calc(var(--spacing) * -.5)}.top-1{top:var(--spacing)}.top-\[calc\(var\(--uhd-inset-top\,0px\)\+12px\)\]{top:calc(var(--uhd-inset-top,0px) + 12px)}.top-\[var\(--uhd-inset-top\,0px\)\]{top:var(--uhd-inset-top,0px)}.-right-0\.5{right:calc(var(--spacing) * -.5)}.-right-1{right:calc(var(--spacing) * -1)}.right-0{right:0}.right-1{right:var(--spacing)}.bottom-0{bottom:0}.bottom-1{bottom:var(--spacing)}.bottom-3{bottom:calc(var(--spacing) * 3)}.left-0{left:0}.left-3{left:calc(var(--spacing) * 3)}.left-\[3px\]{left:3px}.isolate{isolation:isolate}.z-10{z-index:10}.z-30{z-index:30}.z-\[1000\]{z-index:1000}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.m-0{margin:0}.m-32{margin:calc(var(--spacing) * 32)}.-mx-1\.5{margin-inline:calc(var(--spacing) * -1.5)}.mx-0\.5{margin-inline:calc(var(--spacing) * .5)}.mx-2{margin-inline:calc(var(--spacing) * 2)}.-my-0\.5{margin-block:calc(var(--spacing) * -.5)}.-my-1{margin-block:calc(var(--spacing) * -1)}.-my-px{margin-block:-1px}.my-0\.5{margin-block:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-\[5px\]{margin-top:5px}.mt-px{margin-top:1px}.-mr-1\.5{margin-right:calc(var(--spacing) * -1.5)}.mb-0\.5{margin-bottom:calc(var(--spacing) * .5)}.mb-1{margin-bottom:var(--spacing)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.ml-1\.5{margin-left:calc(var(--spacing) * 1.5)}.ml-auto{margin-left:auto}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-2{width:calc(var(--spacing) * 2);height:calc(var(--spacing) * 2)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-7{width:calc(var(--spacing) * 7);height:calc(var(--spacing) * 7)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-\[7px\]{width:7px;height:7px}.size-\[11px\]{width:11px;height:11px}.size-full{width:100%;height:100%}.h-2{height:calc(var(--spacing) * 2)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-\[3px\]{height:3px}.h-\[9px\]{height:9px}.h-\[18px\]{height:18px}.h-\[26px\]{height:26px}.h-full{height:100%}.h-px{height:1px}.max-h-64{max-height:calc(var(--spacing) * 64)}.min-h-0{min-height:0}.min-h-5{min-height:calc(var(--spacing) * 5)}.min-h-6{min-height:calc(var(--spacing) * 6)}.min-h-11{min-height:calc(var(--spacing) * 11)}.min-h-\[18px\]{min-height:18px}.min-h-\[22px\]{min-height:22px}.min-h-\[240px\]{min-height:240px}.w-0\.5{width:calc(var(--spacing) * .5)}.w-2{width:calc(var(--spacing) * 2)}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-11{width:calc(var(--spacing) * 11)}.w-\[3px\]{width:3px}.w-\[88px\]{width:88px}.w-\[92px\]{width:92px}.w-full{width:100%}.w-max{width:max-content}.w-px{width:1px}.max-w-\[60\%\]{max-width:60%}.max-w-\[280px\]{max-width:280px}.max-w-\[320px\]{max-width:320px}.max-w-\[min\(300px\,calc\(100\%-12px\)\)\]{max-width:min(300px,100% - 12px)}.max-w-\[min\(360px\,calc\(100\%-24px\)\)\]{max-width:min(360px,100% - 24px)}.max-w-full{max-width:100%}.min-w-0{min-width:0}.min-w-3\.5{min-width:calc(var(--spacing) * 3.5)}.min-w-\[150px\]{min-width:150px}.min-w-\[280px\]{min-width:280px}.flex-1{flex:1}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.rotate-90{rotate:90deg}.rotate-180{rotate:180deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.cursor-col-resize{cursor:col-resize}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.resize{resize:both}.\[scrollbar-width\:none\]{scrollbar-width:none}.grid-cols-\[minmax\(0\,1fr\)_56px_minmax\(0\,1fr\)\]{grid-template-columns:minmax(0,1fr) 56px minmax(0,1fr)}.flex-col{flex-direction:column}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-\[2px\]{gap:2px}.gap-\[3px\]{gap:3px}.gap-px{gap:1px}.gap-x-1{column-gap:var(--spacing)}.gap-x-3{column-gap:calc(var(--spacing) * 3)}.gap-y-0\.5{row-gap:calc(var(--spacing) * .5)}.gap-y-1{row-gap:var(--spacing)}.self-start{align-self:flex-start}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-x-auto{overflow-x:auto}.rounded{border-radius:.25rem}.rounded-\[1px\]{border-radius:1px}.rounded-\[3px\]{border-radius:3px}.rounded-\[4px\]{border-radius:4px}.rounded-\[6px\]{border-radius:6px}.rounded-\[inherit\]{border-radius:inherit}.rounded-full{border-radius:2147483647px}.rounded-md{border-radius:var(--radius-md)}.rounded-panel{border-radius:var(--uhd-radius)}.rounded-sm{border-radius:var(--radius-sm)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-\[color-mix\(in_oklab\,var\(--uhd-severity-warning\)_45\%\,transparent\)\]{border-color:var(--uhd-severity-warning)}@supports (color:color-mix(in lab, red, red)){.border-\[color-mix\(in_oklab\,var\(--uhd-severity-warning\)_45\%\,transparent\)\]{border-color:color-mix(in oklab,var(--uhd-severity-warning) 45%,transparent)}}.border-accent{border-color:var(--uhd-accent)}.border-error\/60{border-color:var(--uhd-severity-error)}@supports (color:color-mix(in lab, red, red)){.border-error\/60{border-color:color-mix(in oklab, var(--uhd-severity-error) 60%, transparent)}}.border-fg-faint{border-color:var(--uhd-text-faint)}.border-info\/60{border-color:var(--uhd-severity-info)}@supports (color:color-mix(in lab, red, red)){.border-info\/60{border-color:color-mix(in oklab, var(--uhd-severity-info) 60%, transparent)}}.border-line{border-color:var(--uhd-border)}.border-line-strong{border-color:var(--uhd-border-strong)}.border-line-subtle{border-color:var(--uhd-border-subtle)}.border-ok\/60{border-color:var(--uhd-severity-ok)}@supports (color:color-mix(in lab, red, red)){.border-ok\/60{border-color:color-mix(in oklab, var(--uhd-severity-ok) 60%, transparent)}}.border-transparent{border-color:#0000}.border-warning\/60{border-color:var(--uhd-severity-warning)}@supports (color:color-mix(in lab, red, red)){.border-warning\/60{border-color:color-mix(in oklab, var(--uhd-severity-warning) 60%, transparent)}}.bg-\[color-mix\(in_oklab\,var\(--uhd-text\)_3\%\,transparent\)\]{background-color:var(--uhd-text)}@supports (color:color-mix(in lab, red, red)){.bg-\[color-mix\(in_oklab\,var\(--uhd-text\)_3\%\,transparent\)\]{background-color:color-mix(in oklab,var(--uhd-text) 3%,transparent)}}.bg-\[color-mix\(in_oklab\,var\(--uhd-text\)_5\%\,transparent\)\]{background-color:var(--uhd-text)}@supports (color:color-mix(in lab, red, red)){.bg-\[color-mix\(in_oklab\,var\(--uhd-text\)_5\%\,transparent\)\]{background-color:color-mix(in oklab,var(--uhd-text) 5%,transparent)}}.bg-\[color-mix\(in_oklab\,var\(--uhd-text\)_8\%\,transparent\)\]{background-color:var(--uhd-text)}@supports (color:color-mix(in lab, red, red)){.bg-\[color-mix\(in_oklab\,var\(--uhd-text\)_8\%\,transparent\)\]{background-color:color-mix(in oklab,var(--uhd-text) 8%,transparent)}}.bg-\[var\(--uhd-preview\)\]{background-color:var(--uhd-preview)}.bg-accent{background-color:var(--uhd-accent)}.bg-accent-tint{background-color:var(--uhd-accent-tint)}.bg-active{background-color:var(--uhd-active)}.bg-canvas{background-color:var(--uhd-canvas)}.bg-error,.bg-error\/15{background-color:var(--uhd-severity-error)}@supports (color:color-mix(in lab, red, red)){.bg-error\/15{background-color:color-mix(in oklab, var(--uhd-severity-error) 15%, transparent)}}.bg-fg-faint{background-color:var(--uhd-text-faint)}.bg-info{background-color:var(--uhd-severity-info)}.bg-line{background-color:var(--uhd-border)}.bg-ok{background-color:var(--uhd-severity-ok)}.bg-raised{background-color:var(--uhd-surface-raised)}.bg-selection{background-color:var(--uhd-selection)}.bg-sunken{background-color:var(--uhd-surface-sunken)}.bg-surface{background-color:var(--uhd-surface)}.bg-thumb{background-color:var(--uhd-scrollbar-thumb)}.bg-transparent{background-color:#0000}.bg-warning,.bg-warning\/15{background-color:var(--uhd-severity-warning)}@supports (color:color-mix(in lab, red, red)){.bg-warning\/15{background-color:color-mix(in oklab, var(--uhd-severity-warning) 15%, transparent)}}.object-contain{object-fit:contain}.p-0{padding:0}.p-1{padding:var(--spacing)}.p-2{padding:calc(var(--spacing) * 2)}.p-\[6\%\]{padding:6%}.p-px{padding:1px}.px-0\.5{padding-inline:calc(var(--spacing) * .5)}.px-1{padding-inline:var(--spacing)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-\[3px\]{padding-inline:3px}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-10{padding-block:calc(var(--spacing) * 10)}.py-\[3px\]{padding-block:3px}.py-\[7px\]{padding-block:7px}.pt-0\.5{padding-top:calc(var(--spacing) * .5)}.pt-1{padding-top:var(--spacing)}.pt-1\.5{padding-top:calc(var(--spacing) * 1.5)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-\[var\(--uhd-inset-top\,0px\)\]{padding-top:var(--uhd-inset-top,0px)}.pr-1{padding-right:var(--spacing)}.pr-1\.5{padding-right:calc(var(--spacing) * 1.5)}.pr-3{padding-right:calc(var(--spacing) * 3)}.pb-1{padding-bottom:var(--spacing)}.pb-1\.5{padding-bottom:calc(var(--spacing) * 1.5)}.pb-2\.5{padding-bottom:calc(var(--spacing) * 2.5)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pl-1\.5{padding-left:calc(var(--spacing) * 1.5)}.pl-2\.5{padding-left:calc(var(--spacing) * 2.5)}.pl-3{padding-left:calc(var(--spacing) * 3)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-code{font-family:var(--uhd-font-mono)}.font-label{font-family:var(--uhd-font-label)}.font-ui{font-family:var(--uhd-font-ui)}.text-\[9\.5px\]{font-size:9.5px}.text-\[9px\]{font-size:9px}.text-\[10\.5px\]{font-size:10.5px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12\.5px\]{font-size:12.5px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.leading-4{--tw-leading:calc(var(--spacing) * 4);line-height:calc(var(--spacing) * 4)}.leading-\[1\.3\]{--tw-leading:1.3;line-height:1.3}.leading-\[1\.4\]{--tw-leading:1.4;line-height:1.4}.leading-\[1\.5\]{--tw-leading:1.5;line-height:1.5}.leading-\[1\.35\]{--tw-leading:1.35;line-height:1.35}.leading-\[14px\]{--tw-leading:14px;line-height:14px}.leading-\[16px\]{--tw-leading:16px;line-height:16px}.leading-\[18px\]{--tw-leading:18px;line-height:18px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[-0\.01em\]{--tw-tracking:-.01em;letter-spacing:-.01em}.tracking-\[0\.04em\]{--tw-tracking:.04em;letter-spacing:.04em}.tracking-\[0\.06em\]{--tw-tracking:.06em;letter-spacing:.06em}.tracking-\[0\.08em\]{--tw-tracking:.08em;letter-spacing:.08em}.tracking-\[0\.8px\]{--tw-tracking:.8px;letter-spacing:.8px}.tracking-\[0\.12em\]{--tw-tracking:.12em;letter-spacing:.12em}.\[overflow-wrap\:anywhere\]{overflow-wrap:anywhere}.break-words{overflow-wrap:break-word}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.text-accent{color:var(--uhd-accent)}.text-error{color:var(--uhd-severity-error)}.text-fg{color:var(--uhd-text)}.text-fg-faint{color:var(--uhd-text-faint)}.text-fg-muted{color:var(--uhd-text-muted)}.text-info{color:var(--uhd-severity-info)}.text-link{color:var(--uhd-text-link)}.text-muted{color:var(--uhd-muted)}.text-ok{color:var(--uhd-severity-ok)}.text-selection-fg{color:var(--uhd-selection-text)}.text-warning{color:var(--uhd-severity-warning)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.no-underline{text-decoration-line:none}.opacity-40{opacity:.4}.opacity-55{opacity:.55}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-float{--tw-shadow:var(--uhd-shadow-lg);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-panel{--tw-shadow:var(--uhd-shadow-md);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.outline,.outline-1{outline-style:var(--tw-outline-style);outline-width:1px}.-outline-offset-1{outline-offset:calc(1px * -1)}.outline-contrast{outline-color:var(--uhd-contrast-border)}.outline-contrast-active{outline-color:var(--uhd-contrast-active-border)}.outline-focus{outline-color:var(--uhd-focus-ring)}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition-\[opacity\,background-color\]{transition-property:opacity,background-color;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-100{--tw-duration:.1s;transition-duration:.1s}.duration-150{--tw-duration:.15s;transition-duration:.15s}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-all{-webkit-user-select:all;user-select:all}.select-none{-webkit-user-select:none;user-select:none}.\[writing-mode\:vertical-rl\]{writing-mode:vertical-rl}@media (hover:hover){.group-hover\:bg-focus:is(:where(.group):hover *){background-color:var(--uhd-focus-ring)}}.group-focus-visible\:bg-focus:is(:where(.group):focus-visible *),.group-active\:bg-focus:is(:where(.group):active *){background-color:var(--uhd-focus-ring)}.placeholder\:text-fg-faint::placeholder{color:var(--uhd-text-faint)}.before\:absolute:before{content:var(--tw-content);position:absolute}.before\:top-1\/2:before{content:var(--tw-content);top:50%}.before\:left-1\/2:before{content:var(--tw-content);left:50%}.before\:size-full:before{content:var(--tw-content);width:100%;height:100%}.before\:min-h-6:before{content:var(--tw-content);min-height:calc(var(--spacing) * 6)}.before\:min-w-6:before{content:var(--tw-content);min-width:calc(var(--spacing) * 6)}.before\:-translate-1\/2:before{content:var(--tw-content);--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.before\:content-\[\'\'\]:before{--tw-content:"";content:var(--tw-content)}.after\:absolute:after{content:var(--tw-content);position:absolute}.after\:inset-0:after{content:var(--tw-content);inset:0}.after\:content-\[\'\'\]:after{--tw-content:"";content:var(--tw-content)}.focus-within\:outline:focus-within,.focus-within\:outline-1:focus-within{outline-style:var(--tw-outline-style);outline-width:1px}.focus-within\:-outline-offset-1:focus-within{outline-offset:calc(1px * -1)}.focus-within\:outline-focus:focus-within{outline-color:var(--uhd-focus-ring)}@media (hover:hover){.hover\:border-line-strong:hover{border-color:var(--uhd-border-strong)}.hover\:bg-active:hover{background-color:var(--uhd-active)}.hover\:bg-hover:hover{background-color:var(--uhd-hover)}.hover\:bg-thumb-hover:hover{background-color:var(--uhd-scrollbar-thumb-hover)}.hover\:bg-transparent:hover{background-color:#0000}.hover\:text-fg:hover{color:var(--uhd-text)}.hover\:underline:hover{text-decoration-line:underline}.hover\:outline:hover,.hover\:outline-1:hover{outline-style:var(--tw-outline-style);outline-width:1px}.hover\:-outline-offset-1:hover{outline-offset:calc(1px * -1)}.hover\:outline-contrast-active:hover{outline-color:var(--uhd-contrast-active-border)}.hover\:outline-dashed:hover{--tw-outline-style:dashed;outline-style:dashed}}.focus-visible\:border-focus:focus-visible{border-color:var(--uhd-focus-ring)}.focus-visible\:outline:focus-visible,.focus-visible\:outline-1:focus-visible{outline-style:var(--tw-outline-style);outline-width:1px}.focus-visible\:-outline-offset-1:focus-visible{outline-offset:calc(1px * -1)}.focus-visible\:outline-focus:focus-visible{outline-color:var(--uhd-focus-ring)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.focus-visible\:outline-solid:focus-visible{--tw-outline-style:solid;outline-style:solid}.disabled\:cursor-default:disabled{cursor:default}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}@media (hover:hover){.disabled\:hover\:bg-transparent:disabled:hover{background-color:#0000}}:is(.has-\[\[data-card-toggle\]\:focus-visible\]\:outline:has([data-card-toggle]:focus-visible),.has-\[\[data-card-toggle\]\:focus-visible\]\:outline-1:has([data-card-toggle]:focus-visible)){outline-style:var(--tw-outline-style);outline-width:1px}.has-\[\[data-card-toggle\]\:focus-visible\]\:-outline-offset-1:has([data-card-toggle]:focus-visible){outline-offset:calc(1px * -1)}.has-\[\[data-card-toggle\]\:focus-visible\]\:outline-focus:has([data-card-toggle]:focus-visible){outline-color:var(--uhd-focus-ring)}.aria-pressed\:border-accent\/45[aria-pressed=true]{border-color:var(--uhd-accent)}@supports (color:color-mix(in lab, red, red)){.aria-pressed\:border-accent\/45[aria-pressed=true]{border-color:color-mix(in oklab, var(--uhd-accent) 45%, transparent)}}.aria-pressed\:bg-accent-tint[aria-pressed=true]{background-color:var(--uhd-accent-tint)}.aria-pressed\:text-accent[aria-pressed=true]{color:var(--uhd-accent)}.aria-pressed\:outline[aria-pressed=true],.aria-pressed\:outline-1[aria-pressed=true]{outline-style:var(--tw-outline-style);outline-width:1px}.aria-pressed\:-outline-offset-1[aria-pressed=true]{outline-offset:calc(1px * -1)}.aria-pressed\:outline-contrast-active[aria-pressed=true]{outline-color:var(--uhd-contrast-active-border)}@media (hover:hover){.aria-pressed\:hover\:bg-accent-tint[aria-pressed=true]:hover{background-color:var(--uhd-accent-tint)}.aria-pressed\:hover\:text-accent[aria-pressed=true]:hover{color:var(--uhd-accent)}}.data-\[state\=hidden\]\:opacity-0[data-state=hidden]{opacity:0}@media not all and (width>=640px){.max-\[640px\]\:hidden{display:none}}.\[\&\>canvas\]\:block>canvas{display:block}.\[\&\>canvas\]\:size-full>canvas{width:100%;height:100%}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}