@braidlabs/console 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +131 -0
  2. package/package.json +43 -0
  3. package/src/app/console-app.d.ts +17 -0
  4. package/src/app/console-app.js +48 -0
  5. package/src/app/console-app.js.map +1 -0
  6. package/src/app/main.d.ts +1 -0
  7. package/src/app/main.js +32 -0
  8. package/src/app/main.js.map +1 -0
  9. package/src/index.d.ts +38 -0
  10. package/src/index.js +30 -0
  11. package/src/index.js.map +1 -0
  12. package/src/lib/access-panel.d.ts +21 -0
  13. package/src/lib/access-panel.js +35 -0
  14. package/src/lib/access-panel.js.map +1 -0
  15. package/src/lib/client.d.ts +94 -0
  16. package/src/lib/client.js +109 -0
  17. package/src/lib/client.js.map +1 -0
  18. package/src/lib/draft.d.ts +45 -0
  19. package/src/lib/draft.js +85 -0
  20. package/src/lib/draft.js.map +1 -0
  21. package/src/lib/integration-panel.d.ts +13 -0
  22. package/src/lib/integration-panel.js +85 -0
  23. package/src/lib/integration-panel.js.map +1 -0
  24. package/src/lib/integration.d.ts +36 -0
  25. package/src/lib/integration.js +148 -0
  26. package/src/lib/integration.js.map +1 -0
  27. package/src/lib/registry-console.d.ts +46 -0
  28. package/src/lib/registry-console.js +88 -0
  29. package/src/lib/registry-console.js.map +1 -0
  30. package/src/lib/registry-editor.d.ts +26 -0
  31. package/src/lib/registry-editor.js +133 -0
  32. package/src/lib/registry-editor.js.map +1 -0
  33. package/src/lib/styles.d.ts +27 -0
  34. package/src/lib/styles.js +470 -0
  35. package/src/lib/styles.js.map +1 -0
  36. package/src/lib/topology-graph.d.ts +47 -0
  37. package/src/lib/topology-graph.js +124 -0
  38. package/src/lib/topology-graph.js.map +1 -0
  39. package/src/lib/topology.d.ts +86 -0
  40. package/src/lib/topology.js +122 -0
  41. package/src/lib/topology.js.map +1 -0
@@ -0,0 +1,26 @@
1
+ import type { NamedPrincipal } from '@braidlabs/registry';
2
+ import { type ConsoleApi, type PublishOutcome } from './client.js';
3
+ export interface RegistryEditorProps {
4
+ /** Must carry an `apiPath` (or accept the default) — editing needs the write API. */
5
+ api?: ConsoleApi;
6
+ theme?: 'light' | 'dark';
7
+ className?: string;
8
+ /** Called after a successful publish, for hosts that want to react (toast, audit, navigate). */
9
+ onPublished?: (outcome: PublishOutcome) => void;
10
+ /**
11
+ * Principals the access preview tests against, beyond anonymous (which is always included).
12
+ *
13
+ * Held by the host when given, so they can be persisted or shared; otherwise the editor keeps
14
+ * them for the session. Either way they are a what-if, not a directory.
15
+ */
16
+ principals?: NamedPrincipal[];
17
+ onPrincipalsChange?: (principals: NamedPrincipal[]) => void;
18
+ }
19
+ /**
20
+ * Edit the registry and publish it as a new immutable snapshot.
21
+ *
22
+ * The flow is deliberately: **branch from what is pinned → edit → see what it changes → publish**.
23
+ * Publishing never mutates the snapshot being edited; it mints a new one and moves a pointer, so
24
+ * the previous configuration remains exactly as it was and rollback is re-pinning it.
25
+ */
26
+ export declare function RegistryEditor({ api, theme, className, onPublished, principals, onPrincipalsChange, }: RegistryEditorProps): import("react").JSX.Element;
@@ -0,0 +1,133 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useMemo, useState } from 'react';
3
+ import { AccessPanel } from './access-panel.js';
4
+ import { fetchHead, publishSnapshot, RegistryApiError, } from './client.js';
5
+ import { accessMatrix, ANONYMOUS } from '@braidlabs/registry';
6
+ import { addFragment, createDraft, draftStatus, formatList, parseList, removeFragment, resetDraft, updateFragment, } from './draft.js';
7
+ import { ensureStyles } from './styles.js';
8
+ /**
9
+ * Edit the registry and publish it as a new immutable snapshot.
10
+ *
11
+ * The flow is deliberately: **branch from what is pinned → edit → see what it changes → publish**.
12
+ * Publishing never mutates the snapshot being edited; it mints a new one and moves a pointer, so
13
+ * the previous configuration remains exactly as it was and rollback is re-pinning it.
14
+ */
15
+ export function RegistryEditor({ api, theme, className, onPublished, principals, onPrincipalsChange, }) {
16
+ const [draft, setDraft] = useState(() => createDraft([]));
17
+ const [phase, setPhase] = useState({ status: 'loading' });
18
+ const [expanded, setExpanded] = useState(null);
19
+ const [showDiff, setShowDiff] = useState(false);
20
+ const [showAccess, setShowAccess] = useState(false);
21
+ const [ownPrincipals, setOwnPrincipals] = useState([]);
22
+ // Controlled when the host supplies them, uncontrolled otherwise — the same shape as any input.
23
+ const testPrincipals = principals ?? ownPrincipals;
24
+ const setPrincipals = (next) => (onPrincipalsChange ?? setOwnPrincipals)(next);
25
+ const apiKey = `${api?.baseUrl ?? ''}|${api?.apiPath ?? ''}`;
26
+ useEffect(() => {
27
+ ensureStyles();
28
+ }, []);
29
+ useEffect(() => {
30
+ const controller = new AbortController();
31
+ let current = true;
32
+ setPhase({ status: 'loading' });
33
+ fetchHead(api, controller.signal).then((head) => {
34
+ if (!current)
35
+ return;
36
+ setDraft(createDraft(head.snapshot?.manifests ?? [], head.id));
37
+ setPhase({ status: 'ready' });
38
+ }, (error) => {
39
+ if (!current || controller.signal.aborted)
40
+ return;
41
+ setPhase({ status: 'error', error: asError(error), findings: [], notes: [] });
42
+ });
43
+ return () => {
44
+ current = false;
45
+ controller.abort();
46
+ };
47
+ // apiKey stands in for the api object, which is usually a fresh literal each render
48
+ }, [apiKey]);
49
+ const status = useMemo(() => draftStatus(draft), [draft]);
50
+ // Computed whether or not the panel is open: an access loss is a finding, and a finding hidden
51
+ // behind a toggle nobody pressed is not a finding.
52
+ const accessLosses = useMemo(() => accessMatrix(draft.manifests, [ANONYMOUS, ...testPrincipals], draft.base).losses.length, [draft.manifests, draft.base, testPrincipals]);
53
+ const publish = useCallback(async () => {
54
+ setPhase({ status: 'publishing' });
55
+ try {
56
+ const outcome = await publishSnapshot(api ?? {}, { manifests: draft.manifests });
57
+ // Re-base on what was actually published, so the diff resets and a second publish of the
58
+ // same content is correctly reported as no change.
59
+ setDraft(createDraft(draft.manifests, outcome.snapshot.id));
60
+ setPhase({ status: 'published', outcome });
61
+ onPublished?.(outcome);
62
+ }
63
+ catch (error) {
64
+ const apiError = error instanceof RegistryApiError ? error : null;
65
+ setPhase({
66
+ status: 'error',
67
+ error: asError(error),
68
+ findings: apiError?.findings ?? [],
69
+ notes: apiError?.descriptorNotes ?? [],
70
+ });
71
+ }
72
+ }, [api, draft.manifests, onPublished]);
73
+ if (phase.status === 'loading') {
74
+ return (_jsx("div", { className: rootClass(className), ...themeAttr(theme), children: _jsx("p", { className: "braid-console__empty", children: "Loading the pinned registry\u2026" }) }));
75
+ }
76
+ return (_jsxs("div", { className: rootClass(className), ...themeAttr(theme), children: [_jsxs("div", { className: "braid-console__header", children: [_jsx("h2", { className: "braid-console__title", children: "Edit registry" }), _jsx("span", { className: "braid-console__count", children: draft.baseId ? (_jsxs(_Fragment, { children: ["from ", _jsx("code", { className: "braid-console__mono", children: draft.baseId })] })) : ('nothing published yet') }), _jsx("span", { className: "braid-console__spacer" }), _jsx("button", { className: "braid-console__retry", type: "button", onClick: () => setDraft(addFragment(draft)), children: "Add fragment" })] }), phase.status === 'error' && _jsx(ErrorPanel, { phase: phase }), phase.status === 'published' && _jsx(PublishedPanel, { outcome: phase.outcome }), draft.manifests.length === 0 ? (_jsx("p", { className: "braid-console__empty", children: "No fragments. Add one to get started." })) : (_jsx("ul", { className: "braid-console__list", children: draft.manifests.map((manifest, index) => (_jsx(FragmentRow, { manifest: manifest, findings: status.findings.filter((finding) => finding.fragmentIds.includes(manifest.id)), expanded: expanded === index, onToggle: () => setExpanded(expanded === index ? null : index), onChange: (patch) => setDraft(updateFragment(draft, index, patch)), onRemove: () => {
77
+ setDraft(removeFragment(draft, index));
78
+ setExpanded(null);
79
+ } }, index))) })), showDiff && _jsx(DiffPanel, { changes: status.diff }), showAccess && (_jsx(AccessPanel, { manifests: draft.manifests, base: draft.base, principals: testPrincipals, onPrincipalsChange: setPrincipals })), _jsx(PublishBar, { status: status, phase: phase, showDiff: showDiff, onToggleDiff: () => setShowDiff(!showDiff), showAccess: showAccess, onToggleAccess: () => setShowAccess(!showAccess), accessLosses: accessLosses, onReset: () => setDraft(resetDraft(draft)), onPublish: publish })] }));
80
+ }
81
+ function FragmentRow({ manifest, findings, expanded, onToggle, onChange, onRemove, }) {
82
+ const errors = findings.filter((finding) => finding.severity === 'error');
83
+ const fieldsId = `braid-fields-${manifest.id || 'new'}`;
84
+ return (_jsxs("li", { className: `braid-console__card${expanded ? ' is-open' : ''}`, children: [_jsxs("div", { className: "braid-console__cardhead", children: [_jsxs("button", { className: "braid-console__disclose", type: "button", onClick: onToggle, "aria-expanded": expanded, "aria-controls": fieldsId, children: [_jsx("span", { className: "braid-console__caret", "aria-hidden": "true", children: "\u25B8" }), _jsx("span", { className: "braid-console__id", children: manifest.id || '(no id)' })] }), _jsx("span", { className: "braid-console__mono", children: String(manifest.endpoint || '(no endpoint)') }), !expanded && manifest.pierce?.length ? (_jsxs("span", { className: "braid-console__cardmeta", children: ["pierces ", _jsx("span", { className: "braid-console__mono", children: formatList(manifest.pierce) })] })) : null, _jsx("span", { className: "braid-console__spacer" }), errors.length > 0 && (_jsxs("span", { className: "braid-console__badge braid-console__badge--error", children: [errors.length, " error"] })), _jsx("button", { className: "braid-console__ghost", type: "button", onClick: onToggle, "aria-expanded": expanded, "aria-controls": fieldsId, children: expanded ? 'Done' : 'Edit' }), _jsx("button", { className: "braid-console__ghost", type: "button", onClick: onRemove, "aria-label": `Remove ${manifest.id}`, children: "Remove" })] }), findings.length > 0 && (_jsx("ul", { className: "braid-console__findings", children: findings.map((finding, index) => (_jsxs("li", { className: `braid-console__finding braid-console__finding--${finding.severity}`, children: [finding.message, finding.hint && _jsxs("span", { className: "braid-console__desc", children: [" ", finding.hint] })] }, index))) })), expanded && _jsx(FragmentFields, { manifest: manifest, onChange: onChange, id: fieldsId })] }));
85
+ }
86
+ function FragmentFields({ manifest, onChange, id, }) {
87
+ const endpointIsFunction = typeof manifest.endpoint === 'function';
88
+ return (_jsxs("div", { className: "braid-console__fields", id: id, children: [_jsx(Field, { label: "id", hint: "addresses the fragment; no \u201C/\u201D", children: _jsx("input", { value: manifest.id, onChange: (event) => onChange({ id: event.target.value }) }) }), _jsx(Field, { label: "endpoint", hint: endpointIsFunction ? 'an in-process fetch function' : 'absolute URL', owner: "gateway", children: _jsx("input", { value: endpointIsFunction ? '(function)' : String(manifest.endpoint ?? ''), disabled: endpointIsFunction, onChange: (event) => onChange({ endpoint: event.target.value }) }) }), _jsx(Field, { label: "pierce", hint: "page URL patterns, comma separated", owner: "gateway", children: _jsx("input", { value: formatList(manifest.pierce), onChange: (event) => onChange({ pierce: parseList(event.target.value) }) }) }), _jsx(Field, { label: "title", children: _jsx("input", { value: manifest.title ?? '', onChange: (event) => onChange({ title: event.target.value }) }) }), _jsx(Field, { label: "description", children: _jsx("input", { value: manifest.description ?? '', onChange: (event) => onChange({ description: event.target.value }) }) }), _jsx(Field, { label: "tags", hint: "comma separated", children: _jsx("input", { value: formatList(manifest.tags), onChange: (event) => onChange({ tags: parseList(event.target.value) }) }) }), _jsx(Field, { label: "adapter", children: _jsxs("select", { value: manifest.adapter ?? '', onChange: (event) => onChange({ adapter: event.target.value }), children: [_jsx("option", { value: "", children: "compat (default)" }), _jsx("option", { value: "compat", children: "compat" }), _jsx("option", { value: "custom-element", children: "custom-element" })] }) }), manifest.adapter === 'custom-element' && (_jsxs(_Fragment, { children: [_jsx(Field, { label: "entry", hint: "module to evaluate in the realm", children: _jsx("input", { value: manifest.entry ?? '', onChange: (event) => onChange({ entry: event.target.value }) }) }), _jsx(Field, { label: "element", hint: "tag name that module defines", children: _jsx("input", { value: manifest.element ?? '', onChange: (event) => onChange({ element: event.target.value }) }) })] })), _jsx(Field, { label: "fallback", hint: "when SSR of this fragment fails", owner: "gateway", children: _jsxs("select", { value: manifest.fallback ?? '', onChange: (event) => onChange({ fallback: (event.target.value || undefined) }), children: [_jsx("option", { value: "", children: "placeholder (default)" }), _jsx("option", { value: "placeholder", children: "placeholder" }), _jsx("option", { value: "omit", children: "omit" }), _jsx("option", { value: "error-html", children: "error-html" })] }) }), _jsx(Field, { label: "access.list", hint: "roles, any-of \u2014 blank is public", owner: "gateway", children: _jsx("input", { value: formatList(manifest.access?.list?.roles), onChange: (event) => onChange({ access: withRoles(manifest, 'list', parseList(event.target.value)) }) }) }), _jsx(Field, { label: "access.fetch", hint: "roles, any-of \u2014 blank is public", owner: "gateway", children: _jsx("input", { value: formatList(manifest.access?.fetch?.roles), onChange: (event) => onChange({ access: withRoles(manifest, 'fetch', parseList(event.target.value)) }) }) })] }));
89
+ }
90
+ function Field({ label, hint, owner, children, }) {
91
+ return (_jsxs("label", { className: "braid-console__field", children: [_jsxs("span", { className: "braid-console__fieldlabel", children: [label, owner === 'gateway' && (_jsx("span", { className: "braid-console__owner", title: "Gateway-owned: routing or exposure", children: "gateway" }))] }), children, hint && _jsx("span", { className: "braid-console__desc", children: hint })] }));
92
+ }
93
+ function DiffPanel({ changes }) {
94
+ if (changes.identical) {
95
+ return _jsx("p", { className: "braid-console__empty", children: "No changes yet." });
96
+ }
97
+ return (_jsxs("div", { className: "braid-console__diff", children: [changes.added.map((manifest) => (_jsxs("div", { className: "braid-console__diffline braid-console__diffline--add", children: ["+ ", manifest.id] }, `+${manifest.id}`))), changes.removed.map((manifest) => (_jsxs("div", { className: "braid-console__diffline braid-console__diffline--remove", children: ["\u2212 ", manifest.id] }, `-${manifest.id}`))), changes.changed.map(({ id, changes: fields }) => (_jsxs("div", { className: "braid-console__diffline", children: [_jsxs("div", { children: ["~ ", id] }), fields.map((change) => (_jsxs("div", { className: "braid-console__diffield", children: [_jsx("span", { className: "braid-console__mono", children: change.field }), ' ', _jsx("span", { className: `braid-console__owner braid-console__owner--${change.owner}`, children: change.owner }), _jsxs("div", { className: "braid-console__mono", children: [short(change.before), " \u2192 ", short(change.after)] })] }, change.field)))] }, `~${id}`)))] }));
98
+ }
99
+ function PublishBar({ status, phase, showDiff, onToggleDiff, showAccess, onToggleAccess, accessLosses, onReset, onPublish, }) {
100
+ const errors = status.findings.filter((finding) => finding.severity === 'error').length;
101
+ const warnings = status.findings.length - errors;
102
+ return (_jsxs("div", { className: "braid-console__bar", children: [_jsx("span", { className: errors > 0 ? 'braid-console__barstate--error' : 'braid-console__barstate', children: errors > 0
103
+ ? `${errors} error${errors === 1 ? '' : 's'} — cannot publish`
104
+ : status.clean
105
+ ? 'No changes'
106
+ : `Ready${warnings > 0 ? ` — ${warnings} warning${warnings === 1 ? '' : 's'}` : ''}` }), _jsx("span", { className: "braid-console__spacer" }), accessLosses > 0 && (_jsxs("span", { className: "braid-console__barstate--error", children: [accessLosses, " access loss", accessLosses === 1 ? '' : 'es'] })), _jsx("button", { className: "braid-console__ghost", type: "button", onClick: onToggleAccess, children: showAccess ? 'Hide access' : 'Show access' }), _jsx("button", { className: "braid-console__ghost", type: "button", onClick: onToggleDiff, children: showDiff ? 'Hide changes' : 'Show changes' }), _jsx("button", { className: "braid-console__ghost", type: "button", onClick: onReset, disabled: status.clean, children: "Discard" }), _jsx("button", { className: "braid-console__primary", type: "button", onClick: onPublish, disabled: status.blocked || status.clean || phase.status === 'publishing', children: phase.status === 'publishing' ? 'Publishing…' : 'Publish' })] }));
107
+ }
108
+ function PublishedPanel({ outcome }) {
109
+ return (_jsxs("div", { className: "braid-console__notice braid-console__notice--ok", role: "status", children: [_jsx("span", { "aria-hidden": "true", children: "\u2713" }), _jsxs("span", { children: ["Published ", _jsx("code", { className: "braid-console__mono", children: outcome.snapshot.id }), " \u2014", ' ', outcome.snapshot.fragmentCount, " fragment", outcome.snapshot.fragmentCount === 1 ? '' : 's', outcome.pinned ? ', now pinned.' : ', not pinned.', ' ', outcome.pinned && 'Gateways pick it up on restart.'] })] }));
110
+ }
111
+ function ErrorPanel({ phase }) {
112
+ return (_jsxs("div", { className: "braid-console__error", role: "alert", children: [_jsx("h3", { children: "Could not publish" }), _jsx("p", { children: phase.error.message }), phase.findings.length > 0 && (_jsx("ul", { className: "braid-console__findings", children: phase.findings.map((finding, index) => (_jsx("li", { children: finding.message }, index))) })), phase.notes.length > 0 && (_jsx("ul", { className: "braid-console__findings", children: phase.notes.map((note, index) => (_jsx("li", { children: note.message }, index))) }))] }));
113
+ }
114
+ function withRoles(manifest, key, roles) {
115
+ const access = { ...(manifest.access ?? {}) };
116
+ if (roles.length === 0)
117
+ delete access[key];
118
+ else
119
+ access[key] = { ...access[key], roles };
120
+ return access;
121
+ }
122
+ function short(value) {
123
+ if (value === undefined)
124
+ return '(unset)';
125
+ if (typeof value === 'function')
126
+ return '(function)';
127
+ const json = JSON.stringify(value);
128
+ return json.length > 48 ? `${json.slice(0, 45)}…` : json;
129
+ }
130
+ const rootClass = (className) => `braid-console${className ? ` ${className}` : ''}`;
131
+ const themeAttr = (theme) => (theme ? { 'data-theme': theme } : {});
132
+ const asError = (error) => (error instanceof Error ? error : new Error(String(error)));
133
+ //# sourceMappingURL=registry-editor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-editor.js","sourceRoot":"","sources":["../../../../../libs/braid-console/src/lib/registry-editor.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The console's styles, as a string injected once at mount.
3
+ *
4
+ * Two constraints drive every choice here, both from being a *library* that mounts inside someone
5
+ * else's page:
6
+ *
7
+ * 1. **Every rule is scoped under `.braid-console`.** No resets, no bare element selectors, no
8
+ * `:root`. A library that styles `body` or `*` vandalizes its host, and the damage shows up in
9
+ * a part of the app nobody connects to this component.
10
+ * 2. **Everything themable is a custom property on the scope class**, so a host restyles by
11
+ * setting variables rather than escalating specificity. Dark mode follows
12
+ * `prefers-color-scheme`, and a host that knows better can force it with `data-theme` — which
13
+ * must win in *both* directions, since an admin shell may be dark inside a light OS.
14
+ *
15
+ * Shipped as a string rather than a `.css` import so the library has no build-tool requirements:
16
+ * a consumer bundling this needs no CSS loader, no `?inline` suffix, and no side-effect import
17
+ * they can forget.
18
+ *
19
+ * **The palette is Fluent's neutral ramp and brand blue**, because the console's likeliest home is
20
+ * an internal admin surface sitting beside Azure, Entra, or an in-house portal built to match one.
21
+ * A tool that looks foreign next to the tools it is used with reads as untrusted regardless of
22
+ * what it does. The ramp is expressed as tokens rather than literals precisely so a shop with a
23
+ * different system overrides eight variables instead of forking the stylesheet.
24
+ */
25
+ export declare const CONSOLE_STYLES = "\n.braid-console {\n --bc-bg: #ffffff;\n --bc-surface: #faf9f8;\n --bc-surface-alt: #f3f2f1;\n --bc-border: #e1dfdd;\n --bc-border-strong: #c8c6c4;\n --bc-text: #201f1e;\n --bc-muted: #605e5c;\n --bc-subtle: #8a8886;\n --bc-accent: #0f6cbd;\n --bc-accent-hover: #115ea3;\n --bc-accent-soft: #eff6fc;\n --bc-warn-bg: #fff4ce;\n --bc-warn-text: #6a4b16;\n --bc-warn-border: #f2d98c;\n --bc-ok: #0e700e;\n --bc-ok-soft: #dff6dd;\n --bc-err: #a4262c;\n --bc-err-soft: #fde7e9;\n --bc-radius: 4px;\n --bc-gap: 12px;\n --bc-shadow: 0 1.6px 3.6px rgba(0,0,0,0.10), 0 0.3px 0.9px rgba(0,0,0,0.07);\n --bc-font: \"Segoe UI\", \"Segoe UI Web (West European)\", ui-sans-serif, system-ui, -apple-system, Roboto, sans-serif;\n --bc-mono: ui-monospace, \"Cascadia Mono\", SFMono-Regular, Consolas, Menlo, monospace;\n\n color: var(--bc-text);\n background: var(--bc-bg);\n font-family: var(--bc-font);\n font-size: 14px;\n line-height: 1.4;\n container-type: inline-size;\n}\n\n@media (prefers-color-scheme: dark) {\n .braid-console {\n --bc-bg: #1b1a19;\n --bc-surface: #252423;\n --bc-surface-alt: #292827;\n --bc-border: #3b3a39;\n --bc-border-strong: #484644;\n --bc-text: #f3f2f1;\n --bc-muted: #c8c6c4;\n --bc-subtle: #a19f9d;\n --bc-accent: #479ef5;\n --bc-accent-hover: #62abf5;\n --bc-accent-soft: #082338;\n --bc-warn-bg: #3a2f0b;\n --bc-warn-text: #fce100;\n --bc-warn-border: #6b5a12;\n --bc-ok: #54b054;\n --bc-ok-soft: #052505;\n --bc-err: #f1707b;\n --bc-err-soft: #3b1216;\n --bc-shadow: 0 1.6px 3.6px rgba(0,0,0,0.4), 0 0.3px 0.9px rgba(0,0,0,0.3);\n }\n}\n\n/* An explicit host choice wins over the OS in both directions. */\n.braid-console[data-theme='light'] {\n --bc-bg: #ffffff; --bc-surface: #faf9f8; --bc-surface-alt: #f3f2f1;\n --bc-border: #e1dfdd; --bc-border-strong: #c8c6c4;\n --bc-text: #201f1e; --bc-muted: #605e5c; --bc-subtle: #8a8886;\n --bc-accent: #0f6cbd; --bc-accent-hover: #115ea3; --bc-accent-soft: #eff6fc;\n --bc-warn-bg: #fff4ce; --bc-warn-text: #6a4b16; --bc-warn-border: #f2d98c;\n --bc-ok: #0e700e; --bc-ok-soft: #dff6dd; --bc-err: #a4262c; --bc-err-soft: #fde7e9;\n --bc-shadow: 0 1.6px 3.6px rgba(0,0,0,0.10), 0 0.3px 0.9px rgba(0,0,0,0.07);\n}\n.braid-console[data-theme='dark'] {\n --bc-bg: #1b1a19; --bc-surface: #252423; --bc-surface-alt: #292827;\n --bc-border: #3b3a39; --bc-border-strong: #484644;\n --bc-text: #f3f2f1; --bc-muted: #c8c6c4; --bc-subtle: #a19f9d;\n --bc-accent: #479ef5; --bc-accent-hover: #62abf5; --bc-accent-soft: #082338;\n --bc-warn-bg: #3a2f0b; --bc-warn-text: #fce100; --bc-warn-border: #6b5a12;\n --bc-ok: #54b054; --bc-ok-soft: #052505; --bc-err: #f1707b; --bc-err-soft: #3b1216;\n --bc-shadow: 0 1.6px 3.6px rgba(0,0,0,0.4), 0 0.3px 0.9px rgba(0,0,0,0.3);\n}\n\n.braid-console *, .braid-console *::before, .braid-console *::after { box-sizing: border-box; }\n\n/* --- shell -------------------------------------------------------------- */\n\n/* The chrome an operator reads before anything else: what this is, which gateway, how fresh. */\n.braid-console__shell { display: flex; flex-direction: column; gap: 0; }\n\n.braid-console__titlebar {\n display: flex; align-items: center; gap: 10px; flex-wrap: wrap;\n padding: 0 0 10px;\n}\n.braid-console__producttitle { font-size: 20px; font-weight: 600; margin: 0; letter-spacing: -0.01em; }\n.braid-console__breadcrumb { color: var(--bc-subtle); font-size: 13px; display: flex; align-items: center; gap: 6px; }\n.braid-console__breadcrumb code { font-family: var(--bc-mono); font-size: 12px; color: var(--bc-muted); }\n\n/* Fluent's command bar: actions live on one line above the content, left-aligned, icon-led. */\n.braid-console__commandbar {\n display: flex; align-items: center; gap: 4px; flex-wrap: wrap;\n border-top: 1px solid var(--bc-border); border-bottom: 1px solid var(--bc-border);\n padding: 6px 0; margin-bottom: var(--bc-gap);\n}\n.braid-console__command {\n font: inherit; font-size: 13px; color: inherit; background: transparent; border: 1px solid transparent;\n border-radius: var(--bc-radius); padding: 5px 10px; cursor: pointer;\n display: inline-flex; align-items: center; gap: 6px;\n}\n.braid-console__command:hover { background: var(--bc-surface-alt); }\n.braid-console__command:disabled { opacity: 0.4; cursor: not-allowed; background: transparent; }\n.braid-console__command:focus-visible { outline: 2px solid var(--bc-accent); outline-offset: 1px; }\n.braid-console__commandicon { font-size: 13px; line-height: 1; color: var(--bc-accent); }\n.braid-console__commandsep { width: 1px; align-self: stretch; background: var(--bc-border); margin: 2px 4px; }\n\n/* Tabs (Fluent \"pivot\"): an underline on the selected one, never a filled pill. */\n.braid-console__tabs { display: flex; align-items: center; gap: 2px; }\n.braid-console__tab {\n font: inherit; font-size: 14px; color: var(--bc-muted); background: transparent;\n border: 0; border-bottom: 2px solid transparent; cursor: pointer;\n padding: 7px 10px; display: inline-flex; align-items: center; gap: 6px;\n}\n.braid-console__tab:hover { color: var(--bc-text); }\n.braid-console__tab[aria-selected='true'] { color: var(--bc-text); font-weight: 600; border-bottom-color: var(--bc-accent); }\n.braid-console__tab:focus-visible { outline: 2px solid var(--bc-accent); outline-offset: -2px; }\n.braid-console__tabcount {\n font-size: 11px; font-weight: 600; background: var(--bc-surface-alt); color: var(--bc-muted);\n border-radius: 9px; padding: 0 6px; font-variant-numeric: tabular-nums;\n}\n\n/* --- summary strip ------------------------------------------------------ */\n\n/* Four numbers an operator wants before scrolling: scale, composition, and what is gated. */\n.braid-console__stats { display: flex; gap: 1px; background: var(--bc-border); border: 1px solid var(--bc-border);\n border-radius: var(--bc-radius); overflow: hidden; margin-bottom: var(--bc-gap); flex-wrap: wrap; }\n.braid-console__stat { background: var(--bc-bg); padding: 10px 14px; flex: 1 1 auto; min-width: 8rem; }\n.braid-console__statvalue { font-size: 20px; font-weight: 600; font-variant-numeric: tabular-nums; display: block; line-height: 1.2; }\n.braid-console__statlabel { font-size: 12px; color: var(--bc-muted); }\n.braid-console__stat--warn .braid-console__statvalue { color: var(--bc-warn-text); }\n\n.braid-console__header {\n display: flex; flex-wrap: wrap; align-items: center; gap: var(--bc-gap);\n padding-bottom: var(--bc-gap);\n}\n.braid-console__title { font-size: 15px; font-weight: 600; margin: 0; }\n.braid-console__count { color: var(--bc-muted); font-variant-numeric: tabular-nums; font-size: 13px; }\n.braid-console__spacer { margin-left: auto; }\n\n.braid-console__search {\n font: inherit; color: inherit; background: var(--bc-bg);\n border: 1px solid var(--bc-border-strong); border-radius: var(--bc-radius);\n padding: 6px 10px; min-width: 15rem;\n}\n.braid-console__search::placeholder { color: var(--bc-subtle); }\n.braid-console__search:hover { border-color: var(--bc-muted); }\n/* Fluent's field focus: the border thickens on the accent edge rather than a ring floating outside. */\n.braid-console__search:focus-visible { outline: none; border-color: var(--bc-accent); box-shadow: inset 0 -2px 0 0 var(--bc-accent); }\n\n.braid-console__notice {\n display: flex; gap: 8px; align-items: flex-start;\n background: var(--bc-warn-bg); color: var(--bc-warn-text);\n border: 1px solid var(--bc-warn-border); border-left: 3px solid var(--bc-warn-text);\n border-radius: var(--bc-radius); padding: 9px 12px; margin-bottom: var(--bc-gap); font-size: 13px;\n}\n\n/* --- table -------------------------------------------------------------- */\n\n.braid-console__table { width: 100%; border-collapse: collapse; }\n.braid-console__table th {\n text-align: left; font-size: 12px; font-weight: 600; color: var(--bc-muted);\n padding: 8px 12px; border-bottom: 1px solid var(--bc-border-strong);\n position: sticky; top: 0; background: var(--bc-bg); z-index: 1;\n}\n.braid-console__table td { padding: 10px 12px; border-bottom: 1px solid var(--bc-border); vertical-align: top; }\n.braid-console__table tbody tr:hover { background: var(--bc-surface); }\n/* A 2px accent bar on the hovered row, the way a Fluent DetailsList marks the active one. */\n.braid-console__table tbody tr { box-shadow: inset 2px 0 0 0 transparent; }\n.braid-console__table tbody tr:hover { box-shadow: inset 2px 0 0 0 var(--bc-accent); }\n\n.braid-console__id { font-weight: 600; }\n.braid-console__desc { color: var(--bc-muted); margin-top: 2px; font-size: 13px; }\n.braid-console__mono { font-family: var(--bc-mono); font-size: 12.5px; color: var(--bc-muted); }\n.braid-console__patterns { display: flex; flex-direction: column; gap: 2px; }\n\n.braid-console__tag {\n display: inline-block; font-size: 11px; padding: 1px 7px; margin: 4px 4px 0 0;\n background: var(--bc-surface-alt); border: 1px solid var(--bc-border); border-radius: 3px; color: var(--bc-muted);\n}\n.braid-console__badge {\n display: inline-block; font-size: 11.5px; padding: 1px 7px; font-weight: 600;\n border-radius: 3px; border: 1px solid var(--bc-border);\n}\n.braid-console__badge--loadable { color: var(--bc-ok); border-color: transparent; background: var(--bc-ok-soft); }\n.braid-console__badge--gated { color: var(--bc-muted); background: var(--bc-surface-alt); border-color: transparent; }\n\n.braid-console__empty { padding: 40px 10px; text-align: center; color: var(--bc-muted); }\n.braid-console__error {\n border: 1px solid var(--bc-err); border-left: 3px solid var(--bc-err);\n background: var(--bc-err-soft); color: var(--bc-text);\n border-radius: var(--bc-radius); padding: 14px 16px;\n}\n.braid-console__error h3 { margin: 0 0 4px; font-size: 14px; color: var(--bc-err); }\n.braid-console__retry {\n font: inherit; color: inherit; background: var(--bc-bg); cursor: pointer; margin-top: 10px;\n border: 1px solid var(--bc-border-strong); border-radius: var(--bc-radius); padding: 5px 12px;\n}\n.braid-console__retry:hover { background: var(--bc-surface-alt); }\n\n/* --- topology graph ----------------------------------------------------- */\n\n.braid-console__graphwrap { display: flex; gap: var(--bc-gap); align-items: flex-start; }\n.braid-console__graphmain { flex: 1 1 auto; min-width: 0; overflow-x: auto; }\n\n.braid-console__collabels {\n display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;\n font-size: 11px; font-weight: 600; color: var(--bc-subtle);\n text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 6px;\n}\n.braid-console__collabels span:nth-child(2) { text-align: center; }\n.braid-console__collabels span:nth-child(3) { text-align: right; }\n\n.braid-console__graph { width: 100%; min-width: 480px; display: block; overflow: visible; }\n\n.braid-console__edge { fill: none; stroke: var(--bc-border-strong); stroke-width: 1.25; transition: stroke 0.12s, opacity 0.12s; }\n.braid-console__edge--served-by { stroke-dasharray: 3 3; }\n.braid-console__edge.is-lit { stroke: var(--bc-accent); stroke-width: 2; }\n.braid-console__edge.is-dim { opacity: 0.2; }\n\n.braid-console__node { cursor: pointer; transition: opacity 0.12s; }\n.braid-console__node.is-dim { opacity: 0.3; }\n.braid-console__nodebox { fill: var(--bc-bg); stroke: var(--bc-border-strong); stroke-width: 1; }\n.braid-console__node:hover .braid-console__nodebox { stroke: var(--bc-accent); }\n.braid-console__node:focus-visible { outline: none; }\n.braid-console__node:focus-visible .braid-console__nodebox { stroke: var(--bc-accent); stroke-width: 2; }\n.braid-console__node.is-selected .braid-console__nodebox { stroke: var(--bc-accent); stroke-width: 2; fill: var(--bc-accent-soft); }\n\n.braid-console__node--fragment .braid-console__nodebox { fill: var(--bc-surface-alt); }\n/* A shared route is the one state worth colouring: more than one fragment lands on this page. */\n.braid-console__node--route.is-shared .braid-console__nodebox { stroke: var(--bc-warn-border); border-left: 2px solid var(--bc-warn-text); }\n.braid-console__node--route.is-shared .braid-console__nodecount { fill: var(--bc-warn-text); font-weight: 700; }\n\n.braid-console__nodelabel { font-family: var(--bc-mono); font-size: 11.5px; fill: var(--bc-text); pointer-events: none; }\n.braid-console__nodecount { font-size: 11px; fill: var(--bc-subtle); pointer-events: none; font-variant-numeric: tabular-nums; }\n.braid-console__nodegate { fill: var(--bc-subtle); pointer-events: none; }\n\n.braid-console__graphnote {\n font-size: 12.5px; color: var(--bc-muted); margin: var(--bc-gap) 0 0;\n padding: 8px 10px; background: var(--bc-surface); border-radius: var(--bc-radius);\n border-left: 2px solid var(--bc-border-strong);\n}\n\n/* --- detail panel ------------------------------------------------------- */\n\n.braid-console__detail {\n flex: 0 0 260px; border: 1px solid var(--bc-border); border-radius: var(--bc-radius);\n background: var(--bc-surface); padding: 12px; font-size: 13px;\n}\n.braid-console__detail--empty { color: var(--bc-muted); }\n.braid-console__detailhint { font-size: 12px; color: var(--bc-subtle); margin: 8px 0 0; line-height: 1.45; }\n.braid-console__detailhead { display: flex; align-items: center; gap: 8px; }\n.braid-console__detailclose {\n margin-left: auto; font: inherit; background: transparent; border: 0; color: var(--bc-muted);\n cursor: pointer; border-radius: 3px; padding: 2px 6px; line-height: 1;\n}\n.braid-console__detailclose:hover { background: var(--bc-surface-alt); color: var(--bc-text); }\n.braid-console__detailtitle { font-size: 15px; margin: 6px 0 4px; font-family: var(--bc-mono); word-break: break-all; }\n.braid-console__detaildesc { color: var(--bc-muted); margin: 0 0 6px; line-height: 1.45; }\n.braid-console__detailwarn { color: var(--bc-warn-text); margin: 8px 0 0; font-size: 12.5px; line-height: 1.45; }\n\n.braid-console__kind {\n font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600;\n border-radius: 3px; padding: 2px 6px; background: var(--bc-surface-alt); color: var(--bc-muted);\n}\n.braid-console__kind--route { color: var(--bc-accent); background: var(--bc-accent-soft); }\n\n.braid-console__props { display: grid; grid-template-columns: auto 1fr; gap: 4px 10px; margin: 10px 0 0; }\n.braid-console__props dt { color: var(--bc-subtle); font-size: 12px; }\n.braid-console__props dd { margin: 0; }\n\n.braid-console__detailsection { margin-top: 12px; border-top: 1px solid var(--bc-border); padding-top: 10px; }\n.braid-console__detailsection h4 { margin: 0 0 6px; font-size: 12px; color: var(--bc-subtle); text-transform: uppercase; letter-spacing: 0.05em; }\n.braid-console__peerlist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 3px; }\n\n/* --- integration dialog -------------------------------------------------- */\n\n.braid-console__scrim {\n position: fixed; inset: 0; z-index: 40; display: flex; align-items: center; justify-content: center;\n background: rgba(0,0,0,0.4); padding: 24px;\n}\n.braid-console__dialog {\n background: var(--bc-bg); border: 1px solid var(--bc-border); border-radius: 6px;\n box-shadow: 0 6.4px 14.4px rgba(0,0,0,0.13), 0 1.2px 3.6px rgba(0,0,0,0.11);\n width: min(720px, 100%); max-height: 100%; overflow-y: auto; padding: 16px;\n}\n.braid-console__dialoghead { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }\n.braid-console__dialogtitle { margin: 0; font-size: 16px; font-weight: 600; }\n.braid-console__dialogtitle code { font-family: var(--bc-mono); font-size: 15px; }\n.braid-console__dialoghead .braid-console__detailclose { margin-left: auto; }\n\n.braid-console__code {\n margin: 10px 0 0; padding: 12px; overflow-x: auto;\n background: var(--bc-surface-alt); border: 1px solid var(--bc-border); border-radius: var(--bc-radius);\n font-family: var(--bc-mono); font-size: 12.5px; line-height: 1.55; white-space: pre;\n}\n.braid-console__code:focus-visible { outline: 2px solid var(--bc-accent); outline-offset: 1px; }\n\n.braid-console__dialogfoot { display: flex; align-items: center; gap: 12px; margin-top: 12px; flex-wrap: wrap; }\n.braid-console__dialogfoot .braid-console__hint { font-size: 12px; color: var(--bc-subtle); }\n.braid-console__dialogfoot code { font-family: var(--bc-mono); }\n.braid-console__dialogfoot kbd {\n font-family: var(--bc-mono); font-size: 11px; border: 1px solid var(--bc-border-strong);\n border-bottom-width: 2px; border-radius: 3px; padding: 0 4px; background: var(--bc-bg);\n}\n\n/* --- editor ------------------------------------------------------------- */\n\n.braid-console__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }\n.braid-console__card { border: 1px solid var(--bc-border); border-radius: var(--bc-radius); background: var(--bc-bg); }\n.braid-console__card:hover { border-color: var(--bc-border-strong); }\n.braid-console__cardhead { display: flex; align-items: center; gap: var(--bc-gap); padding: 10px 12px; flex-wrap: wrap; }\n\n.braid-console__card.is-open { border-color: var(--bc-accent); box-shadow: var(--bc-shadow); }\n\n.braid-console__disclose {\n font: inherit; color: inherit; background: transparent; cursor: pointer;\n display: inline-flex; align-items: center; gap: 8px;\n border: 1px solid transparent; border-radius: var(--bc-radius); padding: 3px 8px 3px 4px; margin-left: -4px;\n}\n/* The row is a control, so it says so on hover rather than only when the pointer finds the glyph. */\n.braid-console__disclose:hover { background: var(--bc-surface-alt); border-color: var(--bc-border); }\n.braid-console__disclose:focus-visible { outline: 2px solid var(--bc-accent); outline-offset: 2px; }\n\n.braid-console__caret {\n display: inline-block; color: var(--bc-muted); font-size: 11px;\n transition: transform 0.12s ease; transform-origin: 50% 50%;\n}\n.braid-console__card.is-open .braid-console__caret { transform: rotate(90deg); }\n\n.braid-console__cardmeta { font-size: 12px; color: var(--bc-subtle); }\n\n.braid-console__ghost, .braid-console__primary {\n font: inherit; font-size: 13px; cursor: pointer; border-radius: var(--bc-radius); padding: 5px 12px;\n border: 1px solid var(--bc-border-strong); background: var(--bc-bg); color: inherit;\n}\n.braid-console__ghost:hover { background: var(--bc-surface-alt); }\n.braid-console__primary { background: var(--bc-accent); border-color: var(--bc-accent); color: #fff; font-weight: 600; }\n.braid-console__primary:hover { background: var(--bc-accent-hover); border-color: var(--bc-accent-hover); }\n.braid-console__ghost:disabled, .braid-console__primary:disabled { opacity: 0.45; cursor: not-allowed; }\n.braid-console__ghost:focus-visible, .braid-console__primary:focus-visible { outline: 2px solid var(--bc-accent); outline-offset: 2px; }\n\n.braid-console__badge--error { color: var(--bc-err); background: var(--bc-err-soft); border-color: transparent; }\n\n.braid-console__findings { list-style: none; margin: 0; padding: 0 12px 10px; display: flex; flex-direction: column; gap: 5px; }\n.braid-console__finding { font-size: 12.5px; padding: 4px 0 4px 10px; border-left: 2px solid var(--bc-border); line-height: 1.45; }\n.braid-console__finding--error { border-left-color: var(--bc-err); color: var(--bc-err); }\n.braid-console__finding--warning { border-left-color: var(--bc-warn-border); color: var(--bc-warn-text); }\n\n.braid-console__fields {\n display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\n gap: var(--bc-gap); padding: 12px; border-top: 1px solid var(--bc-border); background: var(--bc-surface);\n}\n.braid-console__field { display: flex; flex-direction: column; gap: 4px; }\n.braid-console__fieldlabel { font-size: 12px; font-weight: 600; color: var(--bc-muted); display: flex; align-items: center; gap: 6px; }\n.braid-console__field input, .braid-console__field select {\n font: inherit; font-size: 13px; color: inherit; background: var(--bc-bg);\n border: 1px solid var(--bc-border-strong); border-radius: var(--bc-radius); padding: 6px 9px; width: 100%;\n}\n.braid-console__field input:focus-visible, .braid-console__field select:focus-visible {\n outline: none; border-color: var(--bc-accent); box-shadow: inset 0 -2px 0 0 var(--bc-accent);\n}\n.braid-console__field input:disabled { opacity: 0.6; }\n\n.braid-console__owner {\n font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.04em;\n border: 1px solid var(--bc-border); border-radius: 3px; padding: 1px 5px; color: var(--bc-muted);\n}\n.braid-console__owner--gateway { color: var(--bc-warn-text); border-color: var(--bc-warn-border); background: var(--bc-warn-bg); }\n\n.braid-console__bar {\n position: sticky; bottom: 0; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;\n margin-top: var(--bc-gap); padding: 12px; background: var(--bc-surface);\n border: 1px solid var(--bc-border); border-radius: var(--bc-radius); box-shadow: var(--bc-shadow);\n}\n.braid-console__barstate { color: var(--bc-muted); font-size: 13px; }\n.braid-console__barstate--error { color: var(--bc-err); font-weight: 600; }\n\n.braid-console__notice--ok { background: var(--bc-ok-soft); color: var(--bc-ok); border-color: var(--bc-ok); border-left-color: var(--bc-ok); }\n\n.braid-console__diff {\n font-family: var(--bc-mono); font-size: 12.5px; padding: 12px; margin-top: var(--bc-gap);\n border: 1px solid var(--bc-border); border-radius: var(--bc-radius); background: var(--bc-surface);\n overflow-x: auto;\n}\n.braid-console__diffline { padding: 2px 0; }\n.braid-console__diffline--add { color: var(--bc-ok); }\n.braid-console__diffline--remove { color: var(--bc-err); }\n.braid-console__diffield { padding: 2px 0 2px 16px; color: var(--bc-muted); }\n\n/* --- access matrix ------------------------------------------------------ */\n\n.braid-console__access {\n margin-top: var(--bc-gap); padding: 12px;\n border: 1px solid var(--bc-border); border-radius: var(--bc-radius); background: var(--bc-surface);\n}\n.braid-console__accesshead { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }\n.braid-console__matrix { margin-top: 8px; background: var(--bc-bg); }\n.braid-console__matrix th, .braid-console__matrix td { padding: 6px 10px; }\n.braid-console__matrix th { white-space: nowrap; position: static; }\n.braid-console__remove { border: 0; padding: 0 4px; margin-left: 4px; font-size: 13px; line-height: 1; }\n\n.braid-console__mark { font-family: var(--bc-mono); }\n.braid-console__mark--allowed { color: var(--bc-ok); }\n.braid-console__mark--denied { color: var(--bc-muted); }\n.braid-console__mark--absent { color: var(--bc-muted); opacity: 0.6; }\n\n/* Visually hidden, still read aloud \u2014 the symbols carry meaning that colour alone would not. */\n.braid-console__sronly {\n position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;\n overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;\n}\n\n/* Container query, not a media query: the library's width is its host's business, not the\n viewport's. A console in a 400px sidebar should stack even on a wide screen. */\n@container (max-width: 860px) {\n .braid-console__graphwrap { flex-direction: column; }\n .braid-console__detail { flex: 1 1 auto; width: 100%; }\n}\n\n@container (max-width: 640px) {\n .braid-console__table thead { display: none; }\n .braid-console__table tr { display: block; padding: 8px 0; border-bottom: 1px solid var(--bc-border); }\n .braid-console__table td { display: block; border: 0; padding: 2px 12px; }\n .braid-console__stats { flex-direction: column; }\n}\n\n/* Motion is decoration here; the information is in position and colour, which do not move. */\n@media (prefers-reduced-motion: reduce) {\n .braid-console__edge, .braid-console__node, .braid-console__caret { transition: none; }\n}\n";
26
+ /** Injects the stylesheet once per document. Safe to call from every mounted instance. */
27
+ export declare function ensureStyles(doc?: Document): void;