@flaier/core 0.1.1 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["FlowTimelineRenderer","$attrs"],"sources":["../src/context.ts","../src/custom-nodes.ts","../src/catalog.ts","../src/code-node-sizing.ts","../src/composables/useDiagramExport.ts","../src/composables/useFlaierRuntime.ts","../src/twoslash.ts","../src/components/controls/TimelineControls.vue","../src/components/controls/TimelineControls.vue","../src/components/edges/ArchitectureSmoothEdge.vue","../src/components/edges/ArchitectureSmoothEdge.vue","../src/components/nodes/NodeSourceAnchor.vue","../src/components/nodes/NodeSourceAnchor.vue","../src/components/nodes/ArchitectureNode.vue","../src/components/nodes/ArchitectureNode.vue","../src/composables/useShiki.ts","../src/components/nodes/CodeNode.vue","../src/components/nodes/CodeNode.vue","../src/components/nodes/DecisionNode.vue","../src/components/nodes/DecisionNode.vue","../src/components/nodes/DescriptionNode.vue","../src/components/nodes/DescriptionNode.vue","../src/components/nodes/ErrorNode.vue","../src/components/nodes/ErrorNode.vue","../src/components/nodes/LinkNode.vue","../src/components/nodes/LinkNode.vue","../src/components/nodes/PayloadNode.vue","../src/components/nodes/PayloadNode.vue","../src/components/nodes/TriggerNode.vue","../src/components/nodes/TriggerNode.vue","../src/components/renderer/FlowTimelineRenderer.vue","../src/components/renderer/FlowTimelineRenderer.vue","../src/registry.ts","../src/components/Flaier.vue","../src/components/Flaier.vue","../src/composables/useFlaierFullscreen.ts","../src/components/FlaierPanel.vue","../src/components/FlaierPanel.vue","../src/composables/useTimeline.ts"],"sourcesContent":["import type { InjectionKey, Ref } from \"vue\";\nimport type { FlaierCustomNodeDefinitions, FlaierFlowOption, FlaierSpec } from \"./types\";\n\nexport interface FlaierRuntimeContext {\n spec: Ref<FlaierSpec | null>;\n interval: Ref<number>;\n nodes: Ref<FlaierCustomNodeDefinitions>;\n flowOptions: Ref<FlaierFlowOption[]>;\n activeFlowId: Ref<string | null>;\n setActiveFlow: (flowId: string) => void;\n}\n\nexport const flaierRuntimeKey: InjectionKey<FlaierRuntimeContext> = Symbol(\"flaier-runtime\");\n","import { defineComponent, markRaw, type Component } from \"vue\";\nimport type { FlaierCustomNodeDefinition, FlaierCustomNodeDefinitions } from \"./types\";\n\nconst RESERVED_FLAIER_NODE_NAMES = new Set([\n \"FlowTimeline\",\n \"ArchitectureNode\",\n \"TriggerNode\",\n \"CodeNode\",\n \"DecisionNode\",\n \"PayloadNode\",\n \"ErrorNode\",\n \"DescriptionNode\",\n \"LinkNode\",\n]);\n\nconst FlaierNullNode = defineComponent({\n name: \"FlaierNullNode\",\n setup() {\n return () => null;\n },\n});\n\nfunction normalizeFlaierCustomNodeDefinition(\n definition: FlaierCustomNodeDefinition,\n): FlaierCustomNodeDefinition {\n return {\n ...definition,\n component: markRaw(definition.component) as Component,\n };\n}\n\nexport function normalizeFlaierCustomNodes(\n nodes?: FlaierCustomNodeDefinitions,\n): FlaierCustomNodeDefinitions {\n if (!nodes) {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(nodes)\n .filter(([name]) => {\n if (!RESERVED_FLAIER_NODE_NAMES.has(name)) {\n return true;\n }\n\n console.warn(`[flaier] Ignoring custom node \"${name}\" because the name is reserved.`);\n return false;\n })\n .map(([name, definition]) => [name, normalizeFlaierCustomNodeDefinition(definition)]),\n );\n}\n\nexport function mergeFlaierCustomNodes(\n ...sources: Array<FlaierCustomNodeDefinitions | undefined>\n): FlaierCustomNodeDefinitions {\n return sources.reduce<FlaierCustomNodeDefinitions>((result, source) => {\n if (!source) {\n return result;\n }\n\n return {\n ...result,\n ...normalizeFlaierCustomNodes(source),\n };\n }, {});\n}\n\nexport function createFlaierCustomCatalogComponents(nodes?: FlaierCustomNodeDefinitions) {\n const normalizedNodes = normalizeFlaierCustomNodes(nodes);\n\n if (Object.keys(normalizedNodes).length === 0) {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(normalizedNodes).map(([name, definition]) => [\n name,\n {\n props: definition.props,\n description: definition.description,\n },\n ]),\n );\n}\n\nexport function createFlaierCustomRegistryComponents(nodes?: FlaierCustomNodeDefinitions) {\n const normalizedNodes = normalizeFlaierCustomNodes(nodes);\n\n if (Object.keys(normalizedNodes).length === 0) {\n return {};\n }\n\n return Object.fromEntries(\n Object.keys(normalizedNodes).map((name) => [name, FlaierNullNode]),\n ) as Record<string, Component>;\n}\n","import { defineCatalog } from \"@json-render/core\";\nimport { schema } from \"@json-render/vue\";\nimport { z } from \"zod\";\nimport { createFlaierCustomCatalogComponents } from \"./custom-nodes\";\nimport type { FlaierCatalogOptions } from \"./types\";\n\nexport const magicMoveStepSchema = z.object({\n code: z.string(),\n title: z.string().optional(),\n comment: z.string().optional(),\n story: z.string().optional(),\n speaker: z.string().optional(),\n});\n\nexport const twoslashHtmlSchema = z\n .object({\n dark: z.string().optional(),\n light: z.string().optional(),\n })\n .optional();\n\nexport const edgeTransitionKindSchema = z.enum([\n \"default\",\n \"success\",\n \"error\",\n \"warning\",\n \"retry\",\n \"async\",\n]);\n\nexport const edgeTransitionSchema = z.object({\n to: z.string(),\n label: z.string().optional(),\n description: z.string().optional(),\n kind: edgeTransitionKindSchema.optional(),\n protocol: z.string().optional(),\n transport: z.enum([\"sync\", \"async\"]).optional(),\n auth: z.string().optional(),\n contract: z.string().optional(),\n criticality: z.enum([\"low\", \"medium\", \"high\"]).optional(),\n});\n\nexport const sourceAnchorSchema = z.union([\n z.string(),\n z.object({\n path: z.string(),\n line: z.number().int().positive().optional(),\n column: z.number().int().positive().optional(),\n label: z.string().optional(),\n href: z.string().optional(),\n }),\n]);\n\nexport const architectureZoneSchema = z.object({\n id: z.string(),\n label: z.string(),\n description: z.string().optional(),\n color: z.string().optional(),\n padding: z.number().positive().optional(),\n});\n\nexport const architectureInterfaceSchema = z.object({\n name: z.string(),\n protocol: z.string().optional(),\n direction: z.enum([\"inbound\", \"outbound\", \"bidirectional\"]).optional(),\n contract: z.string().optional(),\n auth: z.string().optional(),\n notes: z.string().optional(),\n});\n\nexport const architectureDataAssetSchema = z.object({\n name: z.string(),\n kind: z.string().optional(),\n classification: z.enum([\"public\", \"internal\", \"confidential\", \"restricted\"]).optional(),\n retention: z.string().optional(),\n notes: z.string().optional(),\n});\n\nexport const architectureSecuritySchema = z.object({\n auth: z.string().optional(),\n encryption: z.string().optional(),\n pii: z.boolean().optional(),\n threatModel: z.string().optional(),\n});\n\nexport const architectureOperationsSchema = z.object({\n owner: z.string().optional(),\n slo: z.string().optional(),\n alert: z.string().optional(),\n runbook: z.string().optional(),\n});\n\nexport const architectureLinkSchema = z.object({\n label: z.string(),\n href: z.string(),\n});\n\nexport const flaierCatalogComponents = {\n components: {\n FlowTimeline: {\n props: z.object({\n title: z.string(),\n description: z.string().optional(),\n mode: z.enum([\"narrative\", \"architecture\"]).default(\"narrative\"),\n zones: z.array(architectureZoneSchema).optional(),\n direction: z.enum([\"horizontal\", \"vertical\"]).default(\"horizontal\"),\n minHeight: z.number().int().positive().optional(),\n layoutEngine: z.enum([\"dagre\", \"manual\"]).default(\"dagre\"),\n layoutRankSep: z.number().positive().optional(),\n layoutNodeSep: z.number().positive().optional(),\n layoutEdgeSep: z.number().positive().optional(),\n themeMode: z.enum([\"local\", \"document\"]).optional(),\n showHeaderOverlay: z.boolean().optional(),\n showExportControls: z.boolean().optional(),\n showThemeToggle: z.boolean().optional(),\n showArchitectureInspector: z.boolean().optional(),\n defaultArchitectureInspectorOpen: z.boolean().optional(),\n showArchitectureInspectorToggleText: z.boolean().optional(),\n }),\n description: \"Root timeline container that orchestrates a pipeline flow graph\",\n slots: [\"default\"],\n },\n ArchitectureNode: {\n props: z.object({\n label: z.string(),\n kind: z\n .enum([\"service\", \"database\", \"queue\", \"cache\", \"gateway\", \"external\", \"compute\"])\n .default(\"service\"),\n technology: z.string().optional(),\n runtime: z.string().optional(),\n owner: z.string().optional(),\n tier: z\n .enum([\"edge\", \"application\", \"integration\", \"data\", \"platform\", \"external\"])\n .optional(),\n status: z.enum([\"planned\", \"active\", \"degraded\", \"retired\"]).optional(),\n zone: z.string().optional(),\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n responsibilities: z.array(z.string()).optional(),\n capabilities: z.array(z.string()).optional(),\n interfaces: z.array(architectureInterfaceSchema).optional(),\n data: z.array(architectureDataAssetSchema).optional(),\n security: architectureSecuritySchema.optional(),\n operations: architectureOperationsSchema.optional(),\n links: z.array(architectureLinkSchema).optional(),\n sourceAnchor: sourceAnchorSchema.optional(),\n transitions: z.array(edgeTransitionSchema).optional(),\n }),\n description: \"Architecture/infrastructure component node for system diagrams\",\n },\n TriggerNode: {\n props: z.object({\n label: z.string(),\n description: z.string().optional(),\n color: z.string().default(\"#22c55e\"),\n sourceAnchor: sourceAnchorSchema.optional(),\n transitions: z.array(edgeTransitionSchema).optional(),\n }),\n description: \"Entry point node representing a trigger (cron, webhook, event)\",\n },\n CodeNode: {\n props: z.object({\n label: z.string(),\n file: z.string().optional(),\n sourceAnchor: sourceAnchorSchema.optional(),\n language: z.string().default(\"typescript\"),\n code: z.string(),\n comment: z.string().optional(),\n story: z.string().optional(),\n wrapLongLines: z.boolean().default(false),\n magicMoveSteps: z.array(magicMoveStepSchema).optional(),\n twoslash: z.boolean().optional(),\n twoslashHtml: twoslashHtmlSchema,\n transitions: z.array(edgeTransitionSchema).optional(),\n }),\n description:\n \"Code block with syntax highlighting, step-by-step magic-move transitions, optional twoslash callouts, and narration/story beats\",\n },\n DecisionNode: {\n props: z.object({\n label: z.string(),\n condition: z.string().optional(),\n description: z.string().optional(),\n sourceAnchor: sourceAnchorSchema.optional(),\n transitions: z.array(edgeTransitionSchema).optional(),\n }),\n description: \"Branch decision node that explains routing criteria before fan-out paths\",\n },\n PayloadNode: {\n props: z.object({\n label: z.string(),\n payload: z.string().optional(),\n before: z.string().optional(),\n after: z.string().optional(),\n format: z.enum([\"json\", \"yaml\", \"text\"]).default(\"json\"),\n description: z.string().optional(),\n sourceAnchor: sourceAnchorSchema.optional(),\n transitions: z.array(edgeTransitionSchema).optional(),\n }),\n description: \"Data-focused node for payload snapshots and before/after transformations\",\n },\n ErrorNode: {\n props: z.object({\n label: z.string(),\n message: z.string(),\n code: z.string().optional(),\n cause: z.string().optional(),\n mitigation: z.string().optional(),\n sourceAnchor: sourceAnchorSchema.optional(),\n transitions: z.array(edgeTransitionSchema).optional(),\n }),\n description: \"Failure node that captures error detail, cause, and recovery guidance\",\n },\n DescriptionNode: {\n props: z.object({\n label: z.string(),\n body: z.string(),\n sourceAnchor: sourceAnchorSchema.optional(),\n transitions: z.array(edgeTransitionSchema).optional(),\n }),\n description: \"Prose/text explanation node for documenting a pipeline step\",\n },\n LinkNode: {\n props: z.object({\n label: z.string(),\n href: z.string(),\n description: z.string().optional(),\n sourceAnchor: sourceAnchorSchema.optional(),\n transitions: z.array(edgeTransitionSchema).optional(),\n }),\n description: \"Clickable reference link to a file or URL\",\n },\n },\n};\n\nexport const catalog = defineCatalog(schema, {\n components: flaierCatalogComponents.components,\n actions: {},\n});\n\nexport function createFlaierCatalog<TNodes extends NonNullable<FlaierCatalogOptions[\"nodes\"]>>(\n options?: FlaierCatalogOptions<TNodes>,\n) {\n return defineCatalog(schema, {\n components: {\n ...flaierCatalogComponents.components,\n ...createFlaierCustomCatalogComponents(options?.nodes),\n },\n actions: {},\n });\n}\n","const CODE_NODE_MIN_WIDTH = 520;\nconst CODE_NODE_MAX_WIDTH = 2200;\nconst CODE_NODE_CHARACTER_WIDTH = 8.5;\nconst CODE_NODE_CHROME_WIDTH = 88;\n\nexport const CODE_NODE_MAX_INLINE_CHARS = Math.floor(\n (CODE_NODE_MAX_WIDTH - CODE_NODE_CHROME_WIDTH) / CODE_NODE_CHARACTER_WIDTH,\n);\n\nexport function estimateCodeNodeWidth(maxLineLength: number) {\n const safeLineLength = Number.isFinite(maxLineLength)\n ? Math.max(0, Math.floor(maxLineLength))\n : 0;\n\n const estimatedWidth = CODE_NODE_CHROME_WIDTH + safeLineLength * CODE_NODE_CHARACTER_WIDTH;\n\n return Math.min(CODE_NODE_MAX_WIDTH, Math.max(CODE_NODE_MIN_WIDTH, Math.ceil(estimatedWidth)));\n}\n\nexport function estimateCodeNodeCharsPerLine(nodeWidth: number) {\n const safeWidth = Number.isFinite(nodeWidth)\n ? Math.max(CODE_NODE_MIN_WIDTH, Math.floor(nodeWidth))\n : CODE_NODE_MIN_WIDTH;\n\n return Math.max(44, Math.floor((safeWidth - CODE_NODE_CHROME_WIDTH) / CODE_NODE_CHARACTER_WIDTH));\n}\n","export interface DiagramBounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport type DiagramExportFormat = \"png\" | \"pdf\";\n\nexport interface ExportFlowDiagramOptions {\n flowElement: HTMLElement;\n theme: \"dark\" | \"light\";\n bounds: DiagramBounds;\n fileNameBase: string;\n format: DiagramExportFormat;\n}\n\nconst EXPORT_PADDING_PX = 72;\nconst MAX_EXPORT_SIDE_PX = 6000;\nconst MAX_EXPORT_AREA_PX = 26_000_000;\n\nexport async function exportFlowDiagram(options: ExportFlowDiagramOptions) {\n if (typeof document === \"undefined\" || typeof window === \"undefined\") {\n throw new Error(\"Diagram export is only available in the browser.\");\n }\n\n const normalizedBounds = normalizeBounds(options.bounds);\n if (!normalizedBounds) {\n throw new Error(\"Diagram has no measurable bounds to export.\");\n }\n\n const capture = createCaptureStage({\n flowElement: options.flowElement,\n theme: options.theme,\n bounds: normalizedBounds,\n });\n\n let pngDataUrl = \"\";\n\n try {\n const { toPng } = await import(\"html-to-image\");\n\n await settleCaptureStage();\n\n pngDataUrl = await toPng(capture.stage, {\n width: capture.width,\n height: capture.height,\n pixelRatio: resolveExportPixelRatio(capture.width, capture.height),\n backgroundColor: capture.backgroundColor,\n cacheBust: true,\n });\n } finally {\n capture.destroy();\n }\n\n const safeBaseName = sanitizeFileName(options.fileNameBase || \"flow-diagram\");\n\n if (options.format === \"png\") {\n downloadDataUrl(pngDataUrl, `${safeBaseName}.png`);\n return;\n }\n\n const pdfBlob = await renderPdfBlob(pngDataUrl, capture.width, capture.height);\n downloadBlob(pdfBlob, `${safeBaseName}.pdf`);\n}\n\nfunction createCaptureStage({\n flowElement,\n theme,\n bounds,\n}: {\n flowElement: HTMLElement;\n theme: \"dark\" | \"light\";\n bounds: Required<DiagramBounds>;\n}) {\n const width = Math.ceil(bounds.width + EXPORT_PADDING_PX * 2);\n const height = Math.ceil(bounds.height + EXPORT_PADDING_PX * 2);\n const sourceRoot = flowElement.closest(\".flaier\") as HTMLElement | null;\n const sourceStyles = getComputedStyle(sourceRoot ?? flowElement);\n const wrapper = document.createElement(\"div\");\n wrapper.style.position = \"fixed\";\n wrapper.style.left = \"-100000px\";\n wrapper.style.top = \"0\";\n wrapper.style.width = \"0\";\n wrapper.style.height = \"0\";\n wrapper.style.overflow = \"hidden\";\n wrapper.style.pointerEvents = \"none\";\n\n const stage = document.createElement(\"div\");\n stage.className = \"flaier\";\n stage.dataset.theme = theme;\n stage.style.position = \"relative\";\n stage.style.width = `${width}px`;\n stage.style.height = `${height}px`;\n stage.style.overflow = \"hidden\";\n stage.style.pointerEvents = \"none\";\n\n for (let index = 0; index < sourceStyles.length; index += 1) {\n const key = sourceStyles.item(index);\n if (!key.startsWith(\"--\")) continue;\n\n const value = sourceStyles.getPropertyValue(key);\n if (!value) continue;\n stage.style.setProperty(key, value);\n }\n\n const backgroundColor = sourceStyles.getPropertyValue(\"--color-background\").trim() || \"#0b1120\";\n stage.style.background = backgroundColor;\n\n const flowClone = flowElement.cloneNode(true) as HTMLElement;\n flowClone.style.width = `${width}px`;\n flowClone.style.height = `${height}px`;\n flowClone.style.margin = \"0\";\n\n inlineSvgPresentationStyles(flowElement, flowClone);\n\n const transformPane = (flowClone.querySelector(\".vue-flow__transformationpane\") ??\n flowClone.querySelector(\".vue-flow__viewport\")) as HTMLElement | null;\n const exportTransform = `translate(${Math.round(EXPORT_PADDING_PX - bounds.x)}px, ${Math.round(EXPORT_PADDING_PX - bounds.y)}px) scale(1)`;\n\n if (transformPane) {\n transformPane.style.transformOrigin = \"0 0\";\n transformPane.style.transform = exportTransform;\n transformPane.style.opacity = \"1\";\n }\n\n const zoneOverlays = flowClone.querySelectorAll<HTMLElement>('[data-zone-overlay=\"true\"]');\n for (const overlay of zoneOverlays) {\n overlay.style.transformOrigin = \"0 0\";\n overlay.style.transform = exportTransform;\n }\n\n stage.appendChild(flowClone);\n wrapper.appendChild(stage);\n document.body.appendChild(wrapper);\n\n return {\n stage,\n width,\n height,\n backgroundColor,\n destroy() {\n wrapper.remove();\n },\n };\n}\n\nfunction normalizeBounds(bounds: DiagramBounds): Required<DiagramBounds> | null {\n if (!Number.isFinite(bounds.x) || !Number.isFinite(bounds.y)) {\n return null;\n }\n\n if (!Number.isFinite(bounds.width) || !Number.isFinite(bounds.height)) {\n return null;\n }\n\n const width = Math.max(1, Math.floor(bounds.width));\n const height = Math.max(1, Math.floor(bounds.height));\n\n return {\n x: Math.floor(bounds.x),\n y: Math.floor(bounds.y),\n width,\n height,\n };\n}\n\nfunction resolveExportPixelRatio(width: number, height: number) {\n let ratio = Math.max(1, Math.min(2, window.devicePixelRatio || 1));\n\n if (width * ratio > MAX_EXPORT_SIDE_PX) {\n ratio = MAX_EXPORT_SIDE_PX / width;\n }\n\n if (height * ratio > MAX_EXPORT_SIDE_PX) {\n ratio = Math.min(ratio, MAX_EXPORT_SIDE_PX / height);\n }\n\n const areaAtRatio = width * height * ratio * ratio;\n if (areaAtRatio > MAX_EXPORT_AREA_PX) {\n ratio = Math.min(ratio, Math.sqrt(MAX_EXPORT_AREA_PX / (width * height)));\n }\n\n return Math.max(0.45, ratio);\n}\n\nfunction inlineSvgPresentationStyles(sourceRoot: HTMLElement, clonedRoot: HTMLElement) {\n copyComputedSvgStyles(sourceRoot, clonedRoot, \".vue-flow__edge-path\", [\n \"fill\",\n \"stroke\",\n \"stroke-width\",\n \"stroke-linecap\",\n \"stroke-linejoin\",\n \"vector-effect\",\n \"filter\",\n \"opacity\",\n ]);\n}\n\nfunction copyComputedSvgStyles(\n sourceRoot: HTMLElement,\n clonedRoot: HTMLElement,\n selector: string,\n properties: string[],\n) {\n const sourceElements = sourceRoot.querySelectorAll<SVGElement>(selector);\n const clonedElements = clonedRoot.querySelectorAll<SVGElement>(selector);\n const total = Math.min(sourceElements.length, clonedElements.length);\n\n for (let index = 0; index < total; index += 1) {\n const sourceElement = sourceElements[index];\n const clonedElement = clonedElements[index];\n if (!sourceElement || !clonedElement) continue;\n\n const computedStyle = getComputedStyle(sourceElement);\n\n for (const property of properties) {\n const value = computedStyle.getPropertyValue(property);\n if (!value) continue;\n clonedElement.style.setProperty(property, value);\n }\n }\n}\n\nasync function settleCaptureStage() {\n if (typeof document !== \"undefined\" && \"fonts\" in document) {\n try {\n await document.fonts.ready;\n } catch {\n // Ignore font readiness failures and continue with the best available render.\n }\n }\n\n await waitForAnimationFrame();\n await waitForAnimationFrame();\n}\n\nfunction waitForAnimationFrame() {\n return new Promise<void>((resolve) => {\n window.requestAnimationFrame(() => resolve());\n });\n}\n\nasync function renderPdfBlob(pngDataUrl: string, widthPx: number, heightPx: number) {\n const jspdfModule = await import(\"jspdf\");\n const jsPDF = (jspdfModule.jsPDF ??\n (typeof jspdfModule.default === \"function\" ? jspdfModule.default : null) ??\n (jspdfModule.default as { jsPDF?: unknown } | undefined)?.jsPDF ??\n null) as\n | (new (options: { unit: string; format: [number, number]; compress: boolean }) => {\n addImage: (...args: unknown[]) => void;\n output: (type: \"blob\") => Blob;\n })\n | null;\n\n if (!jsPDF) {\n throw new Error(\"Could not load PDF runtime. Please try PNG export.\");\n }\n\n const pointPerPixel = 72 / 96;\n const pageWidth = Math.max(72, Math.round(widthPx * pointPerPixel));\n const pageHeight = Math.max(72, Math.round(heightPx * pointPerPixel));\n\n const pdf = new jsPDF({\n unit: \"pt\",\n format: [pageWidth, pageHeight],\n compress: true,\n });\n\n pdf.addImage(pngDataUrl, \"PNG\", 0, 0, pageWidth, pageHeight, undefined, \"FAST\");\n return pdf.output(\"blob\");\n}\n\nfunction sanitizeFileName(value: string) {\n const cleaned = value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n return cleaned || \"flow-diagram\";\n}\n\nfunction downloadDataUrl(dataUrl: string, fileName: string) {\n triggerDownload(dataUrl, fileName);\n}\n\nfunction downloadBlob(blob: Blob, fileName: string) {\n const url = URL.createObjectURL(blob);\n\n try {\n triggerDownload(url, fileName);\n } finally {\n setTimeout(() => {\n URL.revokeObjectURL(url);\n }, 30_000);\n }\n}\n\nfunction triggerDownload(href: string, fileName: string) {\n const anchor = document.createElement(\"a\");\n anchor.href = href;\n anchor.download = fileName;\n anchor.rel = \"noopener\";\n anchor.style.display = \"none\";\n\n document.body.appendChild(anchor);\n\n try {\n anchor.click();\n } finally {\n anchor.remove();\n }\n}\n","import { inject } from \"vue\";\nimport { flaierRuntimeKey } from \"../context\";\n\nexport function useFlaierRuntime() {\n const context = inject(flaierRuntimeKey);\n\n if (!context) {\n throw new Error(\"[flaier] Runtime context not found. Wrap components with <Flaier>.\");\n }\n\n return context;\n}\n","export type SupportedTwoslashLanguage = \"ts\" | \"tsx\";\n\nexport interface TwoslashHtml {\n dark?: string;\n light?: string;\n}\n\nconst TWOSLASH_HINT_PATTERN = /(?:\\^\\?|\\^\\||@errors\\b|@log\\b|@warn\\b|@annotate\\b|@include\\b)/m;\nconst TWOSLASH_LANGUAGE_ALIASES: Record<string, SupportedTwoslashLanguage> = {\n ts: \"ts\",\n typescript: \"ts\",\n tsx: \"tsx\",\n};\n\nexport function hasTwoslashHints(code: string) {\n return TWOSLASH_HINT_PATTERN.test(code);\n}\n\nexport function normalizeTwoslashLanguage(language?: string): SupportedTwoslashLanguage | null {\n const normalized = (language ?? \"typescript\").trim().toLowerCase();\n return TWOSLASH_LANGUAGE_ALIASES[normalized] ?? null;\n}\n\nexport function normalizeTwoslashHtml(value: unknown): TwoslashHtml | undefined {\n if (!value || typeof value !== \"object\") {\n return undefined;\n }\n\n const record = value as Record<string, unknown>;\n const dark = typeof record.dark === \"string\" && record.dark.length > 0 ? record.dark : undefined;\n const light =\n typeof record.light === \"string\" && record.light.length > 0 ? record.light : undefined;\n\n if (!dark && !light) {\n return undefined;\n }\n\n return { dark, light };\n}\n\nexport function hasTwoslashHtml(value: TwoslashHtml | undefined) {\n return Boolean(value?.dark || value?.light);\n}\n\nexport function resolveTwoslashHtmlForTheme(\n value: TwoslashHtml | undefined,\n theme: \"dark\" | \"light\",\n) {\n if (!value) {\n return \"\";\n }\n\n return theme === \"light\" ? (value.light ?? value.dark ?? \"\") : (value.dark ?? value.light ?? \"\");\n}\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\n\ninterface ChoiceOption {\n id: string;\n label: string;\n description?: string;\n kind?: \"default\" | \"success\" | \"error\" | \"warning\" | \"retry\" | \"async\";\n}\n\nconst props = defineProps<{\n currentStep: number;\n totalSteps: number;\n playing: boolean;\n label?: string;\n description?: string;\n sourceAnchorLabel?: string;\n sourceAnchorHref?: string;\n choices?: ChoiceOption[];\n selectedChoiceId?: string;\n}>();\n\nconst emit = defineEmits<{\n next: [];\n prev: [];\n togglePlay: [];\n goTo: [step: number];\n chooseChoice: [choiceId: string];\n}>();\n\nconst MAX_VISIBLE_DOTS = 11;\n\nconst dotWindow = computed(() => {\n if (props.totalSteps <= MAX_VISIBLE_DOTS) {\n return { start: 0, end: Math.max(0, props.totalSteps - 1) };\n }\n\n const halfWindow = Math.floor(MAX_VISIBLE_DOTS / 2);\n let start = Math.max(0, props.currentStep - halfWindow);\n let end = Math.min(props.totalSteps - 1, start + MAX_VISIBLE_DOTS - 1);\n\n if (end - start + 1 < MAX_VISIBLE_DOTS) {\n start = Math.max(0, end - MAX_VISIBLE_DOTS + 1);\n }\n\n return { start, end };\n});\n\nconst visibleStepIndexes = computed(() => {\n const indexes: number[] = [];\n for (let i = dotWindow.value.start; i <= dotWindow.value.end; i += 1) {\n indexes.push(i);\n }\n return indexes;\n});\n\nconst hasLeadingSteps = computed(() => dotWindow.value.start > 0);\nconst hasTrailingSteps = computed(() => dotWindow.value.end < props.totalSteps - 1);\nconst hasChoices = computed(() => (props.choices?.length ?? 0) > 0);\n\nfunction choiceKindClass(kind?: ChoiceOption[\"kind\"]) {\n switch (kind) {\n case \"success\":\n return \"border-emerald-500/40 bg-emerald-500/10 text-emerald-500\";\n case \"error\":\n return \"border-red-500/45 bg-red-500/10 text-red-500\";\n case \"warning\":\n return \"border-amber-500/45 bg-amber-500/10 text-amber-500\";\n case \"retry\":\n return \"border-sky-500/45 bg-sky-500/10 text-sky-500\";\n case \"async\":\n return \"border-violet-500/45 bg-violet-500/10 text-violet-500\";\n default:\n return \"border-border/65 bg-background/70 text-muted-foreground\";\n }\n}\n</script>\n\n<template>\n <div\n class=\"w-full rounded-2xl bg-card/80 backdrop-blur-xl border border-border/60 shadow-2xl px-2.5 py-2\"\n >\n <div class=\"flex items-center gap-2\">\n <button\n class=\"w-8 h-8 rounded-xl flex items-center justify-center text-muted-foreground hover:text-foreground hover:bg-muted/60 disabled:opacity-20 disabled:pointer-events-none transition-colors\"\n :disabled=\"props.currentStep <= 0\"\n @click=\"emit('prev')\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n </button>\n\n <button\n class=\"w-8 h-8 rounded-xl flex items-center justify-center bg-foreground text-background hover:bg-foreground/85 transition-colors\"\n @click=\"emit('togglePlay')\"\n >\n <svg v-if=\"!props.playing\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <polygon points=\"6 3 20 12 6 21 6 3\" />\n </svg>\n <svg v-else width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <rect x=\"5\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\" />\n <rect x=\"15\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\" />\n </svg>\n </button>\n\n <button\n class=\"w-8 h-8 rounded-xl flex items-center justify-center text-muted-foreground hover:text-foreground hover:bg-muted/60 disabled:opacity-20 disabled:pointer-events-none transition-colors\"\n :disabled=\"props.currentStep >= props.totalSteps - 1\"\n @click=\"emit('next')\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n </button>\n\n <div class=\"w-px h-5 bg-border/60\" />\n\n <div class=\"flex min-w-0 flex-1 items-center gap-2.5 px-1.5\">\n <div class=\"h-1 flex-1 overflow-hidden rounded-full bg-muted/70\">\n <div\n class=\"h-full bg-foreground transition-[width] duration-500 ease-out\"\n :style=\"{\n width: `${props.totalSteps > 1 ? (props.currentStep / (props.totalSteps - 1)) * 100 : 100}%`,\n }\"\n />\n </div>\n\n <div class=\"flex items-center gap-1\">\n <span v-if=\"hasLeadingSteps\" class=\"text-[10px] text-muted-foreground/60\">...</span>\n\n <button\n v-for=\"step in visibleStepIndexes\"\n :key=\"step\"\n class=\"h-1.5 rounded-full transition-all duration-300\"\n :class=\"\n step === props.currentStep\n ? 'bg-foreground w-4'\n : step < props.currentStep\n ? 'bg-muted-foreground/50 w-1.5'\n : 'bg-muted-foreground/20 w-1.5'\n \"\n @click=\"emit('goTo', step)\"\n />\n\n <span v-if=\"hasTrailingSteps\" class=\"text-[10px] text-muted-foreground/60\">...</span>\n </div>\n\n <span class=\"shrink-0 text-[11px] text-muted-foreground font-mono tabular-nums\">\n {{ props.currentStep + 1 }}<span class=\"text-muted-foreground/40\">/</span\n >{{ props.totalSteps }}\n </span>\n </div>\n </div>\n\n <div\n v-if=\"props.label || props.description || props.sourceAnchorLabel\"\n class=\"mt-2 border-t border-border/60 pt-2 px-1.5\"\n >\n <p\n v-if=\"props.label\"\n class=\"text-[11px] font-medium text-foreground leading-snug break-words\"\n >\n {{ props.label }}\n </p>\n\n <a\n v-if=\"props.sourceAnchorLabel && props.sourceAnchorHref\"\n :href=\"props.sourceAnchorHref\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"mt-1 inline-flex max-w-full items-center gap-1 rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground transition-colors hover:border-primary/45 hover:text-foreground\"\n >\n <span class=\"truncate\">{{ props.sourceAnchorLabel }}</span>\n </a>\n\n <p\n v-else-if=\"props.sourceAnchorLabel\"\n class=\"mt-1 inline-flex max-w-full items-center rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground\"\n >\n <span class=\"truncate\">{{ props.sourceAnchorLabel }}</span>\n </p>\n\n <p\n v-if=\"props.description\"\n class=\"mt-1 max-h-[120px] overflow-auto pr-1 text-[11px] text-muted-foreground leading-relaxed whitespace-pre-wrap break-words\"\n >\n {{ props.description }}\n </p>\n </div>\n\n <div v-if=\"hasChoices\" class=\"mt-2 border-t border-border/60 pt-2 px-1.5\">\n <p class=\"text-[10px] uppercase tracking-wider text-muted-foreground\">\n Choose Next Path (1-9)\n </p>\n\n <div class=\"mt-1.5 flex flex-wrap gap-1.5\">\n <button\n v-for=\"(choice, index) in props.choices\"\n :key=\"choice.id\"\n class=\"rounded-lg border px-2 py-1 text-[11px] transition-colors text-left\"\n :class=\"\n choice.id === props.selectedChoiceId\n ? 'border-foreground/70 bg-foreground/10 text-foreground'\n : 'border-border/60 text-muted-foreground hover:text-foreground hover:bg-muted/60'\n \"\n @click=\"emit('chooseChoice', choice.id)\"\n >\n <span class=\"flex items-center gap-1.5\">\n <span\n v-if=\"index < 9\"\n class=\"inline-flex h-4 min-w-4 items-center justify-center rounded border border-border/70 bg-background/65 px-1 text-[10px] font-medium tabular-nums\"\n >\n {{ index + 1 }}\n </span>\n <span>{{ choice.label }}</span>\n <span\n v-if=\"choice.kind\"\n class=\"rounded border px-1 py-0.5 text-[9px] uppercase tracking-wider\"\n :class=\"choiceKindClass(choice.kind)\"\n >\n {{ choice.kind }}\n </span>\n </span>\n </button>\n </div>\n\n <p\n v-if=\"props.selectedChoiceId\"\n class=\"mt-1.5 text-[10px] text-muted-foreground leading-relaxed whitespace-pre-wrap break-words\"\n >\n {{ props.choices?.find((choice) => choice.id === props.selectedChoiceId)?.description }}\n </p>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\n\ninterface ChoiceOption {\n id: string;\n label: string;\n description?: string;\n kind?: \"default\" | \"success\" | \"error\" | \"warning\" | \"retry\" | \"async\";\n}\n\nconst props = defineProps<{\n currentStep: number;\n totalSteps: number;\n playing: boolean;\n label?: string;\n description?: string;\n sourceAnchorLabel?: string;\n sourceAnchorHref?: string;\n choices?: ChoiceOption[];\n selectedChoiceId?: string;\n}>();\n\nconst emit = defineEmits<{\n next: [];\n prev: [];\n togglePlay: [];\n goTo: [step: number];\n chooseChoice: [choiceId: string];\n}>();\n\nconst MAX_VISIBLE_DOTS = 11;\n\nconst dotWindow = computed(() => {\n if (props.totalSteps <= MAX_VISIBLE_DOTS) {\n return { start: 0, end: Math.max(0, props.totalSteps - 1) };\n }\n\n const halfWindow = Math.floor(MAX_VISIBLE_DOTS / 2);\n let start = Math.max(0, props.currentStep - halfWindow);\n let end = Math.min(props.totalSteps - 1, start + MAX_VISIBLE_DOTS - 1);\n\n if (end - start + 1 < MAX_VISIBLE_DOTS) {\n start = Math.max(0, end - MAX_VISIBLE_DOTS + 1);\n }\n\n return { start, end };\n});\n\nconst visibleStepIndexes = computed(() => {\n const indexes: number[] = [];\n for (let i = dotWindow.value.start; i <= dotWindow.value.end; i += 1) {\n indexes.push(i);\n }\n return indexes;\n});\n\nconst hasLeadingSteps = computed(() => dotWindow.value.start > 0);\nconst hasTrailingSteps = computed(() => dotWindow.value.end < props.totalSteps - 1);\nconst hasChoices = computed(() => (props.choices?.length ?? 0) > 0);\n\nfunction choiceKindClass(kind?: ChoiceOption[\"kind\"]) {\n switch (kind) {\n case \"success\":\n return \"border-emerald-500/40 bg-emerald-500/10 text-emerald-500\";\n case \"error\":\n return \"border-red-500/45 bg-red-500/10 text-red-500\";\n case \"warning\":\n return \"border-amber-500/45 bg-amber-500/10 text-amber-500\";\n case \"retry\":\n return \"border-sky-500/45 bg-sky-500/10 text-sky-500\";\n case \"async\":\n return \"border-violet-500/45 bg-violet-500/10 text-violet-500\";\n default:\n return \"border-border/65 bg-background/70 text-muted-foreground\";\n }\n}\n</script>\n\n<template>\n <div\n class=\"w-full rounded-2xl bg-card/80 backdrop-blur-xl border border-border/60 shadow-2xl px-2.5 py-2\"\n >\n <div class=\"flex items-center gap-2\">\n <button\n class=\"w-8 h-8 rounded-xl flex items-center justify-center text-muted-foreground hover:text-foreground hover:bg-muted/60 disabled:opacity-20 disabled:pointer-events-none transition-colors\"\n :disabled=\"props.currentStep <= 0\"\n @click=\"emit('prev')\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n </button>\n\n <button\n class=\"w-8 h-8 rounded-xl flex items-center justify-center bg-foreground text-background hover:bg-foreground/85 transition-colors\"\n @click=\"emit('togglePlay')\"\n >\n <svg v-if=\"!props.playing\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <polygon points=\"6 3 20 12 6 21 6 3\" />\n </svg>\n <svg v-else width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <rect x=\"5\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\" />\n <rect x=\"15\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\" />\n </svg>\n </button>\n\n <button\n class=\"w-8 h-8 rounded-xl flex items-center justify-center text-muted-foreground hover:text-foreground hover:bg-muted/60 disabled:opacity-20 disabled:pointer-events-none transition-colors\"\n :disabled=\"props.currentStep >= props.totalSteps - 1\"\n @click=\"emit('next')\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n </button>\n\n <div class=\"w-px h-5 bg-border/60\" />\n\n <div class=\"flex min-w-0 flex-1 items-center gap-2.5 px-1.5\">\n <div class=\"h-1 flex-1 overflow-hidden rounded-full bg-muted/70\">\n <div\n class=\"h-full bg-foreground transition-[width] duration-500 ease-out\"\n :style=\"{\n width: `${props.totalSteps > 1 ? (props.currentStep / (props.totalSteps - 1)) * 100 : 100}%`,\n }\"\n />\n </div>\n\n <div class=\"flex items-center gap-1\">\n <span v-if=\"hasLeadingSteps\" class=\"text-[10px] text-muted-foreground/60\">...</span>\n\n <button\n v-for=\"step in visibleStepIndexes\"\n :key=\"step\"\n class=\"h-1.5 rounded-full transition-all duration-300\"\n :class=\"\n step === props.currentStep\n ? 'bg-foreground w-4'\n : step < props.currentStep\n ? 'bg-muted-foreground/50 w-1.5'\n : 'bg-muted-foreground/20 w-1.5'\n \"\n @click=\"emit('goTo', step)\"\n />\n\n <span v-if=\"hasTrailingSteps\" class=\"text-[10px] text-muted-foreground/60\">...</span>\n </div>\n\n <span class=\"shrink-0 text-[11px] text-muted-foreground font-mono tabular-nums\">\n {{ props.currentStep + 1 }}<span class=\"text-muted-foreground/40\">/</span\n >{{ props.totalSteps }}\n </span>\n </div>\n </div>\n\n <div\n v-if=\"props.label || props.description || props.sourceAnchorLabel\"\n class=\"mt-2 border-t border-border/60 pt-2 px-1.5\"\n >\n <p\n v-if=\"props.label\"\n class=\"text-[11px] font-medium text-foreground leading-snug break-words\"\n >\n {{ props.label }}\n </p>\n\n <a\n v-if=\"props.sourceAnchorLabel && props.sourceAnchorHref\"\n :href=\"props.sourceAnchorHref\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"mt-1 inline-flex max-w-full items-center gap-1 rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground transition-colors hover:border-primary/45 hover:text-foreground\"\n >\n <span class=\"truncate\">{{ props.sourceAnchorLabel }}</span>\n </a>\n\n <p\n v-else-if=\"props.sourceAnchorLabel\"\n class=\"mt-1 inline-flex max-w-full items-center rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground\"\n >\n <span class=\"truncate\">{{ props.sourceAnchorLabel }}</span>\n </p>\n\n <p\n v-if=\"props.description\"\n class=\"mt-1 max-h-[120px] overflow-auto pr-1 text-[11px] text-muted-foreground leading-relaxed whitespace-pre-wrap break-words\"\n >\n {{ props.description }}\n </p>\n </div>\n\n <div v-if=\"hasChoices\" class=\"mt-2 border-t border-border/60 pt-2 px-1.5\">\n <p class=\"text-[10px] uppercase tracking-wider text-muted-foreground\">\n Choose Next Path (1-9)\n </p>\n\n <div class=\"mt-1.5 flex flex-wrap gap-1.5\">\n <button\n v-for=\"(choice, index) in props.choices\"\n :key=\"choice.id\"\n class=\"rounded-lg border px-2 py-1 text-[11px] transition-colors text-left\"\n :class=\"\n choice.id === props.selectedChoiceId\n ? 'border-foreground/70 bg-foreground/10 text-foreground'\n : 'border-border/60 text-muted-foreground hover:text-foreground hover:bg-muted/60'\n \"\n @click=\"emit('chooseChoice', choice.id)\"\n >\n <span class=\"flex items-center gap-1.5\">\n <span\n v-if=\"index < 9\"\n class=\"inline-flex h-4 min-w-4 items-center justify-center rounded border border-border/70 bg-background/65 px-1 text-[10px] font-medium tabular-nums\"\n >\n {{ index + 1 }}\n </span>\n <span>{{ choice.label }}</span>\n <span\n v-if=\"choice.kind\"\n class=\"rounded border px-1 py-0.5 text-[9px] uppercase tracking-wider\"\n :class=\"choiceKindClass(choice.kind)\"\n >\n {{ choice.kind }}\n </span>\n </span>\n </button>\n </div>\n\n <p\n v-if=\"props.selectedChoiceId\"\n class=\"mt-1.5 text-[10px] text-muted-foreground leading-relaxed whitespace-pre-wrap break-words\"\n >\n {{ props.choices?.find((choice) => choice.id === props.selectedChoiceId)?.description }}\n </p>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { BaseEdge, EdgeLabelRenderer, getSmoothStepPath, type EdgeProps } from \"@vue-flow/core\";\nimport { computed } from \"vue\";\n\nconst props = withDefaults(defineProps<EdgeProps>(), {\n interactionWidth: 28,\n});\n\nconst pathDefinition = computed(() => {\n return getSmoothStepPath({\n sourceX: props.sourceX,\n sourceY: props.sourceY,\n sourcePosition: props.sourcePosition,\n targetX: props.targetX,\n targetY: props.targetY,\n targetPosition: props.targetPosition,\n offset: 42,\n borderRadius: 14,\n });\n});\n\nconst edgePath = computed(() => pathDefinition.value[0]);\nconst labelX = computed(() => pathDefinition.value[1]);\nconst labelY = computed(() => pathDefinition.value[2]);\nconst labelText = computed(() => (typeof props.label === \"string\" ? props.label : \"\"));\nconst labelPositionStyle = computed(() => ({\n transform: `translate(-50%, -50%) translate(${labelX.value}px, ${labelY.value}px)`,\n}));\n</script>\n\n<template>\n <BaseEdge\n :id=\"id\"\n :path=\"edgePath\"\n :marker-start=\"markerStart\"\n :marker-end=\"markerEnd\"\n :interaction-width=\"interactionWidth\"\n />\n\n <EdgeLabelRenderer>\n <div v-if=\"labelText\" class=\"fn-edge-html-label nodrag nopan\" :style=\"labelPositionStyle\">\n {{ labelText }}\n </div>\n </EdgeLabelRenderer>\n</template>\n","<script setup lang=\"ts\">\nimport { BaseEdge, EdgeLabelRenderer, getSmoothStepPath, type EdgeProps } from \"@vue-flow/core\";\nimport { computed } from \"vue\";\n\nconst props = withDefaults(defineProps<EdgeProps>(), {\n interactionWidth: 28,\n});\n\nconst pathDefinition = computed(() => {\n return getSmoothStepPath({\n sourceX: props.sourceX,\n sourceY: props.sourceY,\n sourcePosition: props.sourcePosition,\n targetX: props.targetX,\n targetY: props.targetY,\n targetPosition: props.targetPosition,\n offset: 42,\n borderRadius: 14,\n });\n});\n\nconst edgePath = computed(() => pathDefinition.value[0]);\nconst labelX = computed(() => pathDefinition.value[1]);\nconst labelY = computed(() => pathDefinition.value[2]);\nconst labelText = computed(() => (typeof props.label === \"string\" ? props.label : \"\"));\nconst labelPositionStyle = computed(() => ({\n transform: `translate(-50%, -50%) translate(${labelX.value}px, ${labelY.value}px)`,\n}));\n</script>\n\n<template>\n <BaseEdge\n :id=\"id\"\n :path=\"edgePath\"\n :marker-start=\"markerStart\"\n :marker-end=\"markerEnd\"\n :interaction-width=\"interactionWidth\"\n />\n\n <EdgeLabelRenderer>\n <div v-if=\"labelText\" class=\"fn-edge-html-label nodrag nopan\" :style=\"labelPositionStyle\">\n {{ labelText }}\n </div>\n </EdgeLabelRenderer>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\n\nconst props = defineProps<{\n label: string;\n href?: string;\n}>();\n\nconst opensNewTab = computed(() => {\n return typeof props.href === \"string\" && /^https?:\\/\\//i.test(props.href);\n});\n</script>\n\n<template>\n <a\n v-if=\"href\"\n :href=\"href\"\n :target=\"opensNewTab ? '_blank' : undefined\"\n :rel=\"opensNewTab ? 'noopener noreferrer' : undefined\"\n class=\"nowheel nopan nodrag inline-flex min-w-0 max-w-full items-center gap-1 rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground transition-colors hover:border-primary/40 hover:text-foreground\"\n :draggable=\"false\"\n @click.stop\n @pointerdown.stop\n @mousedown.stop\n @touchstart.stop\n >\n <svg\n class=\"h-3 w-3 shrink-0\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M14 3h7v7\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M21 14v7h-7\" />\n <path d=\"M3 10v11h11\" />\n </svg>\n <span class=\"truncate\" :title=\"label\">{{ label }}</span>\n </a>\n\n <span\n v-else\n class=\"nowheel nopan nodrag inline-flex min-w-0 max-w-full items-center gap-1 rounded-md border border-border/65 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground\"\n :title=\"label\"\n @click.stop\n @pointerdown.stop\n @mousedown.stop\n @touchstart.stop\n >\n <svg\n class=\"h-3 w-3 shrink-0\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M3 10v11h11\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M14 3h7v7\" />\n </svg>\n <span class=\"truncate\">{{ label }}</span>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\n\nconst props = defineProps<{\n label: string;\n href?: string;\n}>();\n\nconst opensNewTab = computed(() => {\n return typeof props.href === \"string\" && /^https?:\\/\\//i.test(props.href);\n});\n</script>\n\n<template>\n <a\n v-if=\"href\"\n :href=\"href\"\n :target=\"opensNewTab ? '_blank' : undefined\"\n :rel=\"opensNewTab ? 'noopener noreferrer' : undefined\"\n class=\"nowheel nopan nodrag inline-flex min-w-0 max-w-full items-center gap-1 rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground transition-colors hover:border-primary/40 hover:text-foreground\"\n :draggable=\"false\"\n @click.stop\n @pointerdown.stop\n @mousedown.stop\n @touchstart.stop\n >\n <svg\n class=\"h-3 w-3 shrink-0\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M14 3h7v7\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M21 14v7h-7\" />\n <path d=\"M3 10v11h11\" />\n </svg>\n <span class=\"truncate\" :title=\"label\">{{ label }}</span>\n </a>\n\n <span\n v-else\n class=\"nowheel nopan nodrag inline-flex min-w-0 max-w-full items-center gap-1 rounded-md border border-border/65 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground\"\n :title=\"label\"\n @click.stop\n @pointerdown.stop\n @mousedown.stop\n @touchstart.stop\n >\n <svg\n class=\"h-3 w-3 shrink-0\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M3 10v11h11\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M14 3h7v7\" />\n </svg>\n <span class=\"truncate\">{{ label }}</span>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ntype ArchitectureKind =\n | \"service\"\n | \"database\"\n | \"queue\"\n | \"cache\"\n | \"gateway\"\n | \"external\"\n | \"compute\";\ntype ArchitectureTier = \"edge\" | \"application\" | \"integration\" | \"data\" | \"platform\" | \"external\";\ntype ArchitectureStatus = \"planned\" | \"active\" | \"degraded\" | \"retired\";\n\nconst props = withDefaults(\n defineProps<{\n label: string;\n kind?: ArchitectureKind;\n technology?: string;\n runtime?: string;\n owner?: string;\n tier?: ArchitectureTier;\n status?: ArchitectureStatus;\n tags?: string[];\n capabilities?: string[];\n description?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n }>(),\n {\n kind: \"service\",\n },\n);\n\nconst kindMeta = computed(() => {\n switch (props.kind) {\n case \"database\":\n return {\n tag: \"Database\",\n short: \"DB\",\n cardClass: \"border-emerald-500/40\",\n iconClass: \"border-emerald-500/45 bg-emerald-500/12 text-emerald-500\",\n tagClass: \"border-emerald-500/35 bg-emerald-500/12 text-emerald-500\",\n };\n case \"queue\":\n return {\n tag: \"Queue\",\n short: \"Q\",\n cardClass: \"border-amber-500/45\",\n iconClass: \"border-amber-500/45 bg-amber-500/12 text-amber-500\",\n tagClass: \"border-amber-500/35 bg-amber-500/12 text-amber-500\",\n };\n case \"cache\":\n return {\n tag: \"Cache\",\n short: \"C\",\n cardClass: \"border-cyan-500/45\",\n iconClass: \"border-cyan-500/45 bg-cyan-500/12 text-cyan-500\",\n tagClass: \"border-cyan-500/35 bg-cyan-500/12 text-cyan-500\",\n };\n case \"gateway\":\n return {\n tag: \"Gateway\",\n short: \"GW\",\n cardClass: \"border-indigo-500/45\",\n iconClass: \"border-indigo-500/45 bg-indigo-500/12 text-indigo-400\",\n tagClass: \"border-indigo-500/35 bg-indigo-500/12 text-indigo-400\",\n };\n case \"external\":\n return {\n tag: \"External\",\n short: \"EXT\",\n cardClass: \"border-slate-500/45\",\n iconClass: \"border-slate-500/45 bg-slate-500/12 text-slate-300\",\n tagClass: \"border-slate-500/35 bg-slate-500/12 text-slate-300\",\n };\n case \"compute\":\n return {\n tag: \"Compute\",\n short: \"CPU\",\n cardClass: \"border-rose-500/45\",\n iconClass: \"border-rose-500/45 bg-rose-500/12 text-rose-400\",\n tagClass: \"border-rose-500/35 bg-rose-500/12 text-rose-400\",\n };\n case \"service\":\n default:\n return {\n tag: \"Service\",\n short: \"API\",\n cardClass: \"border-sky-500/45\",\n iconClass: \"border-sky-500/45 bg-sky-500/12 text-sky-400\",\n tagClass: \"border-sky-500/35 bg-sky-500/12 text-sky-400\",\n };\n }\n});\n\nconst statusMeta = computed(() => {\n switch (props.status) {\n case \"planned\":\n return {\n label: \"Planned\",\n className: \"border-blue-400/35 bg-blue-400/12 text-blue-200\",\n };\n case \"degraded\":\n return {\n label: \"Degraded\",\n className: \"border-amber-400/35 bg-amber-400/12 text-amber-200\",\n };\n case \"retired\":\n return {\n label: \"Retired\",\n className: \"border-slate-400/35 bg-slate-400/12 text-slate-300\",\n };\n case \"active\":\n default:\n return {\n label: \"Active\",\n className: \"border-emerald-400/35 bg-emerald-400/12 text-emerald-200\",\n };\n }\n});\n\nconst tierLabel = computed(() => {\n if (!props.tier) {\n return undefined;\n }\n\n return props.tier.charAt(0).toUpperCase() + props.tier.slice(1);\n});\n\nconst compactCapabilities = computed(() => (props.capabilities ?? []).slice(0, 2));\nconst compactTags = computed(() => (props.tags ?? []).slice(0, 3));\n</script>\n\n<template>\n <div\n class=\"fn-node w-[270px] rounded-xl border bg-card/95 px-4 py-3 shadow-sm\"\n :class=\"kindMeta.cardClass\"\n :data-active=\"active\"\n data-node-type=\"architecture\"\n :data-node-kind=\"kind\"\n :data-node-status=\"status\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n\n <div class=\"flex items-start gap-2.5\">\n <div\n class=\"inline-flex h-8 min-w-8 items-center justify-center rounded-md border px-1 text-[10px] font-semibold uppercase tracking-wide\"\n :class=\"kindMeta.iconClass\"\n >\n {{ kindMeta.short }}\n </div>\n\n <div class=\"min-w-0 flex-1\">\n <p\n class=\"inline-flex items-center rounded-full border px-1.5 py-0.5 text-[9px] font-medium uppercase tracking-wider\"\n :class=\"kindMeta.tagClass\"\n >\n {{ kindMeta.tag }}\n </p>\n\n <p class=\"mt-1 text-sm font-semibold text-foreground leading-snug break-words\">\n {{ label }}\n </p>\n\n <p v-if=\"technology\" class=\"mt-0.5 text-[11px] font-mono text-muted-foreground break-words\">\n {{ technology }}\n </p>\n\n <div class=\"mt-1 flex flex-wrap items-center gap-1\">\n <span\n class=\"inline-flex items-center rounded border px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wider\"\n :class=\"statusMeta.className\"\n >\n {{ statusMeta.label }}\n </span>\n\n <span\n v-if=\"tierLabel\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[9px] font-medium uppercase tracking-wider text-muted-foreground\"\n >\n {{ tierLabel }}\n </span>\n </div>\n\n <p v-if=\"owner\" class=\"mt-1 text-[10px] text-muted-foreground break-words\">\n Owner: {{ owner }}\n </p>\n\n <p v-if=\"runtime\" class=\"text-[10px] font-mono text-muted-foreground break-words\">\n Runtime: {{ runtime }}\n </p>\n </div>\n </div>\n\n <div v-if=\"compactCapabilities.length > 0\" class=\"mt-2 flex flex-wrap gap-1\">\n <span\n v-for=\"capability in compactCapabilities\"\n :key=\"capability\"\n class=\"inline-flex items-center rounded border border-primary/30 bg-primary/10 px-1.5 py-0.5 text-[9px] font-medium text-primary\"\n >\n {{ capability }}\n </span>\n </div>\n\n <div v-if=\"compactTags.length > 0\" class=\"mt-1 flex flex-wrap gap-1\">\n <span\n v-for=\"tag in compactTags\"\n :key=\"tag\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/20 px-1.5 py-0.5 text-[9px] font-medium text-muted-foreground\"\n >\n #{{ tag }}\n </span>\n </div>\n\n <p\n v-if=\"description\"\n class=\"mt-2 text-[11px] text-muted-foreground leading-relaxed break-words\"\n >\n {{ description }}\n </p>\n\n <div v-if=\"sourceAnchor?.label\" class=\"mt-2 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ntype ArchitectureKind =\n | \"service\"\n | \"database\"\n | \"queue\"\n | \"cache\"\n | \"gateway\"\n | \"external\"\n | \"compute\";\ntype ArchitectureTier = \"edge\" | \"application\" | \"integration\" | \"data\" | \"platform\" | \"external\";\ntype ArchitectureStatus = \"planned\" | \"active\" | \"degraded\" | \"retired\";\n\nconst props = withDefaults(\n defineProps<{\n label: string;\n kind?: ArchitectureKind;\n technology?: string;\n runtime?: string;\n owner?: string;\n tier?: ArchitectureTier;\n status?: ArchitectureStatus;\n tags?: string[];\n capabilities?: string[];\n description?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n }>(),\n {\n kind: \"service\",\n },\n);\n\nconst kindMeta = computed(() => {\n switch (props.kind) {\n case \"database\":\n return {\n tag: \"Database\",\n short: \"DB\",\n cardClass: \"border-emerald-500/40\",\n iconClass: \"border-emerald-500/45 bg-emerald-500/12 text-emerald-500\",\n tagClass: \"border-emerald-500/35 bg-emerald-500/12 text-emerald-500\",\n };\n case \"queue\":\n return {\n tag: \"Queue\",\n short: \"Q\",\n cardClass: \"border-amber-500/45\",\n iconClass: \"border-amber-500/45 bg-amber-500/12 text-amber-500\",\n tagClass: \"border-amber-500/35 bg-amber-500/12 text-amber-500\",\n };\n case \"cache\":\n return {\n tag: \"Cache\",\n short: \"C\",\n cardClass: \"border-cyan-500/45\",\n iconClass: \"border-cyan-500/45 bg-cyan-500/12 text-cyan-500\",\n tagClass: \"border-cyan-500/35 bg-cyan-500/12 text-cyan-500\",\n };\n case \"gateway\":\n return {\n tag: \"Gateway\",\n short: \"GW\",\n cardClass: \"border-indigo-500/45\",\n iconClass: \"border-indigo-500/45 bg-indigo-500/12 text-indigo-400\",\n tagClass: \"border-indigo-500/35 bg-indigo-500/12 text-indigo-400\",\n };\n case \"external\":\n return {\n tag: \"External\",\n short: \"EXT\",\n cardClass: \"border-slate-500/45\",\n iconClass: \"border-slate-500/45 bg-slate-500/12 text-slate-300\",\n tagClass: \"border-slate-500/35 bg-slate-500/12 text-slate-300\",\n };\n case \"compute\":\n return {\n tag: \"Compute\",\n short: \"CPU\",\n cardClass: \"border-rose-500/45\",\n iconClass: \"border-rose-500/45 bg-rose-500/12 text-rose-400\",\n tagClass: \"border-rose-500/35 bg-rose-500/12 text-rose-400\",\n };\n case \"service\":\n default:\n return {\n tag: \"Service\",\n short: \"API\",\n cardClass: \"border-sky-500/45\",\n iconClass: \"border-sky-500/45 bg-sky-500/12 text-sky-400\",\n tagClass: \"border-sky-500/35 bg-sky-500/12 text-sky-400\",\n };\n }\n});\n\nconst statusMeta = computed(() => {\n switch (props.status) {\n case \"planned\":\n return {\n label: \"Planned\",\n className: \"border-blue-400/35 bg-blue-400/12 text-blue-200\",\n };\n case \"degraded\":\n return {\n label: \"Degraded\",\n className: \"border-amber-400/35 bg-amber-400/12 text-amber-200\",\n };\n case \"retired\":\n return {\n label: \"Retired\",\n className: \"border-slate-400/35 bg-slate-400/12 text-slate-300\",\n };\n case \"active\":\n default:\n return {\n label: \"Active\",\n className: \"border-emerald-400/35 bg-emerald-400/12 text-emerald-200\",\n };\n }\n});\n\nconst tierLabel = computed(() => {\n if (!props.tier) {\n return undefined;\n }\n\n return props.tier.charAt(0).toUpperCase() + props.tier.slice(1);\n});\n\nconst compactCapabilities = computed(() => (props.capabilities ?? []).slice(0, 2));\nconst compactTags = computed(() => (props.tags ?? []).slice(0, 3));\n</script>\n\n<template>\n <div\n class=\"fn-node w-[270px] rounded-xl border bg-card/95 px-4 py-3 shadow-sm\"\n :class=\"kindMeta.cardClass\"\n :data-active=\"active\"\n data-node-type=\"architecture\"\n :data-node-kind=\"kind\"\n :data-node-status=\"status\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n\n <div class=\"flex items-start gap-2.5\">\n <div\n class=\"inline-flex h-8 min-w-8 items-center justify-center rounded-md border px-1 text-[10px] font-semibold uppercase tracking-wide\"\n :class=\"kindMeta.iconClass\"\n >\n {{ kindMeta.short }}\n </div>\n\n <div class=\"min-w-0 flex-1\">\n <p\n class=\"inline-flex items-center rounded-full border px-1.5 py-0.5 text-[9px] font-medium uppercase tracking-wider\"\n :class=\"kindMeta.tagClass\"\n >\n {{ kindMeta.tag }}\n </p>\n\n <p class=\"mt-1 text-sm font-semibold text-foreground leading-snug break-words\">\n {{ label }}\n </p>\n\n <p v-if=\"technology\" class=\"mt-0.5 text-[11px] font-mono text-muted-foreground break-words\">\n {{ technology }}\n </p>\n\n <div class=\"mt-1 flex flex-wrap items-center gap-1\">\n <span\n class=\"inline-flex items-center rounded border px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wider\"\n :class=\"statusMeta.className\"\n >\n {{ statusMeta.label }}\n </span>\n\n <span\n v-if=\"tierLabel\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[9px] font-medium uppercase tracking-wider text-muted-foreground\"\n >\n {{ tierLabel }}\n </span>\n </div>\n\n <p v-if=\"owner\" class=\"mt-1 text-[10px] text-muted-foreground break-words\">\n Owner: {{ owner }}\n </p>\n\n <p v-if=\"runtime\" class=\"text-[10px] font-mono text-muted-foreground break-words\">\n Runtime: {{ runtime }}\n </p>\n </div>\n </div>\n\n <div v-if=\"compactCapabilities.length > 0\" class=\"mt-2 flex flex-wrap gap-1\">\n <span\n v-for=\"capability in compactCapabilities\"\n :key=\"capability\"\n class=\"inline-flex items-center rounded border border-primary/30 bg-primary/10 px-1.5 py-0.5 text-[9px] font-medium text-primary\"\n >\n {{ capability }}\n </span>\n </div>\n\n <div v-if=\"compactTags.length > 0\" class=\"mt-1 flex flex-wrap gap-1\">\n <span\n v-for=\"tag in compactTags\"\n :key=\"tag\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/20 px-1.5 py-0.5 text-[9px] font-medium text-muted-foreground\"\n >\n #{{ tag }}\n </span>\n </div>\n\n <p\n v-if=\"description\"\n class=\"mt-2 text-[11px] text-muted-foreground leading-relaxed break-words\"\n >\n {{ description }}\n </p>\n\n <div v-if=\"sourceAnchor?.label\" class=\"mt-2 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","import { shallowRef, type ShallowRef } from \"vue\";\nimport type { HighlighterCore } from \"shiki\";\n\nlet highlighterPromise: Promise<HighlighterCore> | null = null;\nconst highlighterRef: ShallowRef<HighlighterCore | null> = shallowRef(null);\n\n/**\n * Shared singleton Shiki highlighter.\n * Lazily created on first call; the same instance is reused across all components.\n */\nexport function useShiki(\n langs: string[] = [\n \"typescript\",\n \"tsx\",\n \"javascript\",\n \"jsx\",\n \"python\",\n \"json\",\n \"bash\",\n \"yaml\",\n \"go\",\n \"rust\",\n ],\n theme = \"github-dark\",\n) {\n if (!highlighterPromise) {\n highlighterPromise = import(\"shiki\").then(async ({ createHighlighter }) => {\n const themes = Array.from(new Set([\"github-dark\", \"github-light\", theme]));\n const hl = await createHighlighter({ themes, langs });\n highlighterRef.value = hl;\n return hl;\n });\n }\n\n return {\n highlighter: highlighterRef,\n ready: highlighterPromise,\n };\n}\n","<script setup lang=\"ts\">\nimport { computed, onUnmounted, ref, watch } from \"vue\";\nimport { Handle, Position } from \"@vue-flow/core\";\nimport { ShikiMagicMove, ShikiMagicMovePrecompiled } from \"shiki-magic-move/vue\";\nimport { codeToKeyedTokens, type KeyedTokensInfo } from \"shiki-magic-move/core\";\nimport \"shiki-magic-move/dist/style.css\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\nimport {\n CODE_NODE_MAX_INLINE_CHARS,\n estimateCodeNodeCharsPerLine,\n estimateCodeNodeWidth,\n} from \"../../code-node-sizing\";\nimport { useShiki } from \"../../composables/useShiki\";\nimport {\n hasTwoslashHints,\n hasTwoslashHtml,\n normalizeTwoslashLanguage,\n resolveTwoslashHtmlForTheme,\n} from \"../../twoslash\";\nimport type { MagicMoveStep, TwoslashHtml } from \"../../types\";\n\nconst TWOSLASH_SWAP_DELAY_MS = 560;\nconst FALLBACK_SHIKI_LANGUAGE = \"text\";\n\nconst props = withDefaults(\n defineProps<{\n label: string;\n file?: string;\n language?: string;\n code: string;\n comment?: string;\n story?: string;\n wrapLongLines?: boolean;\n magicMoveSteps?: MagicMoveStep[];\n twoslash?: boolean;\n twoslashHtml?: TwoslashHtml;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n uiTheme?: \"dark\" | \"light\";\n active?: boolean;\n stepIndex?: number;\n }>(),\n {\n language: \"typescript\",\n wrapLongLines: false,\n uiTheme: \"dark\",\n stepIndex: 0,\n },\n);\n\nconst { highlighter } = useShiki();\nconst isClient = typeof window !== \"undefined\";\n\nconst activeStep = computed(() => {\n if (!props.magicMoveSteps?.length) return undefined;\n const idx = Math.min(props.stepIndex, props.magicMoveSteps.length - 1);\n return props.magicMoveSteps[idx];\n});\n\nconst displayCode = computed(() => {\n return activeStep.value?.code ?? props.code;\n});\n\nconst displayTitle = computed(() => activeStep.value?.title);\n\nconst displaySpeaker = computed(() => activeStep.value?.speaker);\n\nconst displayNarrative = computed(() => {\n return activeStep.value?.story ?? activeStep.value?.comment ?? props.story ?? props.comment;\n});\n\nconst codeSequence = computed(() => {\n if (props.magicMoveSteps?.length) {\n return props.magicMoveSteps.map((step) => step.code);\n }\n\n return [props.code];\n});\n\nconst requestedLanguage = computed(() => {\n return (props.language ?? \"typescript\").trim().toLowerCase();\n});\n\nconst renderLanguage = computed(() => {\n const language = requestedLanguage.value || \"typescript\";\n const hl = highlighter.value;\n\n if (!hl) {\n return language;\n }\n\n const loadedLanguages = hl.getLoadedLanguages();\n if (loadedLanguages.includes(language)) {\n return language;\n }\n\n try {\n const resolvedAlias = hl.resolveLangAlias(language);\n if (loadedLanguages.includes(resolvedAlias)) {\n return resolvedAlias;\n }\n } catch {}\n\n return FALLBACK_SHIKI_LANGUAGE;\n});\n\nconst codeVariants = computed(() => {\n const variants = [props.code, ...codeSequence.value];\n return variants.filter((value): value is string => typeof value === \"string\" && value.length > 0);\n});\n\nconst hasMagicMoveSteps = computed(() => {\n return (props.magicMoveSteps?.length ?? 0) > 0;\n});\n\nconst autoTwoslashEnabled = computed(() => {\n return codeVariants.value.some((code) => hasTwoslashHints(code));\n});\n\nconst twoslashRequested = computed(() => {\n return props.twoslash ?? autoTwoslashEnabled.value;\n});\n\nconst twoslashLanguage = computed(() => {\n return normalizeTwoslashLanguage(props.language);\n});\n\nconst resolvedTwoslashHtml = computed(() => {\n return resolveTwoslashHtmlForTheme(props.twoslashHtml, props.uiTheme);\n});\n\nconst displaySourceAnchor = computed(() => {\n if (props.sourceAnchor?.label) {\n return props.sourceAnchor;\n }\n\n if (props.file) {\n return { label: props.file };\n }\n\n return undefined;\n});\n\nconst canRenderTwoslash = computed(() => {\n return (\n twoslashRequested.value &&\n Boolean(twoslashLanguage.value) &&\n hasTwoslashHtml(props.twoslashHtml)\n );\n});\n\nfunction getMaxLineLength(code: string) {\n return code.split(\"\\n\").reduce((max, line) => Math.max(max, line.length), 0);\n}\n\nconst maxLineLength = computed(() => {\n return codeVariants.value.reduce((max, code) => {\n return Math.max(max, getMaxLineLength(code));\n }, 0);\n});\n\nconst nodeWidth = computed(() => {\n return estimateCodeNodeWidth(maxLineLength.value);\n});\n\nconst codeCharsPerLine = computed(() => {\n return estimateCodeNodeCharsPerLine(nodeWidth.value);\n});\n\nconst shouldWrapLongLines = computed(() => {\n return props.wrapLongLines || maxLineLength.value > CODE_NODE_MAX_INLINE_CHARS;\n});\n\nconst shikiTheme = computed(() => {\n return props.uiTheme === \"light\" ? \"github-light\" : \"github-dark\";\n});\n\nconst twoslashShown = ref(false);\n\nconst showTwoslashPane = computed(() => {\n return twoslashShown.value && resolvedTwoslashHtml.value.length > 0;\n});\n\nlet finalSwapTimer: ReturnType<typeof setTimeout> | null = null;\n\nfunction getLastMagicMoveStepIndex() {\n return Math.max(0, (props.magicMoveSteps?.length ?? 1) - 1);\n}\n\nfunction clearFinalSwapTimer() {\n if (!finalSwapTimer) return;\n clearTimeout(finalSwapTimer);\n finalSwapTimer = null;\n}\n\nfunction scheduleFinalSwap() {\n if (!isClient) return;\n\n clearFinalSwapTimer();\n finalSwapTimer = setTimeout(() => {\n if (!canRenderTwoslash.value || !hasMagicMoveSteps.value) return;\n if (props.stepIndex >= getLastMagicMoveStepIndex()) {\n twoslashShown.value = true;\n }\n }, TWOSLASH_SWAP_DELAY_MS);\n}\n\nfunction handleMagicMoveEnd() {\n if (!canRenderTwoslash.value || !hasMagicMoveSteps.value) return;\n if (props.stepIndex < getLastMagicMoveStepIndex()) return;\n\n clearFinalSwapTimer();\n twoslashShown.value = true;\n}\n\nwatch(\n [canRenderTwoslash, hasMagicMoveSteps],\n ([enabled, hasSteps]) => {\n if (!enabled) {\n clearFinalSwapTimer();\n twoslashShown.value = false;\n return;\n }\n\n if (!hasSteps) {\n twoslashShown.value = true;\n return;\n }\n\n if (props.stepIndex < getLastMagicMoveStepIndex()) {\n twoslashShown.value = false;\n }\n },\n { immediate: true },\n);\n\nwatch(\n () => props.stepIndex,\n (stepIndex, previousStepIndex) => {\n if (!canRenderTwoslash.value || !hasMagicMoveSteps.value) return;\n\n const lastStepIndex = getLastMagicMoveStepIndex();\n\n if (stepIndex < lastStepIndex) {\n clearFinalSwapTimer();\n twoslashShown.value = false;\n return;\n }\n\n if (previousStepIndex === undefined || previousStepIndex < lastStepIndex) {\n scheduleFinalSwap();\n }\n },\n { immediate: true },\n);\n\nonUnmounted(() => {\n clearFinalSwapTimer();\n});\n\nconst precompiledSteps = computed<KeyedTokensInfo[] | null>(() => {\n const hl = highlighter.value;\n if (!hl) return null;\n\n try {\n return codeSequence.value.map((code) =>\n codeToKeyedTokens(\n hl as never,\n code,\n {\n lang: renderLanguage.value,\n theme: shikiTheme.value,\n } as never,\n false,\n ),\n );\n } catch {\n return null;\n }\n});\n\nconst precompiledStepIndex = computed(() => {\n const steps = precompiledSteps.value;\n if (!steps?.length) return 0;\n return Math.max(0, Math.min(props.stepIndex, steps.length - 1));\n});\n\nfunction estimateWrappedLines(text: string, charsPerLine = 44) {\n return text\n .split(\"\\n\")\n .reduce((total, line) => total + Math.max(1, Math.ceil(line.length / charsPerLine)), 0);\n}\n\nconst codeViewportHeight = computed(() => {\n const maxLines = codeVariants.value.reduce((max, code) => {\n const lines = shouldWrapLongLines.value\n ? estimateWrappedLines(code, codeCharsPerLine.value)\n : code.split(\"\\n\").length;\n\n return Math.max(max, lines);\n }, 1);\n\n if (shouldWrapLongLines.value) {\n return Math.min(400, Math.max(190, 72 + maxLines * 16));\n }\n\n return Math.min(340, Math.max(160, 84 + maxLines * 17));\n});\n\nconst narrativeVariants = computed(() => {\n const variants = [\n props.story,\n props.comment,\n ...(props.magicMoveSteps?.flatMap((step) => [step.story, step.comment]) ?? []),\n ];\n\n return variants.filter((value): value is string => typeof value === \"string\" && value.length > 0);\n});\n\nconst hasNarrative = computed(() => narrativeVariants.value.length > 0);\n\nconst hasNarrativeMeta = computed(() => {\n return Boolean(\n props.magicMoveSteps?.some((step) => step.title || step.speaker) ||\n displayTitle.value ||\n displaySpeaker.value,\n );\n});\n\nconst narrativeViewportHeight = computed(() => {\n if (!hasNarrative.value) return 0;\n\n const maxLines = narrativeVariants.value.reduce((max, text) => {\n return Math.max(max, estimateWrappedLines(text));\n }, 1);\n\n const baseHeight = hasNarrativeMeta.value ? 56 : 34;\n\n return Math.min(220, Math.max(88, baseHeight + maxLines * 18));\n});\n\nconst magicMoveOptions = {\n duration: 480,\n easing: \"cubic-bezier(0.22, 1, 0.36, 1)\",\n stagger: 0,\n delayMove: 0.18,\n delayEnter: 0.42,\n delayLeave: 0.06,\n animateContainer: false,\n containerStyle: false,\n splitTokens: true,\n enhanceMatching: true,\n lineNumbers: false,\n} as const;\n</script>\n\n<template>\n <div\n class=\"fn-node rounded-lg border border-border bg-card overflow-hidden\"\n :style=\"{ width: `${nodeWidth}px` }\"\n :data-active=\"active\"\n data-node-type=\"code\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n\n <!-- Header -->\n <div class=\"flex items-center justify-between gap-2 px-3 py-2 border-b border-border/50\">\n <span class=\"min-w-0 flex-1 truncate text-sm font-medium text-foreground\">{{ label }}</span>\n <NodeSourceAnchor\n v-if=\"displaySourceAnchor\"\n :label=\"displaySourceAnchor.label\"\n :href=\"displaySourceAnchor.href\"\n />\n </div>\n\n <!-- Code -->\n <div\n class=\"fn-code-stage nowheel nopan px-3 py-2.5 overflow-y-auto transition-[height] duration-300 ease-out\"\n :class=\"shouldWrapLongLines ? 'overflow-x-hidden' : 'overflow-x-auto'\"\n :style=\"{ height: `${codeViewportHeight}px` }\"\n :data-wrap=\"shouldWrapLongLines\"\n >\n <div v-if=\"showTwoslashPane\" class=\"fn-twoslash\" v-html=\"resolvedTwoslashHtml\" />\n <ShikiMagicMovePrecompiled\n v-else-if=\"!shouldWrapLongLines && precompiledSteps && precompiledSteps.length > 0\"\n :steps=\"precompiledSteps\"\n :step=\"precompiledStepIndex\"\n :options=\"magicMoveOptions\"\n @end=\"handleMagicMoveEnd\"\n />\n <ShikiMagicMove\n v-else-if=\"highlighter\"\n :highlighter=\"highlighter\"\n :code=\"displayCode\"\n :lang=\"renderLanguage\"\n :theme=\"shikiTheme\"\n :options=\"magicMoveOptions\"\n class=\"!bg-transparent\"\n @end=\"handleMagicMoveEnd\"\n />\n <pre\n v-else\n class=\"fn-static-code text-xs text-muted-foreground font-mono\"\n :class=\"shouldWrapLongLines ? 'whitespace-pre-wrap break-words' : 'whitespace-pre'\"\n ><code>{{ displayCode }}</code></pre>\n </div>\n\n <!-- Story -->\n <div\n v-if=\"hasNarrative\"\n class=\"nowheel nopan px-3 py-2 border-t border-border/50 overflow-y-auto overflow-x-hidden transition-[height] duration-300 ease-out\"\n :style=\"{ height: `${narrativeViewportHeight}px` }\"\n >\n <div class=\"min-h-full\">\n <div class=\"mb-1 flex items-center justify-between gap-2\">\n <p v-if=\"displayTitle\" class=\"text-[11px] font-medium text-foreground leading-snug\">\n {{ displayTitle }}\n </p>\n <span\n v-if=\"displaySpeaker\"\n class=\"text-[10px] uppercase tracking-wider text-muted-foreground border border-border/60 rounded-full px-2 py-0.5\"\n >\n {{ displaySpeaker }}\n </span>\n </div>\n\n <p class=\"text-[11px] text-muted-foreground leading-relaxed\">{{ displayNarrative }}</p>\n </div>\n </div>\n\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n\n<style scoped>\n.fn-code-stage[data-wrap=\"false\"] :deep(.shiki-magic-move-container),\n.fn-code-stage[data-wrap=\"false\"] :deep(.fn-static-code),\n.fn-code-stage[data-wrap=\"false\"] :deep(.fn-twoslash),\n.fn-code-stage[data-wrap=\"false\"] :deep(.fn-twoslash .twoslash),\n.fn-code-stage[data-wrap=\"false\"] :deep(.fn-twoslash pre.shiki) {\n display: inline-block;\n width: max-content;\n min-width: max-content;\n}\n\n.fn-code-stage[data-wrap=\"true\"] :deep(.shiki-magic-move-container),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-static-code),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-static-code code),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-twoslash),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-twoslash .twoslash),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-twoslash pre.shiki),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-twoslash pre.shiki > code) {\n display: block;\n width: 100%;\n min-width: 0 !important;\n white-space: pre-wrap !important;\n overflow-wrap: anywhere;\n word-break: break-word;\n}\n\n.fn-twoslash :deep(pre.shiki) {\n margin: 0 !important;\n padding: 0 !important;\n background: transparent !important;\n}\n\n.fn-twoslash :deep(pre.shiki code) {\n font-size: 12px;\n line-height: 1.65;\n}\n\n.fn-twoslash :deep(.twoslash-popup-container) {\n max-width: min(520px, calc(100vw - 5rem));\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onUnmounted, ref, watch } from \"vue\";\nimport { Handle, Position } from \"@vue-flow/core\";\nimport { ShikiMagicMove, ShikiMagicMovePrecompiled } from \"shiki-magic-move/vue\";\nimport { codeToKeyedTokens, type KeyedTokensInfo } from \"shiki-magic-move/core\";\nimport \"shiki-magic-move/dist/style.css\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\nimport {\n CODE_NODE_MAX_INLINE_CHARS,\n estimateCodeNodeCharsPerLine,\n estimateCodeNodeWidth,\n} from \"../../code-node-sizing\";\nimport { useShiki } from \"../../composables/useShiki\";\nimport {\n hasTwoslashHints,\n hasTwoslashHtml,\n normalizeTwoslashLanguage,\n resolveTwoslashHtmlForTheme,\n} from \"../../twoslash\";\nimport type { MagicMoveStep, TwoslashHtml } from \"../../types\";\n\nconst TWOSLASH_SWAP_DELAY_MS = 560;\nconst FALLBACK_SHIKI_LANGUAGE = \"text\";\n\nconst props = withDefaults(\n defineProps<{\n label: string;\n file?: string;\n language?: string;\n code: string;\n comment?: string;\n story?: string;\n wrapLongLines?: boolean;\n magicMoveSteps?: MagicMoveStep[];\n twoslash?: boolean;\n twoslashHtml?: TwoslashHtml;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n uiTheme?: \"dark\" | \"light\";\n active?: boolean;\n stepIndex?: number;\n }>(),\n {\n language: \"typescript\",\n wrapLongLines: false,\n uiTheme: \"dark\",\n stepIndex: 0,\n },\n);\n\nconst { highlighter } = useShiki();\nconst isClient = typeof window !== \"undefined\";\n\nconst activeStep = computed(() => {\n if (!props.magicMoveSteps?.length) return undefined;\n const idx = Math.min(props.stepIndex, props.magicMoveSteps.length - 1);\n return props.magicMoveSteps[idx];\n});\n\nconst displayCode = computed(() => {\n return activeStep.value?.code ?? props.code;\n});\n\nconst displayTitle = computed(() => activeStep.value?.title);\n\nconst displaySpeaker = computed(() => activeStep.value?.speaker);\n\nconst displayNarrative = computed(() => {\n return activeStep.value?.story ?? activeStep.value?.comment ?? props.story ?? props.comment;\n});\n\nconst codeSequence = computed(() => {\n if (props.magicMoveSteps?.length) {\n return props.magicMoveSteps.map((step) => step.code);\n }\n\n return [props.code];\n});\n\nconst requestedLanguage = computed(() => {\n return (props.language ?? \"typescript\").trim().toLowerCase();\n});\n\nconst renderLanguage = computed(() => {\n const language = requestedLanguage.value || \"typescript\";\n const hl = highlighter.value;\n\n if (!hl) {\n return language;\n }\n\n const loadedLanguages = hl.getLoadedLanguages();\n if (loadedLanguages.includes(language)) {\n return language;\n }\n\n try {\n const resolvedAlias = hl.resolveLangAlias(language);\n if (loadedLanguages.includes(resolvedAlias)) {\n return resolvedAlias;\n }\n } catch {}\n\n return FALLBACK_SHIKI_LANGUAGE;\n});\n\nconst codeVariants = computed(() => {\n const variants = [props.code, ...codeSequence.value];\n return variants.filter((value): value is string => typeof value === \"string\" && value.length > 0);\n});\n\nconst hasMagicMoveSteps = computed(() => {\n return (props.magicMoveSteps?.length ?? 0) > 0;\n});\n\nconst autoTwoslashEnabled = computed(() => {\n return codeVariants.value.some((code) => hasTwoslashHints(code));\n});\n\nconst twoslashRequested = computed(() => {\n return props.twoslash ?? autoTwoslashEnabled.value;\n});\n\nconst twoslashLanguage = computed(() => {\n return normalizeTwoslashLanguage(props.language);\n});\n\nconst resolvedTwoslashHtml = computed(() => {\n return resolveTwoslashHtmlForTheme(props.twoslashHtml, props.uiTheme);\n});\n\nconst displaySourceAnchor = computed(() => {\n if (props.sourceAnchor?.label) {\n return props.sourceAnchor;\n }\n\n if (props.file) {\n return { label: props.file };\n }\n\n return undefined;\n});\n\nconst canRenderTwoslash = computed(() => {\n return (\n twoslashRequested.value &&\n Boolean(twoslashLanguage.value) &&\n hasTwoslashHtml(props.twoslashHtml)\n );\n});\n\nfunction getMaxLineLength(code: string) {\n return code.split(\"\\n\").reduce((max, line) => Math.max(max, line.length), 0);\n}\n\nconst maxLineLength = computed(() => {\n return codeVariants.value.reduce((max, code) => {\n return Math.max(max, getMaxLineLength(code));\n }, 0);\n});\n\nconst nodeWidth = computed(() => {\n return estimateCodeNodeWidth(maxLineLength.value);\n});\n\nconst codeCharsPerLine = computed(() => {\n return estimateCodeNodeCharsPerLine(nodeWidth.value);\n});\n\nconst shouldWrapLongLines = computed(() => {\n return props.wrapLongLines || maxLineLength.value > CODE_NODE_MAX_INLINE_CHARS;\n});\n\nconst shikiTheme = computed(() => {\n return props.uiTheme === \"light\" ? \"github-light\" : \"github-dark\";\n});\n\nconst twoslashShown = ref(false);\n\nconst showTwoslashPane = computed(() => {\n return twoslashShown.value && resolvedTwoslashHtml.value.length > 0;\n});\n\nlet finalSwapTimer: ReturnType<typeof setTimeout> | null = null;\n\nfunction getLastMagicMoveStepIndex() {\n return Math.max(0, (props.magicMoveSteps?.length ?? 1) - 1);\n}\n\nfunction clearFinalSwapTimer() {\n if (!finalSwapTimer) return;\n clearTimeout(finalSwapTimer);\n finalSwapTimer = null;\n}\n\nfunction scheduleFinalSwap() {\n if (!isClient) return;\n\n clearFinalSwapTimer();\n finalSwapTimer = setTimeout(() => {\n if (!canRenderTwoslash.value || !hasMagicMoveSteps.value) return;\n if (props.stepIndex >= getLastMagicMoveStepIndex()) {\n twoslashShown.value = true;\n }\n }, TWOSLASH_SWAP_DELAY_MS);\n}\n\nfunction handleMagicMoveEnd() {\n if (!canRenderTwoslash.value || !hasMagicMoveSteps.value) return;\n if (props.stepIndex < getLastMagicMoveStepIndex()) return;\n\n clearFinalSwapTimer();\n twoslashShown.value = true;\n}\n\nwatch(\n [canRenderTwoslash, hasMagicMoveSteps],\n ([enabled, hasSteps]) => {\n if (!enabled) {\n clearFinalSwapTimer();\n twoslashShown.value = false;\n return;\n }\n\n if (!hasSteps) {\n twoslashShown.value = true;\n return;\n }\n\n if (props.stepIndex < getLastMagicMoveStepIndex()) {\n twoslashShown.value = false;\n }\n },\n { immediate: true },\n);\n\nwatch(\n () => props.stepIndex,\n (stepIndex, previousStepIndex) => {\n if (!canRenderTwoslash.value || !hasMagicMoveSteps.value) return;\n\n const lastStepIndex = getLastMagicMoveStepIndex();\n\n if (stepIndex < lastStepIndex) {\n clearFinalSwapTimer();\n twoslashShown.value = false;\n return;\n }\n\n if (previousStepIndex === undefined || previousStepIndex < lastStepIndex) {\n scheduleFinalSwap();\n }\n },\n { immediate: true },\n);\n\nonUnmounted(() => {\n clearFinalSwapTimer();\n});\n\nconst precompiledSteps = computed<KeyedTokensInfo[] | null>(() => {\n const hl = highlighter.value;\n if (!hl) return null;\n\n try {\n return codeSequence.value.map((code) =>\n codeToKeyedTokens(\n hl as never,\n code,\n {\n lang: renderLanguage.value,\n theme: shikiTheme.value,\n } as never,\n false,\n ),\n );\n } catch {\n return null;\n }\n});\n\nconst precompiledStepIndex = computed(() => {\n const steps = precompiledSteps.value;\n if (!steps?.length) return 0;\n return Math.max(0, Math.min(props.stepIndex, steps.length - 1));\n});\n\nfunction estimateWrappedLines(text: string, charsPerLine = 44) {\n return text\n .split(\"\\n\")\n .reduce((total, line) => total + Math.max(1, Math.ceil(line.length / charsPerLine)), 0);\n}\n\nconst codeViewportHeight = computed(() => {\n const maxLines = codeVariants.value.reduce((max, code) => {\n const lines = shouldWrapLongLines.value\n ? estimateWrappedLines(code, codeCharsPerLine.value)\n : code.split(\"\\n\").length;\n\n return Math.max(max, lines);\n }, 1);\n\n if (shouldWrapLongLines.value) {\n return Math.min(400, Math.max(190, 72 + maxLines * 16));\n }\n\n return Math.min(340, Math.max(160, 84 + maxLines * 17));\n});\n\nconst narrativeVariants = computed(() => {\n const variants = [\n props.story,\n props.comment,\n ...(props.magicMoveSteps?.flatMap((step) => [step.story, step.comment]) ?? []),\n ];\n\n return variants.filter((value): value is string => typeof value === \"string\" && value.length > 0);\n});\n\nconst hasNarrative = computed(() => narrativeVariants.value.length > 0);\n\nconst hasNarrativeMeta = computed(() => {\n return Boolean(\n props.magicMoveSteps?.some((step) => step.title || step.speaker) ||\n displayTitle.value ||\n displaySpeaker.value,\n );\n});\n\nconst narrativeViewportHeight = computed(() => {\n if (!hasNarrative.value) return 0;\n\n const maxLines = narrativeVariants.value.reduce((max, text) => {\n return Math.max(max, estimateWrappedLines(text));\n }, 1);\n\n const baseHeight = hasNarrativeMeta.value ? 56 : 34;\n\n return Math.min(220, Math.max(88, baseHeight + maxLines * 18));\n});\n\nconst magicMoveOptions = {\n duration: 480,\n easing: \"cubic-bezier(0.22, 1, 0.36, 1)\",\n stagger: 0,\n delayMove: 0.18,\n delayEnter: 0.42,\n delayLeave: 0.06,\n animateContainer: false,\n containerStyle: false,\n splitTokens: true,\n enhanceMatching: true,\n lineNumbers: false,\n} as const;\n</script>\n\n<template>\n <div\n class=\"fn-node rounded-lg border border-border bg-card overflow-hidden\"\n :style=\"{ width: `${nodeWidth}px` }\"\n :data-active=\"active\"\n data-node-type=\"code\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n\n <!-- Header -->\n <div class=\"flex items-center justify-between gap-2 px-3 py-2 border-b border-border/50\">\n <span class=\"min-w-0 flex-1 truncate text-sm font-medium text-foreground\">{{ label }}</span>\n <NodeSourceAnchor\n v-if=\"displaySourceAnchor\"\n :label=\"displaySourceAnchor.label\"\n :href=\"displaySourceAnchor.href\"\n />\n </div>\n\n <!-- Code -->\n <div\n class=\"fn-code-stage nowheel nopan px-3 py-2.5 overflow-y-auto transition-[height] duration-300 ease-out\"\n :class=\"shouldWrapLongLines ? 'overflow-x-hidden' : 'overflow-x-auto'\"\n :style=\"{ height: `${codeViewportHeight}px` }\"\n :data-wrap=\"shouldWrapLongLines\"\n >\n <div v-if=\"showTwoslashPane\" class=\"fn-twoslash\" v-html=\"resolvedTwoslashHtml\" />\n <ShikiMagicMovePrecompiled\n v-else-if=\"!shouldWrapLongLines && precompiledSteps && precompiledSteps.length > 0\"\n :steps=\"precompiledSteps\"\n :step=\"precompiledStepIndex\"\n :options=\"magicMoveOptions\"\n @end=\"handleMagicMoveEnd\"\n />\n <ShikiMagicMove\n v-else-if=\"highlighter\"\n :highlighter=\"highlighter\"\n :code=\"displayCode\"\n :lang=\"renderLanguage\"\n :theme=\"shikiTheme\"\n :options=\"magicMoveOptions\"\n class=\"!bg-transparent\"\n @end=\"handleMagicMoveEnd\"\n />\n <pre\n v-else\n class=\"fn-static-code text-xs text-muted-foreground font-mono\"\n :class=\"shouldWrapLongLines ? 'whitespace-pre-wrap break-words' : 'whitespace-pre'\"\n ><code>{{ displayCode }}</code></pre>\n </div>\n\n <!-- Story -->\n <div\n v-if=\"hasNarrative\"\n class=\"nowheel nopan px-3 py-2 border-t border-border/50 overflow-y-auto overflow-x-hidden transition-[height] duration-300 ease-out\"\n :style=\"{ height: `${narrativeViewportHeight}px` }\"\n >\n <div class=\"min-h-full\">\n <div class=\"mb-1 flex items-center justify-between gap-2\">\n <p v-if=\"displayTitle\" class=\"text-[11px] font-medium text-foreground leading-snug\">\n {{ displayTitle }}\n </p>\n <span\n v-if=\"displaySpeaker\"\n class=\"text-[10px] uppercase tracking-wider text-muted-foreground border border-border/60 rounded-full px-2 py-0.5\"\n >\n {{ displaySpeaker }}\n </span>\n </div>\n\n <p class=\"text-[11px] text-muted-foreground leading-relaxed\">{{ displayNarrative }}</p>\n </div>\n </div>\n\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n\n<style scoped>\n.fn-code-stage[data-wrap=\"false\"] :deep(.shiki-magic-move-container),\n.fn-code-stage[data-wrap=\"false\"] :deep(.fn-static-code),\n.fn-code-stage[data-wrap=\"false\"] :deep(.fn-twoslash),\n.fn-code-stage[data-wrap=\"false\"] :deep(.fn-twoslash .twoslash),\n.fn-code-stage[data-wrap=\"false\"] :deep(.fn-twoslash pre.shiki) {\n display: inline-block;\n width: max-content;\n min-width: max-content;\n}\n\n.fn-code-stage[data-wrap=\"true\"] :deep(.shiki-magic-move-container),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-static-code),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-static-code code),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-twoslash),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-twoslash .twoslash),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-twoslash pre.shiki),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-twoslash pre.shiki > code) {\n display: block;\n width: 100%;\n min-width: 0 !important;\n white-space: pre-wrap !important;\n overflow-wrap: anywhere;\n word-break: break-word;\n}\n\n.fn-twoslash :deep(pre.shiki) {\n margin: 0 !important;\n padding: 0 !important;\n background: transparent !important;\n}\n\n.fn-twoslash :deep(pre.shiki code) {\n font-size: 12px;\n line-height: 1.65;\n}\n\n.fn-twoslash :deep(.twoslash-popup-container) {\n max-width: min(520px, calc(100vw - 5rem));\n}\n</style>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ndefineProps<{\n label: string;\n condition?: string;\n description?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n}>();\n</script>\n\n<template>\n <div\n class=\"fn-node w-[250px] rounded-lg border border-primary/35 bg-card px-4 py-3\"\n :data-active=\"active\"\n data-node-type=\"decision\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n <div class=\"mb-1.5 flex items-center gap-2\">\n <span\n class=\"inline-flex h-5 items-center rounded-full border border-primary/35 bg-primary/10 px-2 text-[10px] font-medium uppercase tracking-wider text-primary\"\n >\n Decision\n </span>\n </div>\n <p class=\"text-sm font-medium text-foreground leading-snug\">{{ label }}</p>\n <p\n v-if=\"condition\"\n class=\"mt-1 text-[11px] text-foreground/85 font-mono leading-relaxed break-words\"\n >\n {{ condition }}\n </p>\n <p v-if=\"description\" class=\"mt-1.5 text-[11px] text-muted-foreground leading-relaxed\">\n {{ description }}\n </p>\n <div v-if=\"sourceAnchor?.label\" class=\"mt-1.5 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ndefineProps<{\n label: string;\n condition?: string;\n description?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n}>();\n</script>\n\n<template>\n <div\n class=\"fn-node w-[250px] rounded-lg border border-primary/35 bg-card px-4 py-3\"\n :data-active=\"active\"\n data-node-type=\"decision\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n <div class=\"mb-1.5 flex items-center gap-2\">\n <span\n class=\"inline-flex h-5 items-center rounded-full border border-primary/35 bg-primary/10 px-2 text-[10px] font-medium uppercase tracking-wider text-primary\"\n >\n Decision\n </span>\n </div>\n <p class=\"text-sm font-medium text-foreground leading-snug\">{{ label }}</p>\n <p\n v-if=\"condition\"\n class=\"mt-1 text-[11px] text-foreground/85 font-mono leading-relaxed break-words\"\n >\n {{ condition }}\n </p>\n <p v-if=\"description\" class=\"mt-1.5 text-[11px] text-muted-foreground leading-relaxed\">\n {{ description }}\n </p>\n <div v-if=\"sourceAnchor?.label\" class=\"mt-1.5 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ndefineProps<{\n label: string;\n body: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n}>();\n</script>\n\n<template>\n <div\n class=\"fn-node w-[240px] rounded-lg border border-border bg-card px-4 py-3\"\n :data-active=\"active\"\n data-node-type=\"description\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n <p class=\"text-sm font-medium text-foreground leading-snug mb-1\">{{ label }}</p>\n <div v-if=\"sourceAnchor?.label\" class=\"mb-1.5 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n <p class=\"text-[11px] text-muted-foreground leading-relaxed\">{{ body }}</p>\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ndefineProps<{\n label: string;\n body: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n}>();\n</script>\n\n<template>\n <div\n class=\"fn-node w-[240px] rounded-lg border border-border bg-card px-4 py-3\"\n :data-active=\"active\"\n data-node-type=\"description\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n <p class=\"text-sm font-medium text-foreground leading-snug mb-1\">{{ label }}</p>\n <div v-if=\"sourceAnchor?.label\" class=\"mb-1.5 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n <p class=\"text-[11px] text-muted-foreground leading-relaxed\">{{ body }}</p>\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ndefineProps<{\n label: string;\n message: string;\n code?: string;\n cause?: string;\n mitigation?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n}>();\n</script>\n\n<template>\n <div\n class=\"fn-node w-[280px] rounded-lg border border-red-400/45 bg-card overflow-hidden\"\n :data-active=\"active\"\n data-node-type=\"error\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n\n <div\n class=\"flex items-center justify-between gap-2 border-b border-red-400/35 bg-red-400/10 px-3 py-2\"\n >\n <span class=\"text-sm font-medium text-foreground\">{{ label }}</span>\n <span\n class=\"rounded-full border border-red-400/45 bg-red-400/18 px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-red-200\"\n >\n Error\n </span>\n </div>\n\n <div class=\"space-y-2 px-3 py-2.5\">\n <p class=\"text-[11px] leading-relaxed text-foreground\">{{ message }}</p>\n\n <div\n v-if=\"code\"\n class=\"inline-flex items-center rounded-md border border-red-400/35 bg-red-400/12 px-2 py-0.5 text-[10px] font-mono text-red-100\"\n >\n {{ code }}\n </div>\n\n <p v-if=\"cause\" class=\"text-[11px] leading-relaxed text-muted-foreground\">\n <span class=\"font-medium text-foreground/90\">Cause:</span> {{ cause }}\n </p>\n\n <p v-if=\"mitigation\" class=\"text-[11px] leading-relaxed text-muted-foreground\">\n <span class=\"font-medium text-foreground/90\">Mitigation:</span> {{ mitigation }}\n </p>\n\n <div v-if=\"sourceAnchor?.label\" class=\"max-w-full pt-1\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n </div>\n\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ndefineProps<{\n label: string;\n message: string;\n code?: string;\n cause?: string;\n mitigation?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n}>();\n</script>\n\n<template>\n <div\n class=\"fn-node w-[280px] rounded-lg border border-red-400/45 bg-card overflow-hidden\"\n :data-active=\"active\"\n data-node-type=\"error\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n\n <div\n class=\"flex items-center justify-between gap-2 border-b border-red-400/35 bg-red-400/10 px-3 py-2\"\n >\n <span class=\"text-sm font-medium text-foreground\">{{ label }}</span>\n <span\n class=\"rounded-full border border-red-400/45 bg-red-400/18 px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-red-200\"\n >\n Error\n </span>\n </div>\n\n <div class=\"space-y-2 px-3 py-2.5\">\n <p class=\"text-[11px] leading-relaxed text-foreground\">{{ message }}</p>\n\n <div\n v-if=\"code\"\n class=\"inline-flex items-center rounded-md border border-red-400/35 bg-red-400/12 px-2 py-0.5 text-[10px] font-mono text-red-100\"\n >\n {{ code }}\n </div>\n\n <p v-if=\"cause\" class=\"text-[11px] leading-relaxed text-muted-foreground\">\n <span class=\"font-medium text-foreground/90\">Cause:</span> {{ cause }}\n </p>\n\n <p v-if=\"mitigation\" class=\"text-[11px] leading-relaxed text-muted-foreground\">\n <span class=\"font-medium text-foreground/90\">Mitigation:</span> {{ mitigation }}\n </p>\n\n <div v-if=\"sourceAnchor?.label\" class=\"max-w-full pt-1\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n </div>\n\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ndefineProps<{\n label: string;\n href: string;\n description?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n}>();\n</script>\n\n<template>\n <div\n class=\"fn-node w-[220px] rounded-lg border border-border bg-card px-4 py-3\"\n :data-active=\"active\"\n data-node-type=\"link\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n <a :href=\"href\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"block group\">\n <p\n class=\"text-sm font-medium text-foreground group-hover:text-primary transition-colors leading-snug\"\n >\n {{ label }}\n </p>\n <p v-if=\"description\" class=\"text-[11px] text-muted-foreground mt-1 leading-relaxed\">\n {{ description }}\n </p>\n </a>\n <div v-if=\"sourceAnchor?.label\" class=\"mt-1.5 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ndefineProps<{\n label: string;\n href: string;\n description?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n}>();\n</script>\n\n<template>\n <div\n class=\"fn-node w-[220px] rounded-lg border border-border bg-card px-4 py-3\"\n :data-active=\"active\"\n data-node-type=\"link\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n <a :href=\"href\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"block group\">\n <p\n class=\"text-sm font-medium text-foreground group-hover:text-primary transition-colors leading-snug\"\n >\n {{ label }}\n </p>\n <p v-if=\"description\" class=\"text-[11px] text-muted-foreground mt-1 leading-relaxed\">\n {{ description }}\n </p>\n </a>\n <div v-if=\"sourceAnchor?.label\" class=\"mt-1.5 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\nconst props = withDefaults(\n defineProps<{\n label: string;\n payload?: string;\n before?: string;\n after?: string;\n format?: \"json\" | \"yaml\" | \"text\";\n description?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n }>(),\n {\n format: \"json\",\n },\n);\n\nconst hasBefore = computed(() => Boolean(props.before));\nconst hasAfter = computed(() => Boolean(props.after));\nconst hasDiff = computed(() => hasBefore.value || hasAfter.value);\nconst singlePayload = computed(() => {\n if (hasDiff.value) return \"\";\n return props.payload ?? \"\";\n});\n</script>\n\n<template>\n <div\n class=\"fn-node w-[300px] rounded-lg border border-border bg-card overflow-hidden\"\n :data-active=\"active\"\n data-node-type=\"payload\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n\n <div class=\"flex items-center justify-between gap-2 border-b border-border/50 px-3 py-2\">\n <span class=\"text-sm font-medium text-foreground\">{{ label }}</span>\n <span\n class=\"rounded-full border border-border/60 bg-muted/45 px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-muted-foreground\"\n >\n {{ format }}\n </span>\n </div>\n\n <div class=\"px-3 py-2.5\">\n <div v-if=\"sourceAnchor?.label\" class=\"mb-2 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n\n <p v-if=\"description\" class=\"mb-2 text-[11px] text-muted-foreground leading-relaxed\">\n {{ description }}\n </p>\n\n <div v-if=\"hasDiff\" class=\"space-y-2\">\n <div v-if=\"hasBefore\" class=\"rounded-md border border-border/65 bg-muted/30 p-2\">\n <p class=\"mb-1 text-[10px] font-medium uppercase tracking-wider text-muted-foreground\">\n Before\n </p>\n <pre\n class=\"nowheel nopan max-h-[132px] overflow-auto text-[11px] leading-relaxed text-foreground whitespace-pre\"\n ><code>{{ before }}</code></pre>\n </div>\n\n <div v-if=\"hasAfter\" class=\"rounded-md border border-primary/30 bg-primary/8 p-2\">\n <p class=\"mb-1 text-[10px] font-medium uppercase tracking-wider text-primary\">After</p>\n <pre\n class=\"nowheel nopan max-h-[132px] overflow-auto text-[11px] leading-relaxed text-foreground whitespace-pre\"\n ><code>{{ after }}</code></pre>\n </div>\n </div>\n\n <div v-else class=\"rounded-md border border-border/65 bg-muted/25 p-2\">\n <pre\n class=\"nowheel nopan max-h-[220px] overflow-auto text-[11px] leading-relaxed text-foreground whitespace-pre\"\n ><code>{{ singlePayload }}</code></pre>\n </div>\n </div>\n\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\nconst props = withDefaults(\n defineProps<{\n label: string;\n payload?: string;\n before?: string;\n after?: string;\n format?: \"json\" | \"yaml\" | \"text\";\n description?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n }>(),\n {\n format: \"json\",\n },\n);\n\nconst hasBefore = computed(() => Boolean(props.before));\nconst hasAfter = computed(() => Boolean(props.after));\nconst hasDiff = computed(() => hasBefore.value || hasAfter.value);\nconst singlePayload = computed(() => {\n if (hasDiff.value) return \"\";\n return props.payload ?? \"\";\n});\n</script>\n\n<template>\n <div\n class=\"fn-node w-[300px] rounded-lg border border-border bg-card overflow-hidden\"\n :data-active=\"active\"\n data-node-type=\"payload\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n\n <div class=\"flex items-center justify-between gap-2 border-b border-border/50 px-3 py-2\">\n <span class=\"text-sm font-medium text-foreground\">{{ label }}</span>\n <span\n class=\"rounded-full border border-border/60 bg-muted/45 px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-muted-foreground\"\n >\n {{ format }}\n </span>\n </div>\n\n <div class=\"px-3 py-2.5\">\n <div v-if=\"sourceAnchor?.label\" class=\"mb-2 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n\n <p v-if=\"description\" class=\"mb-2 text-[11px] text-muted-foreground leading-relaxed\">\n {{ description }}\n </p>\n\n <div v-if=\"hasDiff\" class=\"space-y-2\">\n <div v-if=\"hasBefore\" class=\"rounded-md border border-border/65 bg-muted/30 p-2\">\n <p class=\"mb-1 text-[10px] font-medium uppercase tracking-wider text-muted-foreground\">\n Before\n </p>\n <pre\n class=\"nowheel nopan max-h-[132px] overflow-auto text-[11px] leading-relaxed text-foreground whitespace-pre\"\n ><code>{{ before }}</code></pre>\n </div>\n\n <div v-if=\"hasAfter\" class=\"rounded-md border border-primary/30 bg-primary/8 p-2\">\n <p class=\"mb-1 text-[10px] font-medium uppercase tracking-wider text-primary\">After</p>\n <pre\n class=\"nowheel nopan max-h-[132px] overflow-auto text-[11px] leading-relaxed text-foreground whitespace-pre\"\n ><code>{{ after }}</code></pre>\n </div>\n </div>\n\n <div v-else class=\"rounded-md border border-border/65 bg-muted/25 p-2\">\n <pre\n class=\"nowheel nopan max-h-[220px] overflow-auto text-[11px] leading-relaxed text-foreground whitespace-pre\"\n ><code>{{ singlePayload }}</code></pre>\n </div>\n </div>\n\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\nconst props = withDefaults(\n defineProps<{\n label: string;\n description?: string;\n color?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n }>(),\n {\n color: \"#22c55e\",\n },\n);\n</script>\n\n<template>\n <div\n class=\"fn-node w-[220px] rounded-lg border border-border bg-card px-4 py-3\"\n :data-active=\"active\"\n data-node-type=\"trigger\"\n >\n <div class=\"flex items-center gap-2 mb-1.5\">\n <div class=\"w-2 h-2 rounded-full\" :style=\"{ backgroundColor: color }\" />\n <span class=\"text-[10px] font-medium uppercase tracking-wider text-muted-foreground\"\n >Trigger</span\n >\n </div>\n <p class=\"text-sm font-medium text-foreground leading-snug\">{{ label }}</p>\n <div v-if=\"sourceAnchor?.label\" class=\"mt-1.5 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n <p v-if=\"description\" class=\"text-[11px] text-muted-foreground mt-1 leading-relaxed\">\n {{ description }}\n </p>\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\nconst props = withDefaults(\n defineProps<{\n label: string;\n description?: string;\n color?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n }>(),\n {\n color: \"#22c55e\",\n },\n);\n</script>\n\n<template>\n <div\n class=\"fn-node w-[220px] rounded-lg border border-border bg-card px-4 py-3\"\n :data-active=\"active\"\n data-node-type=\"trigger\"\n >\n <div class=\"flex items-center gap-2 mb-1.5\">\n <div class=\"w-2 h-2 rounded-full\" :style=\"{ backgroundColor: color }\" />\n <span class=\"text-[10px] font-medium uppercase tracking-wider text-muted-foreground\"\n >Trigger</span\n >\n </div>\n <p class=\"text-sm font-medium text-foreground leading-snug\">{{ label }}</p>\n <div v-if=\"sourceAnchor?.label\" class=\"mt-1.5 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n <p v-if=\"description\" class=\"text-[11px] text-muted-foreground mt-1 leading-relaxed\">\n {{ description }}\n </p>\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport dagre from \"@dagrejs/dagre\";\nimport { useStateStore, useStateValue } from \"@json-render/vue\";\nimport {\n Position,\n VueFlow,\n type NodeProps,\n type NodeTypesObject,\n useNodesInitialized,\n useVueFlow,\n} from \"@vue-flow/core\";\nimport {\n computed,\n defineComponent,\n getCurrentInstance,\n h,\n markRaw,\n nextTick,\n onMounted,\n onUnmounted,\n ref,\n watch,\n} from \"vue\";\n\nimport {\n CODE_NODE_MAX_INLINE_CHARS,\n estimateCodeNodeCharsPerLine,\n estimateCodeNodeWidth,\n} from \"../../code-node-sizing\";\nimport { exportFlowDiagram, type DiagramExportFormat } from \"../../composables/useDiagramExport\";\nimport { useFlaierRuntime } from \"../../composables/useFlaierRuntime\";\nimport {\n hasTwoslashHints,\n hasTwoslashHtml,\n normalizeTwoslashHtml,\n normalizeTwoslashLanguage,\n} from \"../../twoslash\";\nimport type {\n ArchitectureDataAsset,\n ArchitectureInterface,\n ArchitectureLink,\n ArchitectureNodeProps,\n FlaierCustomNodeContext,\n FlaierCustomNodeDefinition,\n FlaierCustomNodeSize,\n FlaierResolvedSourceAnchor,\n ArchitectureOperations,\n ArchitectureSecurity,\n ArchitectureZone,\n EdgeTransitionKind,\n FlowEdge,\n FlowNode,\n FlowNodeData,\n FlowNodeType,\n MagicMoveStep,\n SpecElement,\n TwoslashHtml,\n} from \"../../types\";\nimport TimelineControls from \"../controls/TimelineControls.vue\";\nimport ArchitectureSmoothEdge from \"../edges/ArchitectureSmoothEdge.vue\";\nimport ArchitectureNodeVue from \"../nodes/ArchitectureNode.vue\";\nimport CodeNodeVue from \"../nodes/CodeNode.vue\";\nimport DecisionNodeVue from \"../nodes/DecisionNode.vue\";\nimport DescriptionNodeVue from \"../nodes/DescriptionNode.vue\";\nimport ErrorNodeVue from \"../nodes/ErrorNode.vue\";\nimport LinkNodeVue from \"../nodes/LinkNode.vue\";\nimport PayloadNodeVue from \"../nodes/PayloadNode.vue\";\nimport TriggerNodeVue from \"../nodes/TriggerNode.vue\";\n\nconst props = withDefaults(\n defineProps<{\n title: string;\n description?: string;\n mode?: \"narrative\" | \"architecture\";\n zones?: ArchitectureZone[];\n direction?: \"horizontal\" | \"vertical\";\n minHeight?: number;\n layoutEngine?: \"dagre\" | \"manual\";\n layoutRankSep?: number;\n layoutNodeSep?: number;\n layoutEdgeSep?: number;\n themeMode?: \"local\" | \"document\";\n showHeaderOverlay?: boolean;\n showExportControls?: boolean;\n showThemeToggle?: boolean;\n showArchitectureInspector?: boolean;\n defaultArchitectureInspectorOpen?: boolean;\n showArchitectureInspectorToggleText?: boolean;\n }>(),\n {\n mode: \"narrative\",\n direction: \"horizontal\",\n layoutEngine: \"dagre\",\n themeMode: \"local\",\n showHeaderOverlay: true,\n showExportControls: true,\n showThemeToggle: true,\n showArchitectureInspector: true,\n defaultArchitectureInspectorOpen: true,\n showArchitectureInspectorToggleText: true,\n },\n);\n\nconst TYPE_MAP: Record<string, FlowNodeType> = {\n ArchitectureNode: \"architecture\",\n TriggerNode: \"trigger\",\n CodeNode: \"code\",\n DecisionNode: \"decision\",\n PayloadNode: \"payload\",\n ErrorNode: \"error\",\n DescriptionNode: \"description\",\n LinkNode: \"link\",\n};\n\nfunction toNodeType(elementType: string): FlowNodeType | undefined {\n if (TYPE_MAP[elementType]) {\n return TYPE_MAP[elementType];\n }\n\n return customNodes.value[elementType] ? elementType : undefined;\n}\n\nfunction getCustomNodeDefinition(elementType: string): FlaierCustomNodeDefinition | undefined {\n return customNodes.value[elementType];\n}\n\nconst DEFAULT_LAYOUT_ENGINE = \"dagre\";\nconst DEFAULT_FALLBACK_GAP = 420;\nconst DEFAULT_DAGRE_RANK_SEP_HORIZONTAL = 260;\nconst DEFAULT_DAGRE_NODE_SEP_HORIZONTAL = 120;\nconst DEFAULT_DAGRE_RANK_SEP_VERTICAL = 220;\nconst DEFAULT_DAGRE_NODE_SEP_VERTICAL = 120;\nconst DEFAULT_DAGRE_EDGE_SEP = 30;\nconst OVERVIEW_ENTER_ZOOM = 0.52;\nconst OVERVIEW_EXIT_ZOOM = 0.62;\nconst FLAIER_THEME_STORAGE_KEY = \"flaier-ui-theme\";\nconst ARCHITECTURE_ZONE_MIN_CONTENT_PADDING = 44;\nconst ARCHITECTURE_ZONE_MIN_BOTTOM_PADDING = 88;\nconst ARCHITECTURE_ZONE_LABEL_TOP = 12;\nconst ARCHITECTURE_ZONE_LABEL_HEIGHT = 22;\nconst ARCHITECTURE_ZONE_DESCRIPTION_HEIGHT = 16;\nconst ARCHITECTURE_ZONE_LABEL_TO_DESCRIPTION_GAP = 6;\nconst ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP = 12;\nconst ARCHITECTURE_ZONE_NESTED_LABEL_STEP = 18;\nconst ARCHITECTURE_ZONE_CONTAINED_ZONE_GAP = 46;\nconst EDGE_TRANSITION_KINDS: EdgeTransitionKind[] = [\n \"default\",\n \"success\",\n \"error\",\n \"warning\",\n \"retry\",\n \"async\",\n];\nconst EDGE_TRANSITION_KIND_SET = new Set(EDGE_TRANSITION_KINDS);\nconst EDGE_TRANSITION_TRANSPORT_SET = new Set([\"sync\", \"async\"]);\nconst EDGE_TRANSITION_CRITICALITY_SET = new Set([\"low\", \"medium\", \"high\"]);\nconst ARCHITECTURE_NODE_KINDS: Array<NonNullable<ArchitectureNodeProps[\"kind\"]>> = [\n \"service\",\n \"database\",\n \"queue\",\n \"cache\",\n \"gateway\",\n \"external\",\n \"compute\",\n];\nconst ARCHITECTURE_NODE_KIND_SET = new Set(ARCHITECTURE_NODE_KINDS);\nconst ARCHITECTURE_NODE_STATUS_VALUES: Array<NonNullable<ArchitectureNodeProps[\"status\"]>> = [\n \"planned\",\n \"active\",\n \"degraded\",\n \"retired\",\n];\nconst ARCHITECTURE_NODE_STATUS_SET = new Set(ARCHITECTURE_NODE_STATUS_VALUES);\nconst ARCHITECTURE_NODE_TIER_VALUES: Array<NonNullable<ArchitectureNodeProps[\"tier\"]>> = [\n \"edge\",\n \"application\",\n \"integration\",\n \"data\",\n \"platform\",\n \"external\",\n];\nconst ARCHITECTURE_NODE_TIER_SET = new Set(ARCHITECTURE_NODE_TIER_VALUES);\nconst ARCHITECTURE_INTERFACE_DIRECTION_VALUES: Array<\n NonNullable<ArchitectureInterface[\"direction\"]>\n> = [\"inbound\", \"outbound\", \"bidirectional\"];\nconst ARCHITECTURE_INTERFACE_DIRECTION_SET = new Set(ARCHITECTURE_INTERFACE_DIRECTION_VALUES);\nconst ARCHITECTURE_DATA_CLASSIFICATION_VALUES: Array<\n NonNullable<ArchitectureDataAsset[\"classification\"]>\n> = [\"public\", \"internal\", \"confidential\", \"restricted\"];\nconst ARCHITECTURE_DATA_CLASSIFICATION_SET = new Set(ARCHITECTURE_DATA_CLASSIFICATION_VALUES);\nconst ARCHITECTURE_ZONE_COLOR_PALETTE = [\n \"#38bdf8\",\n \"#22c55e\",\n \"#f59e0b\",\n \"#f97316\",\n \"#a78bfa\",\n \"#14b8a6\",\n \"#fb7185\",\n];\nconst SOURCE_ANCHOR_LINK_PATTERN = /^(https?:\\/\\/|vscode:\\/\\/|idea:\\/\\/)/i;\nconst SOURCE_ANCHOR_TRAILING_LOCATION_PATTERN = /^(.*?):(\\d+)(?::(\\d+))?$/;\n\ninterface NodeSize {\n width: number;\n height: number;\n}\n\ninterface OrderedNodeElement {\n key: string;\n index: number;\n nodeType: FlowNodeType;\n element: SpecElement;\n}\n\ninterface TimelineFrame {\n nodeIndex: number;\n nodeKey: string;\n localStep: number;\n totalLocalSteps: number;\n}\n\ninterface BranchChoice {\n id: string;\n label: string;\n description?: string;\n kind?: EdgeTransitionKind;\n}\n\ninterface ParsedTransition {\n to: string;\n label?: string;\n description?: string;\n kind?: EdgeTransitionKind;\n protocol?: string;\n transport?: \"sync\" | \"async\";\n auth?: string;\n contract?: string;\n criticality?: \"low\" | \"medium\" | \"high\";\n}\n\ninterface ParsedSourceAnchor {\n label: string;\n href?: string;\n}\n\ninterface ParsedAnchorLocation {\n path: string;\n line?: number;\n column?: number;\n}\n\ninterface ResolvedArchitectureZone extends ArchitectureZone {\n padding: number;\n}\n\ninterface ArchitectureZoneOverlay {\n id: string;\n label: string;\n description?: string;\n color: string;\n x: number;\n y: number;\n width: number;\n height: number;\n nodeCount: number;\n nestingDepth: number;\n labelLane: number;\n labelOffsetY: number;\n descriptionOffsetY: number;\n}\n\ninterface ArchitectureOutgoingEdge {\n target: string;\n label?: string;\n protocol?: string;\n transport?: \"sync\" | \"async\";\n auth?: string;\n criticality?: \"low\" | \"medium\" | \"high\";\n}\n\ninterface ArchitectureInspectorArchitectureView {\n type: \"ArchitectureNode\";\n label: string;\n sourceAnchor?: ParsedSourceAnchor;\n kind?: ArchitectureNodeProps[\"kind\"];\n status?: ArchitectureNodeProps[\"status\"];\n tier?: ArchitectureNodeProps[\"tier\"];\n technology?: string;\n runtime?: string;\n owner?: string;\n zoneLabel?: string;\n summary: string;\n tags: string[];\n responsibilities: string[];\n capabilities: string[];\n interfaces: ArchitectureInterface[];\n dataAssets: ArchitectureDataAsset[];\n security?: ArchitectureSecurity;\n operations?: ArchitectureOperations;\n links: ArchitectureLink[];\n outgoing: ArchitectureOutgoingEdge[];\n}\n\ninterface ArchitectureInspectorGenericView {\n type: \"Other\";\n label: string;\n sourceAnchor?: ParsedSourceAnchor;\n summary: string;\n elementType: string;\n}\n\ntype ArchitectureInspectorView =\n | ArchitectureInspectorArchitectureView\n | ArchitectureInspectorGenericView;\n\nconst EMPTY_ARCHITECTURE_INSPECTOR_NODE: ArchitectureInspectorArchitectureView = {\n type: \"ArchitectureNode\",\n label: \"\",\n summary: \"\",\n tags: [],\n responsibilities: [],\n capabilities: [],\n interfaces: [],\n dataAssets: [],\n links: [],\n outgoing: [],\n};\n\nconst runtime = useFlaierRuntime();\nconst spec = computed(() => runtime.spec.value);\nconst customNodes = computed(() => runtime.nodes.value);\nconst availableFlows = computed(() => runtime.flowOptions.value);\nconst activeFlowId = computed(() => runtime.activeFlowId.value);\nconst activeFlow = computed(() => {\n const activeId = activeFlowId.value;\n if (!activeId) return undefined;\n return availableFlows.value.find((flow) => flow.id === activeId);\n});\nconst showFlowSelector = computed(() => availableFlows.value.length > 1);\nconst showHeaderOverlay = computed(() => props.showHeaderOverlay !== false);\nconst overlayTitle = computed(() => activeFlow.value?.title ?? props.title);\nconst overlayDescription = computed(() => activeFlow.value?.description ?? props.description);\nconst headerModeLabel = computed(() => {\n if (showFlowSelector.value) {\n return \"Flow\";\n }\n\n return isArchitectureMode.value ? \"Diagram\" : \"Narrative\";\n});\nconst headerDropdownRef = ref<HTMLDivElement | null>(null);\nconst headerDropdownOpen = ref(false);\nconst exportMenuRef = ref<HTMLDivElement | null>(null);\nconst exportMenuOpen = ref(false);\nconst exportInFlight = ref<DiagramExportFormat | null>(null);\nconst exportError = ref<string | null>(null);\nconst containerRef = ref<HTMLDivElement | null>(null);\nconst sceneRef = ref<HTMLElement | null>(null);\nconst containerReady = ref(false);\nconst containerWidth = ref(0);\nconst containerHeight = ref(0);\nconst uiTheme = ref<\"dark\" | \"light\">(\"dark\");\nlet documentThemeObserver: MutationObserver | null = null;\nlet documentThemeMediaQuery: MediaQueryList | null = null;\nlet handleDocumentThemeMediaQueryChange: ((event: MediaQueryListEvent) => void) | null = null;\nconst isLightTheme = computed(() => uiTheme.value === \"light\");\nconst themeMode = computed(() => (props.themeMode === \"document\" ? \"document\" : \"local\"));\nconst isArchitectureMode = computed(() => props.mode === \"architecture\");\nconst showExportControls = computed(() => props.showExportControls !== false);\nconst showThemeToggle = computed(() => props.showThemeToggle !== false);\nconst showArchitectureInspectorPanel = computed(() => props.showArchitectureInspector !== false);\nconst defaultArchitectureInspectorOpen = computed(\n () => props.defaultArchitectureInspectorOpen !== false,\n);\nconst showArchitectureInspectorToggleText = computed(\n () => props.showArchitectureInspectorToggleText !== false,\n);\nconst showTopRightControls = computed(() => {\n return (\n showExportControls.value ||\n showThemeToggle.value ||\n (showExportControls.value && Boolean(exportError.value))\n );\n});\nconst architectureInspectorOpen = ref(props.defaultArchitectureInspectorOpen !== false);\nconst themeToggleLabel = computed(() => {\n return isLightTheme.value ? \"Switch to dark mode\" : \"Switch to light mode\";\n});\n\nconst architectureInspectorToggleLabel = computed(() => {\n return architectureInspectorOpen.value\n ? \"Hide architecture details sidebar\"\n : \"Show architecture details sidebar\";\n});\n\nconst exportButtonLabel = computed(() => {\n if (exportInFlight.value === \"png\") {\n return \"Exporting PNG...\";\n }\n\n if (exportInFlight.value === \"pdf\") {\n return \"Exporting PDF...\";\n }\n\n return \"Export full diagram\";\n});\n\nfunction toggleTheme() {\n if (themeMode.value === \"document\") {\n applyDocumentTheme(isLightTheme.value ? \"dark\" : \"light\");\n return;\n }\n\n uiTheme.value = isLightTheme.value ? \"dark\" : \"light\";\n}\n\nfunction toggleArchitectureInspector() {\n architectureInspectorOpen.value = !architectureInspectorOpen.value;\n}\n\nfunction normalizeTheme(value: unknown): \"dark\" | \"light\" | null {\n if (value === \"dark\" || value === \"light\") {\n return value;\n }\n\n return null;\n}\n\nfunction readStoredTheme() {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n try {\n return normalizeTheme(window.localStorage.getItem(FLAIER_THEME_STORAGE_KEY));\n } catch {\n return null;\n }\n}\n\nfunction getPreferredSystemTheme(): \"dark\" | \"light\" {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") {\n return \"dark\";\n }\n\n return window.matchMedia(\"(prefers-color-scheme: light)\").matches ? \"light\" : \"dark\";\n}\n\nfunction getDocumentTheme(): \"dark\" | \"light\" | null {\n if (typeof document === \"undefined\") {\n return null;\n }\n\n const root = document.documentElement;\n const dataTheme = root.getAttribute(\"data-theme\")?.trim().toLowerCase();\n\n if (dataTheme === \"dark\" || dataTheme === \"light\") {\n return dataTheme;\n }\n\n if (root.classList.contains(\"dark\")) {\n return \"dark\";\n }\n\n if (root.classList.contains(\"light\")) {\n return \"light\";\n }\n\n const colorScheme = root.style.colorScheme?.trim().toLowerCase();\n if (colorScheme === \"dark\" || colorScheme === \"light\") {\n return colorScheme;\n }\n\n return null;\n}\n\nfunction applyDocumentTheme(theme: \"dark\" | \"light\") {\n if (typeof document === \"undefined\") {\n return;\n }\n\n const root = document.documentElement;\n root.classList.toggle(\"dark\", theme === \"dark\");\n root.style.colorScheme = theme;\n}\n\nfunction persistTheme(theme: \"dark\" | \"light\") {\n if (typeof window === \"undefined\") {\n return;\n }\n\n try {\n window.localStorage.setItem(FLAIER_THEME_STORAGE_KEY, theme);\n } catch {\n // no-op when storage is unavailable\n }\n}\n\nfunction syncDocumentTheme() {\n uiTheme.value = getDocumentTheme() ?? getPreferredSystemTheme();\n}\n\nfunction startDocumentThemeSync() {\n if (typeof document !== \"undefined\" && typeof MutationObserver !== \"undefined\") {\n if (!documentThemeObserver) {\n documentThemeObserver = new MutationObserver(() => {\n syncDocumentTheme();\n });\n\n documentThemeObserver.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\", \"style\", \"data-theme\"],\n });\n }\n }\n\n if (typeof window !== \"undefined\" && typeof window.matchMedia === \"function\") {\n if (!documentThemeMediaQuery) {\n documentThemeMediaQuery = window.matchMedia(\"(prefers-color-scheme: light)\");\n }\n\n if (!handleDocumentThemeMediaQueryChange) {\n handleDocumentThemeMediaQueryChange = () => {\n syncDocumentTheme();\n };\n\n if (typeof documentThemeMediaQuery.addEventListener === \"function\") {\n documentThemeMediaQuery.addEventListener(\"change\", handleDocumentThemeMediaQueryChange);\n } else {\n documentThemeMediaQuery.addListener(handleDocumentThemeMediaQueryChange);\n }\n }\n }\n}\n\nfunction stopDocumentThemeSync() {\n if (documentThemeObserver) {\n documentThemeObserver.disconnect();\n documentThemeObserver = null;\n }\n\n if (documentThemeMediaQuery && handleDocumentThemeMediaQueryChange) {\n if (typeof documentThemeMediaQuery.removeEventListener === \"function\") {\n documentThemeMediaQuery.removeEventListener(\"change\", handleDocumentThemeMediaQueryChange);\n } else {\n documentThemeMediaQuery.removeListener(handleDocumentThemeMediaQueryChange);\n }\n }\n\n handleDocumentThemeMediaQueryChange = null;\n documentThemeMediaQuery = null;\n}\n\nfunction toggleHeaderDropdown() {\n if (!showFlowSelector.value) return;\n closeExportMenu();\n headerDropdownOpen.value = !headerDropdownOpen.value;\n}\n\nfunction closeHeaderDropdown() {\n headerDropdownOpen.value = false;\n}\n\nfunction toggleExportMenu() {\n if (exportInFlight.value) return;\n if (!canExportDiagram.value) return;\n\n closeHeaderDropdown();\n exportMenuOpen.value = !exportMenuOpen.value;\n}\n\nfunction closeExportMenu() {\n exportMenuOpen.value = false;\n}\n\nfunction handleFlowSelect(flowId: string) {\n if (!flowId) return;\n\n runtime.setActiveFlow(flowId);\n headerDropdownOpen.value = false;\n closeExportMenu();\n}\n\nwatch(showFlowSelector, (show) => {\n if (!show) {\n headerDropdownOpen.value = false;\n }\n});\n\nwatch(activeFlowId, () => {\n headerDropdownOpen.value = false;\n closeExportMenu();\n});\n\nwatch(uiTheme, (theme) => {\n if (themeMode.value === \"document\") {\n return;\n }\n\n persistTheme(theme);\n});\n\nwatch(\n themeMode,\n (mode) => {\n if (mode === \"document\") {\n startDocumentThemeSync();\n syncDocumentTheme();\n return;\n }\n\n stopDocumentThemeSync();\n uiTheme.value = readStoredTheme() ?? getPreferredSystemTheme();\n },\n { immediate: true },\n);\n\nconst rootElement = computed(() => {\n const activeSpec = spec.value;\n if (!activeSpec) return undefined;\n return activeSpec.elements[activeSpec.root];\n});\n\nconst orderedNodeElements = computed<OrderedNodeElement[]>(() => {\n const activeSpec = spec.value;\n const root = rootElement.value;\n\n if (!activeSpec || !root?.children?.length) return [];\n\n const result: OrderedNodeElement[] = [];\n const queue = [...root.children];\n const seen = new Set<string>();\n\n while (queue.length > 0) {\n const key = queue.shift();\n if (!key || seen.has(key)) continue;\n\n const element = activeSpec.elements[key];\n if (!element) continue;\n\n const nodeType = toNodeType(element.type);\n if (!nodeType) continue;\n\n seen.add(key);\n result.push({ key, index: result.length, nodeType, element });\n\n for (const childKey of element.children ?? []) {\n if (!seen.has(childKey)) {\n queue.push(childKey);\n }\n }\n }\n\n return result;\n});\n\nconst orderedNodeByKey = computed<Record<string, OrderedNodeElement>>(() => {\n const map: Record<string, OrderedNodeElement> = {};\n\n for (const node of orderedNodeElements.value) {\n map[node.key] = node;\n }\n\n return map;\n});\n\nconst rootLinearNextByKey = computed<Record<string, string>>(() => {\n const root = rootElement.value;\n if (!root?.children?.length) return {};\n const rootChildren = root.children;\n\n const map: Record<string, string> = {};\n\n rootChildren.forEach((key, index) => {\n const nextKey = rootChildren[index + 1];\n if (!nextKey) return;\n\n if (orderedNodeByKey.value[key] && orderedNodeByKey.value[nextKey]) {\n map[key] = nextKey;\n }\n });\n\n return map;\n});\n\nconst transitionMetaBySource = computed<Record<string, Record<string, ParsedTransition>>>(() => {\n const map: Record<string, Record<string, ParsedTransition>> = {};\n\n for (const node of orderedNodeElements.value) {\n const transitions = toTransitions(node.element.props.transitions).filter((transition) =>\n Boolean(orderedNodeByKey.value[transition.to]),\n );\n\n if (transitions.length === 0) continue;\n\n const byTarget: Record<string, ParsedTransition> = {};\n for (const transition of transitions) {\n if (byTarget[transition.to]) continue;\n byTarget[transition.to] = transition;\n }\n\n if (Object.keys(byTarget).length > 0) {\n map[node.key] = byTarget;\n }\n }\n\n return map;\n});\n\nconst outgoingNodeKeys = computed<Record<string, string[]>>(() => {\n const map: Record<string, string[]> = {};\n\n for (const node of orderedNodeElements.value) {\n const transitionTargets = toTransitions(node.element.props.transitions)\n .map((transition) => transition.to)\n .filter((key) => Boolean(orderedNodeByKey.value[key]));\n\n const explicit = (node.element.children ?? []).filter((key) =>\n Boolean(orderedNodeByKey.value[key]),\n );\n\n const combined = mergeOutgoingTargets(transitionTargets, explicit);\n\n if (combined.length > 0) {\n map[node.key] = combined;\n continue;\n }\n\n const fallback = rootLinearNextByKey.value[node.key];\n map[node.key] = fallback ? [fallback] : [];\n }\n\n return map;\n});\n\nconst incomingNodeKeys = computed<Record<string, string[]>>(() => {\n const map: Record<string, string[]> = {};\n\n for (const node of orderedNodeElements.value) {\n map[node.key] = [];\n }\n\n for (const [source, targets] of Object.entries(outgoingNodeKeys.value)) {\n for (const target of targets) {\n if (!map[target]) continue;\n map[target].push(source);\n }\n }\n\n return map;\n});\n\nconst startNodeKey = computed(() => {\n const root = rootElement.value;\n if (!root?.children?.length) return undefined;\n\n return root.children.find((key) => Boolean(orderedNodeByKey.value[key]));\n});\n\nfunction toOptionalString(value: unknown) {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction toStringArray(value: unknown) {\n if (!Array.isArray(value)) {\n return [];\n }\n\n return value\n .map((entry) => toTrimmedNonEmptyString(entry))\n .filter((entry): entry is string => Boolean(entry));\n}\n\nfunction toTrimmedNonEmptyString(value: unknown) {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction toRequiredString(value: unknown) {\n return toOptionalString(value) ?? \"\";\n}\n\nfunction toBoolean(value: unknown, fallback = false) {\n return typeof value === \"boolean\" ? value : fallback;\n}\n\nfunction toOptionalBoolean(value: unknown) {\n return typeof value === \"boolean\" ? value : undefined;\n}\n\nfunction toTwoslashHtml(value: unknown): TwoslashHtml | undefined {\n return normalizeTwoslashHtml(value);\n}\n\nfunction toPayloadFormat(value: unknown): \"json\" | \"yaml\" | \"text\" | undefined {\n if (value === \"json\" || value === \"yaml\" || value === \"text\") {\n return value;\n }\n\n return undefined;\n}\n\nfunction toArchitectureKind(value: unknown): ArchitectureNodeProps[\"kind\"] | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n if (ARCHITECTURE_NODE_KIND_SET.has(value as NonNullable<ArchitectureNodeProps[\"kind\"]>)) {\n return value as ArchitectureNodeProps[\"kind\"];\n }\n\n return undefined;\n}\n\nfunction toArchitectureZoneId(value: unknown) {\n return toTrimmedNonEmptyString(value);\n}\n\nfunction toArchitectureStatus(value: unknown): ArchitectureNodeProps[\"status\"] | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n if (ARCHITECTURE_NODE_STATUS_SET.has(value as NonNullable<ArchitectureNodeProps[\"status\"]>)) {\n return value as ArchitectureNodeProps[\"status\"];\n }\n\n return undefined;\n}\n\nfunction toArchitectureTier(value: unknown): ArchitectureNodeProps[\"tier\"] | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n if (ARCHITECTURE_NODE_TIER_SET.has(value as NonNullable<ArchitectureNodeProps[\"tier\"]>)) {\n return value as ArchitectureNodeProps[\"tier\"];\n }\n\n return undefined;\n}\n\nfunction toArchitectureInterfaces(value: unknown): ArchitectureInterface[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n const result: ArchitectureInterface[] = [];\n\n for (const rawEntry of value) {\n if (!rawEntry || typeof rawEntry !== \"object\") {\n continue;\n }\n\n const entry = rawEntry as Record<string, unknown>;\n const name = toTrimmedNonEmptyString(entry.name);\n if (!name) {\n continue;\n }\n\n const directionRaw = toTrimmedNonEmptyString(entry.direction);\n const direction =\n directionRaw &&\n ARCHITECTURE_INTERFACE_DIRECTION_SET.has(\n directionRaw as NonNullable<ArchitectureInterface[\"direction\"]>,\n )\n ? (directionRaw as ArchitectureInterface[\"direction\"])\n : undefined;\n\n result.push({\n name,\n protocol: toTrimmedNonEmptyString(entry.protocol),\n direction,\n contract: toTrimmedNonEmptyString(entry.contract),\n auth: toTrimmedNonEmptyString(entry.auth),\n notes: toTrimmedNonEmptyString(entry.notes),\n });\n }\n\n return result;\n}\n\nfunction toArchitectureDataAssets(value: unknown): ArchitectureDataAsset[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n const result: ArchitectureDataAsset[] = [];\n\n for (const rawEntry of value) {\n if (!rawEntry || typeof rawEntry !== \"object\") {\n continue;\n }\n\n const entry = rawEntry as Record<string, unknown>;\n const name = toTrimmedNonEmptyString(entry.name);\n if (!name) {\n continue;\n }\n\n const classificationRaw = toTrimmedNonEmptyString(entry.classification);\n const classification =\n classificationRaw &&\n ARCHITECTURE_DATA_CLASSIFICATION_SET.has(\n classificationRaw as NonNullable<ArchitectureDataAsset[\"classification\"]>,\n )\n ? (classificationRaw as ArchitectureDataAsset[\"classification\"])\n : undefined;\n\n result.push({\n name,\n kind: toTrimmedNonEmptyString(entry.kind),\n classification,\n retention: toTrimmedNonEmptyString(entry.retention),\n notes: toTrimmedNonEmptyString(entry.notes),\n });\n }\n\n return result;\n}\n\nfunction toArchitectureSecurity(value: unknown): ArchitectureSecurity | undefined {\n if (!value || typeof value !== \"object\") {\n return undefined;\n }\n\n const record = value as Record<string, unknown>;\n const security = {\n auth: toTrimmedNonEmptyString(record.auth),\n encryption: toTrimmedNonEmptyString(record.encryption),\n pii: toOptionalBoolean(record.pii),\n threatModel: toTrimmedNonEmptyString(record.threatModel),\n } satisfies ArchitectureSecurity;\n\n if (\n !security.auth &&\n !security.encryption &&\n security.pii === undefined &&\n !security.threatModel\n ) {\n return undefined;\n }\n\n return security;\n}\n\nfunction toArchitectureOperations(value: unknown): ArchitectureOperations | undefined {\n if (!value || typeof value !== \"object\") {\n return undefined;\n }\n\n const record = value as Record<string, unknown>;\n const operations = {\n owner: toTrimmedNonEmptyString(record.owner),\n slo: toTrimmedNonEmptyString(record.slo),\n alert: toTrimmedNonEmptyString(record.alert),\n runbook: toTrimmedNonEmptyString(record.runbook),\n } satisfies ArchitectureOperations;\n\n if (!operations.owner && !operations.slo && !operations.alert && !operations.runbook) {\n return undefined;\n }\n\n return operations;\n}\n\nfunction toArchitectureLinks(value: unknown): ArchitectureLink[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n const result: ArchitectureLink[] = [];\n\n for (const rawEntry of value) {\n if (!rawEntry || typeof rawEntry !== \"object\") {\n continue;\n }\n\n const entry = rawEntry as Record<string, unknown>;\n const label = toTrimmedNonEmptyString(entry.label);\n const href = toTrimmedNonEmptyString(entry.href);\n if (!label || !href) {\n continue;\n }\n\n result.push({\n label,\n href,\n });\n }\n\n return result;\n}\n\nfunction toArchitectureZones(value: unknown): ResolvedArchitectureZone[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n const seen = new Set<string>();\n const result: ResolvedArchitectureZone[] = [];\n\n for (const rawEntry of value) {\n if (!rawEntry || typeof rawEntry !== \"object\") {\n continue;\n }\n\n const entry = rawEntry as Record<string, unknown>;\n const id = toTrimmedNonEmptyString(entry.id);\n const label = toTrimmedNonEmptyString(entry.label);\n if (!id || !label || seen.has(id)) {\n continue;\n }\n\n seen.add(id);\n\n const paddingRaw = entry.padding;\n const padding =\n typeof paddingRaw === \"number\" && Number.isFinite(paddingRaw)\n ? Math.max(28, Math.min(180, Math.round(paddingRaw)))\n : 62;\n\n result.push({\n id,\n label,\n description: toTrimmedNonEmptyString(entry.description),\n color: toTrimmedNonEmptyString(entry.color),\n padding,\n });\n }\n\n return result;\n}\n\nfunction humanizeZoneId(value: string) {\n return value\n .replace(/[-_]+/g, \" \")\n .replace(/\\s+/g, \" \")\n .trim()\n .replace(/(^|\\s)\\w/g, (char) => char.toUpperCase());\n}\n\nfunction resolveZoneColor(index: number, explicitColor?: string) {\n return (\n explicitColor ||\n ARCHITECTURE_ZONE_COLOR_PALETTE[index % ARCHITECTURE_ZONE_COLOR_PALETTE.length] ||\n \"#38bdf8\"\n );\n}\n\nfunction toHexChannel(value: string) {\n return Number.parseInt(value, 16);\n}\n\nfunction hexToRgb(value: string) {\n const hex = value.trim().replace(/^#/, \"\");\n if (hex.length === 3) {\n const r = toHexChannel(`${hex[0]}${hex[0]}`);\n const g = toHexChannel(`${hex[1]}${hex[1]}`);\n const b = toHexChannel(`${hex[2]}${hex[2]}`);\n if ([r, g, b].every((channel) => Number.isFinite(channel))) {\n return { r, g, b };\n }\n\n return undefined;\n }\n\n if (hex.length === 6) {\n const r = toHexChannel(hex.slice(0, 2));\n const g = toHexChannel(hex.slice(2, 4));\n const b = toHexChannel(hex.slice(4, 6));\n if ([r, g, b].every((channel) => Number.isFinite(channel))) {\n return { r, g, b };\n }\n }\n\n return undefined;\n}\n\nfunction withAlpha(color: string, alpha: number) {\n const rgb = hexToRgb(color);\n if (!rgb) {\n return color;\n }\n\n return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`;\n}\n\nfunction toPositiveInteger(value: unknown) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n return undefined;\n }\n\n const asInteger = Math.floor(value);\n return asInteger > 0 ? asInteger : undefined;\n}\n\nfunction parseInlineSourceAnchorLocation(value: string): ParsedAnchorLocation | undefined {\n const trimmed = value.trim();\n if (!trimmed) return undefined;\n\n const matched = SOURCE_ANCHOR_TRAILING_LOCATION_PATTERN.exec(trimmed);\n if (!matched) {\n return {\n path: trimmed,\n };\n }\n\n const rawPath = matched[1]?.trim();\n const rawLine = matched[2];\n const rawColumn = matched[3];\n\n if (!rawPath || !rawLine) {\n return {\n path: trimmed,\n };\n }\n\n const line = Number(rawLine);\n const column = rawColumn ? Number(rawColumn) : undefined;\n\n return {\n path: rawPath,\n line: Number.isFinite(line) && line > 0 ? Math.floor(line) : undefined,\n column: Number.isFinite(column) && (column ?? 0) > 0 ? Math.floor(column as number) : undefined,\n };\n}\n\nfunction toVsCodeFileHref(path: string, line?: number, column?: number) {\n const normalizedPath = path.trim().replace(/\\\\/g, \"/\");\n if (!normalizedPath) return undefined;\n\n const encodedPath = encodeURI(normalizedPath);\n const linePart = line ? `:${line}` : \"\";\n const columnPart = line && column ? `:${column}` : \"\";\n\n return `vscode://file/${encodedPath}${linePart}${columnPart}`;\n}\n\nfunction resolveSourceAnchorHref(\n path: string,\n line?: number,\n column?: number,\n explicitHref?: string,\n) {\n if (explicitHref) {\n return explicitHref;\n }\n\n if (SOURCE_ANCHOR_LINK_PATTERN.test(path)) {\n return path;\n }\n\n return toVsCodeFileHref(path, line, column);\n}\n\nfunction toSourceAnchor(value: unknown): ParsedSourceAnchor | undefined {\n const inlineAnchor = toTrimmedNonEmptyString(value);\n if (inlineAnchor) {\n const parsed = parseInlineSourceAnchorLocation(inlineAnchor);\n\n return {\n label: inlineAnchor,\n href: parsed ? resolveSourceAnchorHref(parsed.path, parsed.line, parsed.column) : undefined,\n };\n }\n\n if (!value || typeof value !== \"object\") {\n return undefined;\n }\n\n const record = value as Record<string, unknown>;\n const path = toTrimmedNonEmptyString(record.path);\n if (!path) {\n return undefined;\n }\n\n const line = toPositiveInteger(record.line);\n const column = toPositiveInteger(record.column);\n const explicitLabel = toTrimmedNonEmptyString(record.label);\n const explicitHref = toTrimmedNonEmptyString(record.href);\n\n const location = [path];\n if (line !== undefined) {\n location.push(String(line));\n\n if (column !== undefined) {\n location.push(String(column));\n }\n }\n\n const label = explicitLabel ?? location.join(\":\");\n\n return {\n label,\n href: resolveSourceAnchorHref(path, line, column, explicitHref),\n };\n}\n\nfunction resolveNodeSourceAnchor(nodeProps: Record<string, unknown>) {\n const explicit = toSourceAnchor(nodeProps.sourceAnchor);\n if (explicit) {\n return explicit;\n }\n\n const fileFallback = toTrimmedNonEmptyString(nodeProps.file);\n if (!fileFallback) {\n return undefined;\n }\n\n return {\n label: fileFallback,\n } satisfies ParsedSourceAnchor;\n}\n\nfunction createCustomNodeContext(\n node: OrderedNodeElement,\n): FlaierCustomNodeContext<Record<string, unknown>> {\n return {\n key: node.key,\n elementType: node.element.type,\n props: node.element.props,\n sourceAnchor: resolveNodeSourceAnchor(node.element.props) as\n | FlaierResolvedSourceAnchor\n | undefined,\n };\n}\n\nfunction toCustomNodeSize(value: FlaierCustomNodeSize | undefined): NodeSize | undefined {\n if (!value) {\n return undefined;\n }\n\n const width = Number(value.width);\n const height = Number(value.height);\n\n if (!Number.isFinite(width) || !Number.isFinite(height)) {\n return undefined;\n }\n\n return {\n width: Math.max(120, Math.round(width)),\n height: Math.max(72, Math.round(height)),\n };\n}\n\nfunction getNodeSummary(node: OrderedNodeElement) {\n const customNode = getCustomNodeDefinition(node.element.type);\n if (customNode?.getSummary) {\n return customNode.getSummary(createCustomNodeContext(node)) ?? \"\";\n }\n\n if (node.element.type === \"CodeNode\") {\n return (\n toTrimmedNonEmptyString(node.element.props.story) ??\n toTrimmedNonEmptyString(node.element.props.comment) ??\n \"\"\n );\n }\n\n if (node.element.type === \"DescriptionNode\") {\n return toTrimmedNonEmptyString(node.element.props.body) ?? \"\";\n }\n\n if (node.element.type === \"DecisionNode\") {\n return (\n toTrimmedNonEmptyString(node.element.props.description) ??\n toTrimmedNonEmptyString(node.element.props.condition) ??\n \"\"\n );\n }\n\n if (node.element.type === \"PayloadNode\") {\n return toTrimmedNonEmptyString(node.element.props.description) ?? \"\";\n }\n\n if (node.element.type === \"ErrorNode\") {\n const message = toTrimmedNonEmptyString(node.element.props.message);\n const cause = toTrimmedNonEmptyString(node.element.props.cause);\n const mitigation = toTrimmedNonEmptyString(node.element.props.mitigation);\n\n return [message, cause ? `Cause: ${cause}` : \"\", mitigation ? `Mitigation: ${mitigation}` : \"\"]\n .filter((value): value is string => typeof value === \"string\" && value.length > 0)\n .join(\" \");\n }\n\n if (node.element.type === \"ArchitectureNode\") {\n const technology = toTrimmedNonEmptyString(node.element.props.technology);\n const description = toTrimmedNonEmptyString(node.element.props.description);\n\n return [technology ? `Technology: ${technology}` : \"\", description ?? \"\"]\n .filter((value): value is string => typeof value === \"string\" && value.length > 0)\n .join(\" \");\n }\n\n return toTrimmedNonEmptyString(node.element.props.description) ?? \"\";\n}\n\nfunction createCustomNodeRenderer(\n elementType: string,\n definition: FlaierCustomNodeDefinition,\n displayName: string,\n) {\n return markRaw(\n defineComponent<NodeProps<FlowNodeData>>({\n name: `Flaier${displayName}Node`,\n props: [\n \"id\",\n \"type\",\n \"selected\",\n \"connectable\",\n \"position\",\n \"dimensions\",\n \"label\",\n \"isValidTargetPos\",\n \"isValidSourcePos\",\n \"parent\",\n \"parentNodeId\",\n \"dragging\",\n \"resizing\",\n \"zIndex\",\n \"targetPosition\",\n \"sourcePosition\",\n \"dragHandle\",\n \"data\",\n \"events\",\n ],\n setup(nodeProps) {\n return () =>\n h(definition.component, {\n ...nodeProps.data?.props,\n active: nodeProps.data?.active,\n nodeKey: nodeProps.data?.key,\n elementType: nodeProps.data?.elementType ?? elementType,\n sourceAnchor: nodeProps.data?.sourceAnchor,\n });\n },\n }),\n );\n}\n\nconst customNodeTypes = computed<NodeTypesObject>(() => {\n return Object.fromEntries(\n Object.entries(customNodes.value).map(([elementType, definition]) => {\n const displayName = elementType.replace(/[^a-z0-9]+/gi, \"\") || \"Custom\";\n\n return [elementType, createCustomNodeRenderer(elementType, definition, displayName)];\n }),\n );\n});\n\nfunction codeNodeTwoslashEnabled(element: SpecElement) {\n if (element.type !== \"CodeNode\") return false;\n\n if (!normalizeTwoslashLanguage(toOptionalString(element.props.language))) {\n return false;\n }\n\n if (!hasTwoslashHtml(toTwoslashHtml(element.props.twoslashHtml))) {\n return false;\n }\n\n const requested = toOptionalBoolean(element.props.twoslash);\n if (requested === true) return true;\n if (requested === false) return false;\n\n const variants = [\n toRequiredString(element.props.code),\n ...toMagicMoveSteps(element.props.magicMoveSteps).map((step) => step.code),\n ];\n\n return variants.some((code) => hasTwoslashHints(code));\n}\n\nfunction toPositiveNumber(value: unknown, fallback: number, min = 1) {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return Math.max(min, Math.floor(value));\n }\n\n return fallback;\n}\n\nfunction toMagicMoveSteps(value: unknown): MagicMoveStep[] {\n if (!Array.isArray(value)) return [];\n\n return value\n .filter((item): item is MagicMoveStep => {\n if (!item || typeof item !== \"object\") return false;\n\n const record = item as Record<string, unknown>;\n if (typeof record.code !== \"string\") return false;\n\n const optionalKeys: Array<\"title\" | \"comment\" | \"story\" | \"speaker\"> = [\n \"title\",\n \"comment\",\n \"story\",\n \"speaker\",\n ];\n\n return optionalKeys.every((key) => {\n const current = record[key];\n return current === undefined || typeof current === \"string\";\n });\n })\n .map((item) => ({\n code: item.code,\n title: toOptionalString(item.title),\n comment: toOptionalString(item.comment),\n story: toOptionalString(item.story),\n speaker: toOptionalString(item.speaker),\n }));\n}\n\nfunction toTransitionKind(value: unknown): EdgeTransitionKind | undefined {\n if (typeof value !== \"string\") return undefined;\n return EDGE_TRANSITION_KIND_SET.has(value as EdgeTransitionKind)\n ? (value as EdgeTransitionKind)\n : undefined;\n}\n\nfunction toTransitionTransport(value: unknown): \"sync\" | \"async\" | undefined {\n if (typeof value !== \"string\") return undefined;\n return EDGE_TRANSITION_TRANSPORT_SET.has(value) ? (value as \"sync\" | \"async\") : undefined;\n}\n\nfunction toTransitionCriticality(value: unknown): \"low\" | \"medium\" | \"high\" | undefined {\n if (typeof value !== \"string\") return undefined;\n return EDGE_TRANSITION_CRITICALITY_SET.has(value)\n ? (value as \"low\" | \"medium\" | \"high\")\n : undefined;\n}\n\nfunction toTransitions(value: unknown): ParsedTransition[] {\n if (!Array.isArray(value)) return [];\n\n return value\n .filter((item): item is Record<string, unknown> => {\n if (!item || typeof item !== \"object\") return false;\n if (!toOptionalString(item.to)) return false;\n\n const label = item.label;\n const description = item.description;\n const kind = item.kind;\n const protocol = item.protocol;\n const transport = item.transport;\n const auth = item.auth;\n const contract = item.contract;\n const criticality = item.criticality;\n\n if (label !== undefined && typeof label !== \"string\") return false;\n if (description !== undefined && typeof description !== \"string\") return false;\n if (kind !== undefined && !toTransitionKind(kind)) return false;\n if (protocol !== undefined && typeof protocol !== \"string\") return false;\n if (transport !== undefined && !toTransitionTransport(transport)) return false;\n if (auth !== undefined && typeof auth !== \"string\") return false;\n if (contract !== undefined && typeof contract !== \"string\") return false;\n if (criticality !== undefined && !toTransitionCriticality(criticality)) return false;\n\n return true;\n })\n .map((item) => ({\n to: toRequiredString(item.to),\n label: toOptionalString(item.label),\n description: toOptionalString(item.description),\n kind: toTransitionKind(item.kind),\n protocol: toOptionalString(item.protocol),\n transport: toTransitionTransport(item.transport),\n auth: toOptionalString(item.auth),\n contract: toOptionalString(item.contract),\n criticality: toTransitionCriticality(item.criticality),\n }));\n}\n\nfunction resolveTransitionEdgeLabel(transition?: ParsedTransition) {\n if (!transition) {\n return undefined;\n }\n\n const metadataParts = [transition.protocol, transition.transport, transition.criticality].filter(\n (value): value is string => Boolean(value),\n );\n\n if (transition.label) {\n return metadataParts.length > 0\n ? `${transition.label} (${metadataParts.join(\" | \")})`\n : transition.label;\n }\n\n if (metadataParts.length > 0) {\n return metadataParts.join(\" | \");\n }\n\n return undefined;\n}\n\nfunction mergeOutgoingTargets(primary: string[], secondary: string[]) {\n const merged: string[] = [];\n const seen = new Set<string>();\n\n for (const target of [...primary, ...secondary]) {\n if (!target || seen.has(target)) continue;\n\n seen.add(target);\n merged.push(target);\n }\n\n return merged;\n}\n\nfunction getNodeFrameCount(element: SpecElement) {\n if (element.type !== \"CodeNode\") return 1;\n\n const magicMoveSteps = toMagicMoveSteps(element.props.magicMoveSteps);\n const baseSteps = Math.max(1, magicMoveSteps.length);\n\n if (magicMoveSteps.length > 0 && codeNodeTwoslashEnabled(element)) {\n return baseSteps + 1;\n }\n\n return baseSteps;\n}\n\nfunction getCodeNodeMaxLines(element: SpecElement) {\n const rootCodeLines = toRequiredString(element.props.code).split(\"\\n\").length;\n const stepLines = toMagicMoveSteps(element.props.magicMoveSteps).map(\n (step) => step.code.split(\"\\n\").length,\n );\n\n return Math.max(rootCodeLines, ...stepLines);\n}\n\nfunction getCodeNodeMaxLineLength(element: SpecElement) {\n const variants = [\n toRequiredString(element.props.code),\n ...toMagicMoveSteps(element.props.magicMoveSteps).map((step) => step.code),\n ];\n\n return variants.reduce((max, code) => {\n const lineMax = code\n .split(\"\\n\")\n .reduce((lineLengthMax, line) => Math.max(lineLengthMax, line.length), 0);\n\n return Math.max(max, lineMax);\n }, 0);\n}\n\nfunction estimateWrappedLines(text: string, charsPerLine = 48) {\n return text\n .split(\"\\n\")\n .reduce((total, line) => total + Math.max(1, Math.ceil(line.length / charsPerLine)), 0);\n}\n\nfunction getCodeNodeWrappedLines(element: SpecElement, charsPerLine = 44) {\n const variants = [\n toRequiredString(element.props.code),\n ...toMagicMoveSteps(element.props.magicMoveSteps).map((step) => step.code),\n ];\n\n return variants.reduce((max, code) => {\n return Math.max(max, estimateWrappedLines(code, charsPerLine));\n }, 1);\n}\n\nfunction hasCodeNodeStoryMeta(element: SpecElement) {\n return toMagicMoveSteps(element.props.magicMoveSteps).some((step) => step.title || step.speaker);\n}\n\nfunction getCodeNodeStoryLines(element: SpecElement) {\n const variants = [\n toOptionalString(element.props.story),\n toOptionalString(element.props.comment),\n ...toMagicMoveSteps(element.props.magicMoveSteps).flatMap((step) => [step.story, step.comment]),\n ].filter((value): value is string => typeof value === \"string\" && value.length > 0);\n\n if (variants.length === 0) return 0;\n\n return variants.reduce((max, current) => Math.max(max, estimateWrappedLines(current)), 1);\n}\n\nfunction estimateNodeTextLines(value: unknown, charsPerLine: number) {\n const text = toOptionalString(value);\n if (!text) return 0;\n return estimateWrappedLines(text, charsPerLine);\n}\n\nfunction estimateCodeNodeSize(element: SpecElement): NodeSize {\n const maxLineLength = getCodeNodeMaxLineLength(element);\n const nodeWidth = estimateCodeNodeWidth(maxLineLength);\n const codeCharsPerLine = estimateCodeNodeCharsPerLine(nodeWidth);\n const autoWrapEnabled = maxLineLength > CODE_NODE_MAX_INLINE_CHARS;\n const wrapEnabled = toBoolean(element.props.wrapLongLines) || autoWrapEnabled;\n\n const codeLines = wrapEnabled\n ? getCodeNodeWrappedLines(element, codeCharsPerLine)\n : getCodeNodeMaxLines(element);\n const storyLines = getCodeNodeStoryLines(element);\n const storyHasMeta = hasCodeNodeStoryMeta(element);\n\n const codeViewportHeight = wrapEnabled\n ? Math.min(400, Math.max(190, 72 + codeLines * 16))\n : Math.min(340, Math.max(160, 84 + codeLines * 17));\n\n const storyViewportHeight =\n storyLines > 0 ? Math.min(220, Math.max(88, (storyHasMeta ? 56 : 34) + storyLines * 18)) : 0;\n\n return {\n width: nodeWidth,\n height: Math.min(760, Math.max(230, 42 + codeViewportHeight + storyViewportHeight + 14)),\n };\n}\n\nfunction estimateNodeSize(node: OrderedNodeElement): NodeSize {\n const { element } = node;\n const customNode = getCustomNodeDefinition(element.type);\n\n if (customNode?.estimateSize) {\n const customSize = toCustomNodeSize(customNode.estimateSize(createCustomNodeContext(node)));\n if (customSize) {\n return customSize;\n }\n }\n\n if (customNode) {\n return {\n width: 240,\n height: 120,\n };\n }\n\n if (element.type === \"ArchitectureNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 28));\n const technologyLines = estimateNodeTextLines(element.props.technology, 30);\n const ownerLines = estimateNodeTextLines(element.props.owner, 30);\n const runtimeLines = estimateNodeTextLines(element.props.runtime, 30);\n const descriptionLines = estimateNodeTextLines(element.props.description, 34);\n const capabilityCount = Math.min(4, toStringArray(element.props.capabilities).length);\n const tagCount = Math.min(4, toStringArray(element.props.tags).length);\n const chipRows =\n (capabilityCount > 0 ? Math.ceil(capabilityCount / 2) : 0) + (tagCount > 0 ? 1 : 0);\n const metaRows =\n toArchitectureStatus(element.props.status) || toArchitectureTier(element.props.tier) ? 1 : 0;\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 270,\n height: Math.min(\n 460,\n Math.max(\n 144,\n 58 +\n labelLines * 19 +\n technologyLines * 14 +\n ownerLines * 12 +\n runtimeLines * 12 +\n descriptionLines * 15 +\n metaRows * 16 +\n chipRows * 18 +\n anchorHeight,\n ),\n ),\n };\n }\n\n if (element.type === \"CodeNode\") {\n return estimateCodeNodeSize(element);\n }\n\n if (element.type === \"TriggerNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 24));\n const descriptionLines = estimateNodeTextLines(element.props.description, 30);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 220,\n height: Math.min(\n 300,\n Math.max(100, 46 + labelLines * 18 + descriptionLines * 15 + anchorHeight),\n ),\n };\n }\n\n if (element.type === \"DecisionNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 26));\n const conditionLines = estimateNodeTextLines(element.props.condition, 34);\n const descriptionLines = estimateNodeTextLines(element.props.description, 34);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 250,\n height: Math.min(\n 360,\n Math.max(\n 122,\n 50 + labelLines * 18 + conditionLines * 16 + descriptionLines * 15 + anchorHeight,\n ),\n ),\n };\n }\n\n if (element.type === \"PayloadNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 32));\n const descriptionLines = estimateNodeTextLines(element.props.description, 34);\n const beforeLines = estimateNodeTextLines(element.props.before, 40);\n const afterLines = estimateNodeTextLines(element.props.after, 40);\n const payloadLines = estimateNodeTextLines(element.props.payload, 40);\n const bodyLines = Math.max(payloadLines, beforeLines + afterLines);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 300,\n height: Math.min(\n 540,\n Math.max(160, 60 + labelLines * 18 + descriptionLines * 14 + bodyLines * 10 + anchorHeight),\n ),\n };\n }\n\n if (element.type === \"ErrorNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 30));\n const messageLines = Math.max(1, estimateNodeTextLines(element.props.message, 34));\n const causeLines = estimateNodeTextLines(element.props.cause, 34);\n const mitigationLines = estimateNodeTextLines(element.props.mitigation, 34);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 280,\n height: Math.min(\n 440,\n Math.max(\n 140,\n 58 +\n labelLines * 18 +\n messageLines * 16 +\n causeLines * 15 +\n mitigationLines * 15 +\n anchorHeight,\n ),\n ),\n };\n }\n\n if (element.type === \"DescriptionNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 26));\n const bodyLines = Math.max(1, estimateNodeTextLines(element.props.body, 30));\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 240,\n height: Math.min(360, Math.max(118, 44 + labelLines * 18 + bodyLines * 16 + anchorHeight)),\n };\n }\n\n if (element.type === \"LinkNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 24));\n const descriptionLines = estimateNodeTextLines(element.props.description, 30);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 220,\n height: Math.min(\n 300,\n Math.max(98, 42 + labelLines * 18 + descriptionLines * 15 + anchorHeight),\n ),\n };\n }\n\n return {\n width: 240,\n height: 120,\n };\n}\n\nconst selectedBranchByNode = ref<Record<string, string>>({});\nconst pathFrames = ref<TimelineFrame[]>([]);\n\nfunction createFramesForNode(nodeKey: string): TimelineFrame[] {\n const node = orderedNodeByKey.value[nodeKey];\n if (!node) return [];\n\n const totalLocalSteps = getNodeFrameCount(node.element);\n\n return Array.from({ length: totalLocalSteps }, (_, localStep) => ({\n nodeIndex: node.index,\n nodeKey,\n localStep,\n totalLocalSteps,\n }));\n}\n\nfunction resolveNextNode(nodeKey: string, options: string[]) {\n const selected = selectedBranchByNode.value[nodeKey];\n if (selected && options.includes(selected)) {\n return selected;\n }\n\n return options[0];\n}\n\nfunction buildGuidedPath(startKey: string, maxFrames = 450): TimelineFrame[] {\n const frames: TimelineFrame[] = [];\n const visitedEdges = new Map<string, number>();\n let currentKey: string | undefined = startKey;\n\n while (currentKey && frames.length < maxFrames) {\n const nodeFrames = createFramesForNode(currentKey);\n if (nodeFrames.length === 0) break;\n\n frames.push(...nodeFrames);\n\n const options = outgoingNodeKeys.value[currentKey] ?? [];\n if (options.length === 0) break;\n\n const nextKey = resolveNextNode(currentKey, options);\n if (!nextKey) break;\n\n const edgeKey = `${currentKey}->${nextKey}`;\n const edgeVisits = (visitedEdges.get(edgeKey) ?? 0) + 1;\n visitedEdges.set(edgeKey, edgeVisits);\n if (edgeVisits > 2) break;\n\n currentKey = nextKey;\n }\n\n return frames;\n}\n\nfunction findNearestFrameIndex(frames: TimelineFrame[], nodeKey: string, anchor = 0) {\n let bestIndex = -1;\n let bestDistance = Number.POSITIVE_INFINITY;\n\n for (let index = 0; index < frames.length; index += 1) {\n if (frames[index]?.nodeKey !== nodeKey) continue;\n\n const distance = Math.abs(index - anchor);\n if (distance < bestDistance) {\n bestDistance = distance;\n bestIndex = index;\n }\n }\n\n return bestIndex;\n}\n\nfunction sortOptionsForTraversal(sourceKey: string, options: string[]) {\n const selected = selectedBranchByNode.value[sourceKey];\n\n return [...options].sort((a, b) => {\n const aSelected = a === selected;\n const bSelected = b === selected;\n\n if (aSelected !== bSelected) {\n return aSelected ? -1 : 1;\n }\n\n const aIndex = orderedNodeByKey.value[a]?.index ?? Number.MAX_SAFE_INTEGER;\n const bIndex = orderedNodeByKey.value[b]?.index ?? Number.MAX_SAFE_INTEGER;\n\n return aIndex - bIndex;\n });\n}\n\nfunction findPathKeysToNode(startKey: string, targetKey: string) {\n if (startKey === targetKey) {\n return [startKey];\n }\n\n const queue: Array<{ key: string; path: string[]; depth: number }> = [\n {\n key: startKey,\n path: [startKey],\n depth: 0,\n },\n ];\n\n const visitedDepth = new Map<string, number>([[startKey, 0]]);\n const maxDepth = Math.max(8, orderedNodeElements.value.length + 8);\n const maxIterations = Math.max(\n 80,\n orderedNodeElements.value.length * orderedNodeElements.value.length * 2,\n );\n let guard = 0;\n\n while (queue.length > 0 && guard < maxIterations) {\n guard += 1;\n\n const current = queue.shift();\n if (!current) continue;\n if (current.depth >= maxDepth) continue;\n\n const options = sortOptionsForTraversal(current.key, outgoingNodeKeys.value[current.key] ?? []);\n\n for (const option of options) {\n if (!orderedNodeByKey.value[option]) continue;\n\n const nextDepth = current.depth + 1;\n if (option === targetKey) {\n return [...current.path, option];\n }\n\n const knownDepth = visitedDepth.get(option);\n if (knownDepth !== undefined && knownDepth <= nextDepth) {\n continue;\n }\n\n visitedDepth.set(option, nextDepth);\n queue.push({\n key: option,\n path: [...current.path, option],\n depth: nextDepth,\n });\n }\n }\n\n return null;\n}\n\nfunction applyBranchSelectionsForPath(pathKeys: string[]) {\n if (pathKeys.length < 2) return;\n\n const nextSelected = { ...selectedBranchByNode.value };\n\n for (let index = 0; index < pathKeys.length - 1; index += 1) {\n const source = pathKeys[index];\n const target = pathKeys[index + 1];\n if (!source || !target) continue;\n\n const options = outgoingNodeKeys.value[source] ?? [];\n if (options.length > 1 && options.includes(target)) {\n nextSelected[source] = target;\n }\n }\n\n selectedBranchByNode.value = nextSelected;\n}\n\nconst totalSteps = computed(() => pathFrames.value.length);\nconst maxStepIndex = computed(() => Math.max(0, totalSteps.value - 1));\n\nconst { set } = useStateStore();\nconst currentStepState = useStateValue<number>(\"/currentStep\");\nconst playingState = useStateValue<boolean>(\"/playing\");\n\nfunction clampStep(value: number) {\n if (!Number.isFinite(value)) return 0;\n const step = Math.floor(value);\n return Math.max(0, Math.min(step, maxStepIndex.value));\n}\n\nconst currentStep = computed<number>({\n get() {\n return clampStep(Number(currentStepState.value ?? 0));\n },\n set(value: number) {\n set(\"/currentStep\", clampStep(value));\n },\n});\n\nconst playing = computed<boolean>({\n get() {\n return Boolean(playingState.value ?? false);\n },\n set(value: boolean) {\n set(\"/playing\", value);\n },\n});\n\nwatch(\n [startNodeKey, orderedNodeElements, isArchitectureMode],\n ([start, , architectureMode]) => {\n if (architectureMode) {\n selectedBranchByNode.value = {};\n pathFrames.value = [];\n currentStep.value = 0;\n playing.value = false;\n return;\n }\n\n selectedBranchByNode.value = {};\n\n if (!start) {\n pathFrames.value = [];\n currentStep.value = 0;\n return;\n }\n\n const built = buildGuidedPath(start);\n pathFrames.value = built.length > 0 ? built : createFramesForNode(start);\n currentStep.value = clampStep(Number(currentStepState.value ?? 0));\n },\n { immediate: true },\n);\n\nwatch(totalSteps, () => {\n currentStep.value = clampStep(currentStep.value);\n});\n\nconst intervalMs = computed(() => {\n const value = Number(runtime.interval.value);\n if (!Number.isFinite(value) || value <= 0) return 3000;\n return Math.max(250, Math.floor(value));\n});\n\nlet timer: ReturnType<typeof setInterval> | null = null;\n\nfunction clearTimer() {\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n}\n\nfunction next() {\n if (isArchitectureMode.value) {\n return false;\n }\n\n if (currentStep.value >= totalSteps.value - 1) {\n return false;\n }\n\n currentStep.value += 1;\n return true;\n}\n\nwatch(\n [playing, totalSteps, intervalMs],\n ([isPlaying, steps, interval]) => {\n clearTimer();\n\n if (!isPlaying || steps <= 1) return;\n\n timer = setInterval(() => {\n const advanced = next();\n if (!advanced) {\n playing.value = false;\n }\n }, interval);\n },\n { immediate: true },\n);\n\nfunction prev() {\n if (isArchitectureMode.value) {\n return;\n }\n\n if (currentStep.value > 0) {\n currentStep.value -= 1;\n }\n}\n\nfunction goTo(step: number) {\n if (isArchitectureMode.value) {\n return;\n }\n\n currentStep.value = clampStep(step);\n}\n\nfunction togglePlay() {\n if (isArchitectureMode.value) {\n playing.value = false;\n return;\n }\n\n if (totalSteps.value <= 1) {\n playing.value = false;\n return;\n }\n\n playing.value = !playing.value;\n}\n\nconst activeFrame = computed(() => pathFrames.value[currentStep.value]);\nconst nextPlannedNodeKey = computed(() => pathFrames.value[currentStep.value + 1]?.nodeKey);\n\nfunction jumpToNode(nodeKey: string) {\n if (!orderedNodeByKey.value[nodeKey]) return;\n\n playing.value = false;\n\n const existingIndex = findNearestFrameIndex(pathFrames.value, nodeKey, currentStep.value);\n if (existingIndex >= 0) {\n currentStep.value = existingIndex;\n return;\n }\n\n const start = startNodeKey.value;\n if (!start) {\n const standaloneFrames = createFramesForNode(nodeKey);\n if (standaloneFrames.length === 0) return;\n\n pathFrames.value = standaloneFrames;\n currentStep.value = 0;\n return;\n }\n\n const pathKeys = findPathKeysToNode(start, nodeKey);\n if (pathKeys) {\n applyBranchSelectionsForPath(pathKeys);\n }\n\n const rebuiltFrames = buildGuidedPath(start);\n pathFrames.value = rebuiltFrames.length > 0 ? rebuiltFrames : createFramesForNode(start);\n\n const rebuiltIndex = findNearestFrameIndex(pathFrames.value, nodeKey, currentStep.value);\n if (rebuiltIndex >= 0) {\n currentStep.value = rebuiltIndex;\n return;\n }\n\n const standaloneFrames = createFramesForNode(nodeKey);\n if (standaloneFrames.length === 0) return;\n\n pathFrames.value = standaloneFrames;\n currentStep.value = 0;\n}\n\nconst resolvedLayoutEngine = computed<\"dagre\" | \"manual\">(() => {\n return props.layoutEngine === \"manual\" ? \"manual\" : DEFAULT_LAYOUT_ENGINE;\n});\n\nconst resolvedLayoutRankSep = computed(() => {\n const fallback =\n props.direction === \"vertical\"\n ? DEFAULT_DAGRE_RANK_SEP_VERTICAL\n : DEFAULT_DAGRE_RANK_SEP_HORIZONTAL;\n\n return toPositiveNumber(props.layoutRankSep, fallback, 80);\n});\n\nconst resolvedLayoutNodeSep = computed(() => {\n const fallback =\n props.direction === \"vertical\"\n ? DEFAULT_DAGRE_NODE_SEP_VERTICAL\n : DEFAULT_DAGRE_NODE_SEP_HORIZONTAL;\n\n return toPositiveNumber(props.layoutNodeSep, fallback, 40);\n});\n\nconst resolvedLayoutEdgeSep = computed(() => {\n return toPositiveNumber(props.layoutEdgeSep, DEFAULT_DAGRE_EDGE_SEP, 8);\n});\n\nfunction createFallbackLayoutPositions(\n nodes: OrderedNodeElement[],\n rankGap = DEFAULT_FALLBACK_GAP,\n) {\n const mainGap = Math.max(80, rankGap);\n const positions: Record<string, { x: number; y: number }> = {};\n\n for (const node of nodes) {\n if (props.direction === \"vertical\") {\n positions[node.key] = { x: 0, y: node.index * mainGap };\n continue;\n }\n\n positions[node.key] = { x: node.index * mainGap, y: 0 };\n }\n\n return positions;\n}\n\nfunction normalizePositions(positions: Record<string, { x: number; y: number }>) {\n if (Object.keys(positions).length === 0) {\n return positions;\n }\n\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n\n for (const position of Object.values(positions)) {\n minX = Math.min(minX, position.x);\n minY = Math.min(minY, position.y);\n }\n\n for (const key of Object.keys(positions)) {\n const currentPosition = positions[key];\n if (!currentPosition) continue;\n\n positions[key] = {\n x: currentPosition.x - minX,\n y: currentPosition.y - minY,\n };\n }\n\n return positions;\n}\n\nfunction createManualLayoutPositions(\n orderedNodes: OrderedNodeElement[],\n rankGap: number,\n laneGap: number,\n) {\n if (orderedNodes.length === 0) return {};\n\n const depthByKey: Record<string, number> = {};\n for (const node of orderedNodes) {\n depthByKey[node.key] = Number.NEGATIVE_INFINITY;\n }\n\n const startKey = startNodeKey.value ?? orderedNodes[0]?.key;\n if (!startKey) {\n return createFallbackLayoutPositions(orderedNodes, rankGap);\n }\n\n depthByKey[startKey] = 0;\n\n const queue: string[] = [startKey];\n const maxDepth = Math.max(0, orderedNodes.length - 1);\n let guard = 0;\n const maxIterations = Math.max(24, orderedNodes.length * orderedNodes.length);\n\n while (queue.length > 0 && guard < maxIterations) {\n guard += 1;\n\n const key = queue.shift();\n if (!key) continue;\n\n const baseDepth = depthByKey[key] ?? Number.NEGATIVE_INFINITY;\n if (!Number.isFinite(baseDepth)) continue;\n\n for (const target of outgoingNodeKeys.value[key] ?? []) {\n if (!(target in depthByKey)) continue;\n\n const candidateDepth = Math.min(maxDepth, baseDepth + 1);\n const currentDepth = depthByKey[target] ?? Number.NEGATIVE_INFINITY;\n\n if (candidateDepth > currentDepth) {\n depthByKey[target] = candidateDepth;\n queue.push(target);\n }\n }\n }\n\n let fallbackDepth = 0;\n for (const node of orderedNodes) {\n if (Number.isFinite(depthByKey[node.key])) continue;\n\n depthByKey[node.key] = Math.min(maxDepth, fallbackDepth);\n fallbackDepth += 1;\n }\n\n const layers: Record<number, string[]> = {};\n for (const node of orderedNodes) {\n const depth = depthByKey[node.key] ?? 0;\n if (!layers[depth]) {\n layers[depth] = [];\n }\n\n layers[depth].push(node.key);\n }\n\n const laneByKey: Record<string, number> = {};\n const sortedDepths = Object.keys(layers)\n .map(Number)\n .sort((a, b) => a - b);\n\n for (const depth of sortedDepths) {\n const layerKeys = [...(layers[depth] ?? [])];\n\n layerKeys.sort((a, b) => {\n const aParents = (incomingNodeKeys.value[a] ?? []).filter((parent) => {\n const parentDepth = depthByKey[parent] ?? Number.NEGATIVE_INFINITY;\n return Number.isFinite(parentDepth) && parentDepth < depth;\n });\n const bParents = (incomingNodeKeys.value[b] ?? []).filter((parent) => {\n const parentDepth = depthByKey[parent] ?? Number.NEGATIVE_INFINITY;\n return Number.isFinite(parentDepth) && parentDepth < depth;\n });\n\n const aAnchor =\n aParents.length > 0\n ? aParents.reduce((sum, parent) => sum + (laneByKey[parent] ?? 0), 0) / aParents.length\n : 0;\n const bAnchor =\n bParents.length > 0\n ? bParents.reduce((sum, parent) => sum + (laneByKey[parent] ?? 0), 0) / bParents.length\n : 0;\n\n if (aAnchor === bAnchor) {\n const aIndex = orderedNodeByKey.value[a]?.index ?? 0;\n const bIndex = orderedNodeByKey.value[b]?.index ?? 0;\n return aIndex - bIndex;\n }\n\n return aAnchor - bAnchor;\n });\n\n const count = layerKeys.length;\n layerKeys.forEach((key, index) => {\n laneByKey[key] = (index - (count - 1) / 2) * laneGap;\n });\n }\n\n const positions: Record<string, { x: number; y: number }> = {};\n\n for (const node of orderedNodes) {\n const depth = depthByKey[node.key] ?? 0;\n const lane = laneByKey[node.key] ?? 0;\n\n if (props.direction === \"vertical\") {\n positions[node.key] = {\n x: Math.round(lane),\n y: Math.round(depth * rankGap),\n };\n continue;\n }\n\n positions[node.key] = {\n x: Math.round(depth * rankGap),\n y: Math.round(lane),\n };\n }\n\n return normalizePositions(positions);\n}\n\nconst nodeSizes = computed<Record<string, NodeSize>>(() => {\n const sizes: Record<string, NodeSize> = {};\n\n for (const node of orderedNodeElements.value) {\n sizes[node.key] = estimateNodeSize(node);\n }\n\n return sizes;\n});\n\nconst architectureZoneDefinitions = computed<ResolvedArchitectureZone[]>(() => {\n if (!isArchitectureMode.value) {\n return [];\n }\n\n const rootZones = toArchitectureZones(props.zones ?? rootElement.value?.props.zones);\n const byId = new Map<string, ResolvedArchitectureZone>();\n\n for (const zone of rootZones) {\n byId.set(zone.id, zone);\n }\n\n for (const node of orderedNodeElements.value) {\n const zoneId = toArchitectureZoneId(node.element.props.zone);\n if (!zoneId || byId.has(zoneId)) {\n continue;\n }\n\n byId.set(zoneId, {\n id: zoneId,\n label: humanizeZoneId(zoneId),\n padding: 62,\n });\n }\n\n return Array.from(byId.values());\n});\n\nconst architectureZoneLabelById = computed<Record<string, string>>(() => {\n const map: Record<string, string> = {};\n\n for (const zone of architectureZoneDefinitions.value) {\n map[zone.id] = zone.label;\n }\n\n return map;\n});\n\nconst architectureNodeZoneByKey = computed<Record<string, string>>(() => {\n const map: Record<string, string> = {};\n\n for (const node of orderedNodeElements.value) {\n const zoneId = toArchitectureZoneId(node.element.props.zone);\n if (!zoneId) {\n continue;\n }\n\n map[node.key] = zoneId;\n }\n\n return map;\n});\n\nconst architectureZoneOverlays = computed<ArchitectureZoneOverlay[]>(() => {\n if (!isArchitectureMode.value) {\n return [];\n }\n\n const rawOverlays: Array<{\n id: string;\n label: string;\n description?: string;\n color: string;\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n padding: number;\n nodeCount: number;\n sourceIndex: number;\n }> = [];\n\n architectureZoneDefinitions.value.forEach((zone, index) => {\n const members = orderedNodeElements.value.filter(\n (node) => architectureNodeZoneByKey.value[node.key] === zone.id,\n );\n if (members.length === 0) {\n return;\n }\n\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n\n for (const member of members) {\n const position = layoutPositions.value[member.key];\n if (!position) {\n continue;\n }\n\n const size = nodeSizes.value[member.key] ?? { width: 240, height: 120 };\n\n minX = Math.min(minX, position.x);\n minY = Math.min(minY, position.y);\n maxX = Math.max(maxX, position.x + size.width);\n maxY = Math.max(maxY, position.y + size.height);\n }\n\n if (\n !Number.isFinite(minX) ||\n !Number.isFinite(minY) ||\n !Number.isFinite(maxX) ||\n !Number.isFinite(maxY)\n ) {\n return;\n }\n\n const padding = zone.padding;\n rawOverlays.push({\n id: zone.id,\n label: zone.label,\n description: zone.description,\n color: resolveZoneColor(index, zone.color),\n minX,\n minY,\n maxX,\n maxY,\n padding,\n nodeCount: members.length,\n sourceIndex: index,\n });\n });\n\n const provisionalBounds = rawOverlays.map((overlay) => ({\n id: overlay.id,\n x: overlay.minX - overlay.padding,\n y: overlay.minY - overlay.padding,\n width: overlay.maxX - overlay.minX + overlay.padding * 2,\n height: overlay.maxY - overlay.minY + overlay.padding * 2,\n }));\n\n const nestingDepthById = new Map<string, number>();\n const containsNestedZoneById = new Map<string, boolean>();\n\n for (const current of provisionalBounds) {\n const depth = provisionalBounds.reduce((count, candidate) => {\n if (candidate.id === current.id) {\n return count;\n }\n\n const containsCurrent =\n candidate.x <= current.x + 12 &&\n candidate.y <= current.y + 12 &&\n candidate.x + candidate.width >= current.x + current.width - 12 &&\n candidate.y + candidate.height >= current.y + current.height - 12;\n\n return containsCurrent ? count + 1 : count;\n }, 0);\n\n nestingDepthById.set(current.id, depth);\n containsNestedZoneById.set(\n current.id,\n provisionalBounds.some((candidate) => {\n if (candidate.id === current.id) {\n return false;\n }\n\n return (\n current.x <= candidate.x + 12 &&\n current.y <= candidate.y + 12 &&\n current.x + current.width >= candidate.x + candidate.width - 12 &&\n current.y + current.height >= candidate.y + candidate.height - 12\n );\n }),\n );\n }\n\n const overlappingZoneIds = new Set<string>();\n for (let index = 0; index < provisionalBounds.length; index += 1) {\n const current = provisionalBounds[index];\n if (!current) {\n continue;\n }\n\n for (let compareIndex = index + 1; compareIndex < provisionalBounds.length; compareIndex += 1) {\n const candidate = provisionalBounds[compareIndex];\n if (!candidate) {\n continue;\n }\n\n const overlaps =\n current.x < candidate.x + candidate.width &&\n current.x + current.width > candidate.x &&\n current.y < candidate.y + candidate.height &&\n current.y + current.height > candidate.y;\n\n if (!overlaps) {\n continue;\n }\n\n overlappingZoneIds.add(current.id);\n overlappingZoneIds.add(candidate.id);\n }\n }\n\n const labelLaneById = new Map<string, number>();\n const placedLabelBoxes: Array<{\n id: string;\n lane: number;\n x: number;\n y: number;\n width: number;\n height: number;\n }> = [];\n const sortedForLabelPlacement = rawOverlays\n .map((overlay) => {\n const sidePadding = Math.max(overlay.padding, ARCHITECTURE_ZONE_MIN_CONTENT_PADDING);\n const descriptionReserve = overlay.description\n ? ARCHITECTURE_ZONE_DESCRIPTION_HEIGHT + ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP\n : 0;\n const topPadding =\n sidePadding +\n ARCHITECTURE_ZONE_LABEL_HEIGHT +\n ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP +\n descriptionReserve;\n const width = Math.min(\n Math.max(132, overlay.label.length * 7 + String(overlay.nodeCount).length * 14 + 86),\n Math.max(148, overlay.maxX - overlay.minX + sidePadding * 2 - 28),\n );\n\n return {\n id: overlay.id,\n x: overlay.minX - sidePadding + 16,\n y: overlay.minY - topPadding + ARCHITECTURE_ZONE_LABEL_TOP,\n width,\n };\n })\n .sort((a, b) => {\n if (a.y !== b.y) {\n return a.y - b.y;\n }\n\n return a.x - b.x;\n });\n\n for (const labelCandidate of sortedForLabelPlacement) {\n let lane = 0;\n\n while (\n placedLabelBoxes.some((placed) => {\n if (placed.lane !== lane) {\n return false;\n }\n\n const currentY = labelCandidate.y + lane * ARCHITECTURE_ZONE_NESTED_LABEL_STEP;\n return (\n labelCandidate.x < placed.x + placed.width &&\n labelCandidate.x + labelCandidate.width > placed.x &&\n currentY < placed.y + placed.height &&\n currentY + ARCHITECTURE_ZONE_LABEL_HEIGHT > placed.y\n );\n })\n ) {\n lane += 1;\n }\n\n labelLaneById.set(labelCandidate.id, lane);\n placedLabelBoxes.push({\n id: labelCandidate.id,\n lane,\n x: labelCandidate.x,\n y: labelCandidate.y + lane * ARCHITECTURE_ZONE_NESTED_LABEL_STEP,\n width: labelCandidate.width,\n height: ARCHITECTURE_ZONE_LABEL_HEIGHT,\n });\n }\n\n const maxLabelLane = placedLabelBoxes.reduce((max, placed) => Math.max(max, placed.lane), 0);\n\n return rawOverlays\n .map((overlay) => {\n const nestingDepth = nestingDepthById.get(overlay.id) ?? 0;\n const nestedZoneGap = containsNestedZoneById.get(overlay.id)\n ? ARCHITECTURE_ZONE_CONTAINED_ZONE_GAP\n : 0;\n const baseSidePadding = Math.max(overlay.padding, ARCHITECTURE_ZONE_MIN_CONTENT_PADDING);\n const sidePadding = baseSidePadding + nestedZoneGap;\n const bottomPadding =\n Math.max(baseSidePadding, ARCHITECTURE_ZONE_MIN_BOTTOM_PADDING) + nestedZoneGap;\n const labelLane = labelLaneById.get(overlay.id) ?? 0;\n const labelOffsetY =\n ARCHITECTURE_ZONE_LABEL_TOP + labelLane * ARCHITECTURE_ZONE_NESTED_LABEL_STEP;\n const showDescription = Boolean(overlay.description) && !overlappingZoneIds.has(overlay.id);\n const descriptionOffsetY =\n labelOffsetY + ARCHITECTURE_ZONE_LABEL_HEIGHT + ARCHITECTURE_ZONE_LABEL_TO_DESCRIPTION_GAP;\n const descriptionReserve = showDescription\n ? ARCHITECTURE_ZONE_DESCRIPTION_HEIGHT + ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP\n : 0;\n const topPadding =\n sidePadding +\n ARCHITECTURE_ZONE_LABEL_HEIGHT +\n ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP +\n descriptionReserve +\n maxLabelLane * ARCHITECTURE_ZONE_NESTED_LABEL_STEP;\n\n return {\n id: overlay.id,\n label: overlay.label,\n description: showDescription ? overlay.description : undefined,\n color: overlay.color,\n x: Math.round(overlay.minX - sidePadding),\n y: Math.round(overlay.minY - topPadding),\n width: Math.max(120, Math.round(overlay.maxX - overlay.minX + sidePadding * 2)),\n height: Math.max(100, Math.round(overlay.maxY - overlay.minY + topPadding + bottomPadding)),\n nodeCount: overlay.nodeCount,\n nestingDepth,\n labelLane,\n labelOffsetY,\n descriptionOffsetY,\n sourceIndex: overlay.sourceIndex,\n };\n })\n .sort((a, b) => {\n const areaDiff = b.width * b.height - a.width * a.height;\n if (areaDiff !== 0) {\n return areaDiff;\n }\n\n return a.sourceIndex - b.sourceIndex;\n })\n .map(({ sourceIndex: _sourceIndex, ...overlay }) => overlay);\n});\n\nfunction architectureZoneCardStyle(zone: ArchitectureZoneOverlay) {\n return {\n left: `${zone.x}px`,\n top: `${zone.y}px`,\n width: `${zone.width}px`,\n height: `${zone.height}px`,\n borderColor: withAlpha(zone.color, 0.38),\n background: `linear-gradient(180deg, ${withAlpha(zone.color, 0.1)} 0%, ${withAlpha(zone.color, 0.045)} 62%, ${withAlpha(zone.color, 0.03)} 100%)`,\n boxShadow: `inset 0 0 0 1px ${withAlpha(zone.color, 0.1)}`,\n };\n}\n\nfunction architectureZoneLabelStyle(zone: ArchitectureZoneOverlay) {\n return {\n top: `${zone.labelOffsetY}px`,\n borderColor: withAlpha(zone.color, 0.55),\n background: withAlpha(zone.color, 0.18),\n color: zone.color,\n };\n}\n\nfunction architectureZoneDescriptionStyle(zone: ArchitectureZoneOverlay) {\n return {\n top: `${zone.descriptionOffsetY}px`,\n };\n}\n\nconst layoutPositions = computed<Record<string, { x: number; y: number }>>(() => {\n const orderedNodes = orderedNodeElements.value;\n if (orderedNodes.length === 0) return {};\n\n const rankGap = resolvedLayoutRankSep.value;\n const nodeGap = resolvedLayoutNodeSep.value;\n const edgeGap = resolvedLayoutEdgeSep.value;\n const fallback = createFallbackLayoutPositions(orderedNodes, rankGap);\n\n if (resolvedLayoutEngine.value === \"manual\") {\n return createManualLayoutPositions(orderedNodes, rankGap, nodeGap);\n }\n\n const graph = new dagre.graphlib.Graph();\n graph.setDefaultEdgeLabel(() => ({}));\n graph.setGraph({\n rankdir: props.direction === \"vertical\" ? \"TB\" : \"LR\",\n ranker: \"network-simplex\",\n acyclicer: \"greedy\",\n align: \"UL\",\n marginx: 36,\n marginy: 36,\n ranksep: rankGap,\n nodesep: nodeGap,\n edgesep: edgeGap,\n });\n\n for (const node of orderedNodes) {\n const size = nodeSizes.value[node.key] ?? { width: 240, height: 120 };\n\n graph.setNode(node.key, {\n width: size.width,\n height: size.height,\n });\n }\n\n for (const node of orderedNodes) {\n const targets = outgoingNodeKeys.value[node.key] ?? [];\n const preferredTarget = resolveNextNode(node.key, targets);\n\n for (const target of targets) {\n if (!orderedNodeByKey.value[target]) continue;\n\n graph.setEdge(node.key, target, {\n minlen: 1,\n weight: target === preferredTarget ? 3 : 1,\n });\n }\n }\n\n try {\n dagre.layout(graph);\n } catch {\n return fallback;\n }\n\n const positions: Record<string, { x: number; y: number }> = {};\n\n for (const node of orderedNodes) {\n const layoutNode = graph.node(node.key);\n if (!layoutNode || typeof layoutNode.x !== \"number\" || typeof layoutNode.y !== \"number\") {\n continue;\n }\n\n const size = nodeSizes.value[node.key] ?? { width: 240, height: 120 };\n\n positions[node.key] = {\n x: Math.round(layoutNode.x - size.width / 2),\n y: Math.round(layoutNode.y - size.height / 2),\n };\n }\n\n if (Object.keys(positions).length === 0) {\n return fallback;\n }\n\n return normalizePositions(positions);\n});\n\nconst nodes = computed<FlowNode[]>(() => {\n const fallbackPositions = createFallbackLayoutPositions(\n orderedNodeElements.value,\n resolvedLayoutRankSep.value,\n );\n\n return orderedNodeElements.value.map(({ key, nodeType, element, index }) => ({\n id: key,\n type: nodeType,\n targetPosition: Position.Left,\n sourcePosition: Position.Right,\n position:\n layoutPositions.value[key] ??\n fallbackPositions[key] ??\n (props.direction === \"vertical\"\n ? { x: 0, y: index * DEFAULT_FALLBACK_GAP }\n : { x: index * DEFAULT_FALLBACK_GAP, y: 0 }),\n data: {\n key,\n type: nodeType,\n elementType: element.type,\n props: element.props,\n active: isActive(key),\n sourceAnchor: resolveNodeSourceAnchor(element.props),\n index,\n },\n }));\n});\n\nconst edges = computed<FlowEdge[]>(() => {\n const result: FlowEdge[] = [];\n\n for (const node of orderedNodeElements.value) {\n const targets = outgoingNodeKeys.value[node.key] ?? [];\n\n for (const target of targets) {\n if (!orderedNodeByKey.value[target]) continue;\n\n const isActiveEdge =\n !isArchitectureMode.value &&\n activeFrame.value?.nodeKey === node.key &&\n nextPlannedNodeKey.value === target;\n const transition = transitionMetaBySource.value[node.key]?.[target];\n const edgeClasses = [\n isActiveEdge ? \"active-edge\" : null,\n transition?.kind ? `edge-kind-${transition.kind}` : null,\n ].filter((value): value is string => Boolean(value));\n\n const edgeLabel = resolveTransitionEdgeLabel(transition);\n const hasLabel = Boolean(edgeLabel);\n\n result.push({\n id: `e-${node.key}-${target}`,\n source: node.key,\n target,\n type: isArchitectureMode.value ? \"architecture\" : \"smoothstep\",\n animated: !isArchitectureMode.value,\n class: edgeClasses.length > 0 ? edgeClasses.join(\" \") : undefined,\n label: edgeLabel,\n labelShowBg: hasLabel && !isArchitectureMode.value,\n labelBgPadding: hasLabel && !isArchitectureMode.value ? [6, 3] : undefined,\n labelBgBorderRadius: hasLabel && !isArchitectureMode.value ? 6 : undefined,\n labelBgStyle:\n hasLabel && !isArchitectureMode.value\n ? { fill: \"var(--color-card)\", fillOpacity: 0.985, stroke: \"var(--color-border)\" }\n : undefined,\n labelStyle:\n hasLabel && !isArchitectureMode.value\n ? {\n fill: \"var(--color-foreground)\",\n fontSize: \"10px\",\n fontWeight: 600,\n }\n : undefined,\n });\n }\n }\n\n return result;\n});\n\nconst diagramBounds = computed(() => {\n if (nodes.value.length === 0) {\n return null;\n }\n\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n\n for (const node of nodes.value) {\n const size = nodeSizes.value[node.id] ?? { width: 240, height: 120 };\n minX = Math.min(minX, node.position.x);\n minY = Math.min(minY, node.position.y);\n maxX = Math.max(maxX, node.position.x + size.width);\n maxY = Math.max(maxY, node.position.y + size.height);\n }\n\n for (const zone of architectureZoneOverlays.value) {\n minX = Math.min(minX, zone.x);\n minY = Math.min(minY, zone.y);\n maxX = Math.max(maxX, zone.x + zone.width);\n maxY = Math.max(maxY, zone.y + zone.height);\n }\n\n if (\n !Number.isFinite(minX) ||\n !Number.isFinite(minY) ||\n !Number.isFinite(maxX) ||\n !Number.isFinite(maxY)\n ) {\n return null;\n }\n\n return {\n x: Math.floor(minX),\n y: Math.floor(minY),\n width: Math.max(1, Math.ceil(maxX - minX)),\n height: Math.max(1, Math.ceil(maxY - minY)),\n };\n});\n\nfunction createExportFileBaseName() {\n const rawName = activeFlow.value?.id ?? overlayTitle.value ?? props.title ?? \"flow-diagram\";\n\n const slug = rawName\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n return slug || \"flow-diagram\";\n}\n\nasync function exportDiagram(format: DiagramExportFormat) {\n if (exportInFlight.value) return;\n if (!canExportDiagram.value) return;\n\n const flowElement = sceneRef.value;\n const bounds = diagramBounds.value;\n\n if (!flowElement || !bounds) {\n exportError.value = \"Diagram is still initializing. Try again in a moment.\";\n return;\n }\n\n exportError.value = null;\n exportMenuOpen.value = false;\n exportInFlight.value = format;\n\n try {\n await exportFlowDiagram({\n flowElement,\n theme: uiTheme.value,\n bounds,\n fileNameBase: createExportFileBaseName(),\n format,\n });\n } catch (error) {\n exportError.value =\n error instanceof Error ? error.message : `Failed to export ${format.toUpperCase()} diagram.`;\n } finally {\n exportInFlight.value = null;\n }\n}\n\nfunction isActive(nodeKey: string) {\n if (isArchitectureMode.value) {\n return true;\n }\n\n return activeFrame.value?.nodeKey === nodeKey;\n}\n\nfunction codeStepIndex(nodeKey: string) {\n if (activeFrame.value?.nodeKey !== nodeKey) {\n return 0;\n }\n\n return activeFrame.value.localStep;\n}\n\nconst activeNode = computed(() => {\n const key = activeFrame.value?.nodeKey;\n if (!key) return undefined;\n return orderedNodeByKey.value[key];\n});\n\nconst activeLocalStep = computed(() => activeFrame.value?.localStep ?? 0);\n\nconst activeLabel = computed(() => {\n const node = activeNode.value;\n if (!node) return \"\";\n\n const base = toOptionalString(node.element.props.label) ?? \"\";\n\n if (node.element.type !== \"CodeNode\") {\n return base;\n }\n\n const steps = toMagicMoveSteps(node.element.props.magicMoveSteps);\n if (steps.length === 0) return base;\n\n const title = steps[Math.min(activeLocalStep.value, steps.length - 1)]?.title;\n return title ? `${base} - ${title}` : base;\n});\n\nconst activeDescription = computed(() => {\n const node = activeNode.value;\n if (!node) return \"\";\n\n if (node.element.type === \"CodeNode\") {\n const steps = toMagicMoveSteps(node.element.props.magicMoveSteps);\n const defaultStory =\n toOptionalString(node.element.props.story) ?? toOptionalString(node.element.props.comment);\n\n if (steps.length > 0) {\n const beat = steps[Math.min(activeLocalStep.value, steps.length - 1)];\n\n return beat?.story ?? beat?.comment ?? defaultStory ?? \"\";\n }\n\n return defaultStory ?? \"\";\n }\n\n return getNodeSummary(node);\n});\n\nconst activeSourceAnchor = computed(() => {\n const node = activeNode.value;\n if (!node) return undefined;\n\n return resolveNodeSourceAnchor(node.element.props);\n});\n\nconst architectureSelectedNodeKey = ref<string | null>(null);\n\nconst architectureSelectedNode = computed(() => {\n if (!isArchitectureMode.value) {\n return undefined;\n }\n\n const selected = architectureSelectedNodeKey.value;\n if (selected && orderedNodeByKey.value[selected]) {\n return orderedNodeByKey.value[selected];\n }\n\n return orderedNodeElements.value[0];\n});\n\nwatch(\n [isArchitectureMode, orderedNodeElements],\n ([architectureMode, ordered]) => {\n if (!architectureMode) {\n architectureSelectedNodeKey.value = null;\n return;\n }\n\n const selected = architectureSelectedNodeKey.value;\n if (selected && ordered.some((node) => node.key === selected)) {\n return;\n }\n\n architectureSelectedNodeKey.value = ordered[0]?.key ?? null;\n },\n { immediate: true },\n);\n\nconst architectureInspector = computed<ArchitectureInspectorView | null>(() => {\n const node = architectureSelectedNode.value;\n if (!node) {\n return null;\n }\n\n const label = toTrimmedNonEmptyString(node.element.props.label) ?? node.key;\n const sourceAnchor = resolveNodeSourceAnchor(node.element.props);\n\n if (node.element.type !== \"ArchitectureNode\") {\n return {\n type: \"Other\",\n label,\n summary: getNodeSummary(node),\n sourceAnchor,\n elementType: node.element.type,\n };\n }\n\n const zoneId = toArchitectureZoneId(node.element.props.zone);\n const zoneLabel = zoneId\n ? (architectureZoneLabelById.value[zoneId] ?? humanizeZoneId(zoneId))\n : undefined;\n const interfaces = toArchitectureInterfaces(node.element.props.interfaces);\n const dataAssets = toArchitectureDataAssets(node.element.props.data);\n const security = toArchitectureSecurity(node.element.props.security);\n const operations = toArchitectureOperations(node.element.props.operations);\n const links = toArchitectureLinks(node.element.props.links);\n const outgoing: ArchitectureOutgoingEdge[] = [];\n\n for (const targetKey of outgoingNodeKeys.value[node.key] ?? []) {\n const targetNode = orderedNodeByKey.value[targetKey];\n if (!targetNode) {\n continue;\n }\n\n const transition = transitionMetaBySource.value[node.key]?.[targetKey];\n\n outgoing.push({\n target: toTrimmedNonEmptyString(targetNode.element.props.label) ?? targetKey,\n label: transition?.label,\n protocol: transition?.protocol,\n transport: transition?.transport,\n auth: transition?.auth,\n criticality: transition?.criticality,\n });\n }\n\n return {\n type: \"ArchitectureNode\",\n label,\n kind: toArchitectureKind(node.element.props.kind),\n status: toArchitectureStatus(node.element.props.status),\n tier: toArchitectureTier(node.element.props.tier),\n technology: toTrimmedNonEmptyString(node.element.props.technology),\n runtime: toTrimmedNonEmptyString(node.element.props.runtime),\n owner: toTrimmedNonEmptyString(node.element.props.owner),\n zoneLabel,\n summary: toTrimmedNonEmptyString(node.element.props.description) ?? \"\",\n tags: toStringArray(node.element.props.tags),\n responsibilities: toStringArray(node.element.props.responsibilities),\n capabilities: toStringArray(node.element.props.capabilities),\n interfaces,\n dataAssets,\n security,\n operations,\n links,\n outgoing,\n sourceAnchor,\n };\n});\n\nconst architectureInspectorNode = computed<ArchitectureInspectorArchitectureView | null>(() => {\n const inspector = architectureInspector.value;\n if (!inspector || inspector.type !== \"ArchitectureNode\") {\n return null;\n }\n\n return inspector;\n});\n\nconst architectureInspectorNodeSafe = computed(() => {\n return architectureInspectorNode.value ?? EMPTY_ARCHITECTURE_INSPECTOR_NODE;\n});\n\nconst architectureInspectorPanelStyle = computed(() => {\n return {\n transform: architectureInspectorOpen.value ? \"translateX(0)\" : \"translateX(100%)\",\n };\n});\n\nconst branchChoices = computed<BranchChoice[]>(() => {\n if (isArchitectureMode.value) {\n return [];\n }\n\n const node = activeNode.value;\n const frame = activeFrame.value;\n if (!node || !frame) return [];\n\n if (frame.localStep < frame.totalLocalSteps - 1) {\n return [];\n }\n\n const options = outgoingNodeKeys.value[node.key] ?? [];\n if (options.length <= 1) return [];\n\n const result: BranchChoice[] = [];\n\n for (const id of options) {\n const target = orderedNodeByKey.value[id];\n if (!target) continue;\n\n const transition = transitionMetaBySource.value[node.key]?.[id];\n\n const targetLabel = toOptionalString(target.element.props.label) ?? id;\n const targetDescription = getNodeSummary(target);\n\n result.push({\n id,\n label: transition?.label ?? targetLabel,\n description: transition?.description ?? targetDescription,\n kind: transition?.kind,\n });\n }\n\n return result;\n});\n\nconst selectedBranchChoiceId = computed(() => {\n const node = activeNode.value;\n if (!node || branchChoices.value.length === 0) return undefined;\n\n const selected = selectedBranchByNode.value[node.key];\n if (selected) return selected;\n\n return nextPlannedNodeKey.value;\n});\n\nfunction chooseChoice(choiceId: string) {\n const node = activeNode.value;\n if (!node) return;\n\n const options = outgoingNodeKeys.value[node.key] ?? [];\n if (!options.includes(choiceId)) return;\n\n selectedBranchByNode.value = {\n ...selectedBranchByNode.value,\n [node.key]: choiceId,\n };\n\n const prefix = pathFrames.value.slice(0, currentStep.value + 1);\n const suffix = buildGuidedPath(choiceId);\n\n pathFrames.value = [...prefix, ...suffix];\n\n if (pathFrames.value.length > currentStep.value + 1) {\n currentStep.value += 1;\n }\n}\n\nconst containerMinHeight = computed(() => {\n const provided = Number(props.minHeight);\n if (Number.isFinite(provided) && provided >= 320) {\n return Math.floor(provided);\n }\n\n if (isArchitectureMode.value) {\n return 620;\n }\n\n const node = activeNode.value ?? orderedNodeElements.value[0];\n if (!node || node.element.type !== \"CodeNode\") {\n return 520;\n }\n\n const maxLineLength = getCodeNodeMaxLineLength(node.element);\n const nodeWidth = estimateCodeNodeWidth(maxLineLength);\n const codeCharsPerLine = estimateCodeNodeCharsPerLine(nodeWidth);\n const autoWrapEnabled = maxLineLength > CODE_NODE_MAX_INLINE_CHARS;\n const wrapEnabled = toBoolean(node.element.props.wrapLongLines) || autoWrapEnabled;\n\n const codeLines = wrapEnabled\n ? getCodeNodeWrappedLines(node.element, codeCharsPerLine)\n : getCodeNodeMaxLines(node.element);\n const storyLines = getCodeNodeStoryLines(node.element);\n const storyHasMeta = hasCodeNodeStoryMeta(node.element);\n\n const codeViewportHeight = wrapEnabled\n ? Math.min(400, Math.max(190, 72 + codeLines * 16))\n : Math.min(340, Math.max(160, 84 + codeLines * 17));\n\n const storyViewportHeight =\n storyLines > 0 ? Math.min(220, Math.max(88, (storyHasMeta ? 56 : 34) + storyLines * 18)) : 0;\n\n return Math.min(880, Math.max(560, codeViewportHeight + storyViewportHeight + 300));\n});\n\nconst instance = getCurrentInstance();\nconst flowId = `flaier-${instance?.uid ?? 0}`;\nconst { fitView, onNodeClick, onViewportChange, setCenter, viewport } = useVueFlow(flowId);\nconst nodesInitialized = useNodesInitialized();\nconst paneReady = ref(false);\nconst overviewMode = ref(false);\nlet resizeObserver: ResizeObserver | null = null;\n\nconst architectureZoneLayerStyle = computed(() => {\n const x = Number.isFinite(viewport.value.x) ? viewport.value.x : 0;\n const y = Number.isFinite(viewport.value.y) ? viewport.value.y : 0;\n const zoom = Number.isFinite(viewport.value.zoom) ? viewport.value.zoom : 1;\n\n return {\n transform: `translate(${x}px, ${y}px) scale(${zoom})`,\n transformOrigin: \"0 0\",\n };\n});\n\nfunction handleDocumentPointerDown(event: PointerEvent) {\n const target = event.target as Node | null;\n if (!target) return;\n\n if (headerDropdownOpen.value && !headerDropdownRef.value?.contains(target)) {\n closeHeaderDropdown();\n }\n\n if (exportMenuOpen.value && !exportMenuRef.value?.contains(target)) {\n closeExportMenu();\n }\n}\n\nfunction isEditableTarget(target: EventTarget | null) {\n if (!(target instanceof HTMLElement)) {\n return false;\n }\n\n if (target.isContentEditable) {\n return true;\n }\n\n const tagName = target.tagName;\n if (tagName === \"INPUT\" || tagName === \"TEXTAREA\" || tagName === \"SELECT\") {\n return true;\n }\n\n return Boolean(target.closest('[contenteditable=\"true\"]'));\n}\n\nfunction handleDocumentKeydown(event: KeyboardEvent) {\n if (event.key === \"Escape\") {\n closeHeaderDropdown();\n closeExportMenu();\n\n if (isArchitectureMode.value) {\n architectureInspectorOpen.value = false;\n }\n\n return;\n }\n\n if (event.defaultPrevented) return;\n if (event.metaKey || event.ctrlKey || event.altKey) return;\n if (isEditableTarget(event.target)) return;\n if (isArchitectureMode.value) return;\n\n if (event.key === \"ArrowRight\" || event.key === \"ArrowDown\") {\n event.preventDefault();\n next();\n return;\n }\n\n if (event.key === \"ArrowLeft\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n prev();\n return;\n }\n\n if (/^[1-9]$/.test(event.key)) {\n const index = Number(event.key) - 1;\n const choice = branchChoices.value[index];\n if (!choice) return;\n\n event.preventDefault();\n chooseChoice(choice.id);\n }\n}\n\nfunction syncOverviewModeFromZoom(zoom: number) {\n if (overviewMode.value) {\n if (zoom >= OVERVIEW_EXIT_ZOOM) {\n overviewMode.value = false;\n }\n\n return;\n }\n\n if (zoom <= OVERVIEW_ENTER_ZOOM) {\n overviewMode.value = true;\n }\n}\n\nwatch(\n () => viewport.value.zoom,\n (zoom) => {\n if (!Number.isFinite(zoom)) return;\n\n syncOverviewModeFromZoom(zoom);\n },\n { immediate: true },\n);\n\nonViewportChange((transform) => {\n if (!Number.isFinite(transform.zoom)) return;\n\n syncOverviewModeFromZoom(transform.zoom);\n});\n\nonNodeClick(({ node }) => {\n if (isArchitectureMode.value) {\n architectureSelectedNodeKey.value = node.id;\n architectureInspectorOpen.value = true;\n return;\n }\n\n jumpToNode(node.id);\n});\n\nfunction updateContainerReady() {\n const element = containerRef.value;\n containerWidth.value = element?.clientWidth ?? 0;\n containerHeight.value = element?.clientHeight ?? 0;\n containerReady.value = containerWidth.value > 0 && containerHeight.value > 0;\n}\n\nconst sceneStyle = computed<Record<string, string>>(() => ({\n height: `${Math.max(containerHeight.value, containerMinHeight.value)}px`,\n}));\n\nonMounted(() => {\n if (typeof document !== \"undefined\") {\n document.addEventListener(\"pointerdown\", handleDocumentPointerDown);\n document.addEventListener(\"keydown\", handleDocumentKeydown);\n }\n\n nextTick(() => {\n updateContainerReady();\n\n if (typeof ResizeObserver === \"undefined\") return;\n\n resizeObserver = new ResizeObserver(() => {\n updateContainerReady();\n });\n\n if (containerRef.value) {\n resizeObserver.observe(containerRef.value);\n }\n });\n});\n\nfunction onInit() {\n paneReady.value = true;\n}\n\nconst viewportReady = computed(\n () => paneReady.value && nodesInitialized.value && containerReady.value && nodes.value.length > 0,\n);\n\nconst canExportDiagram = computed(() => {\n return Boolean(viewportReady.value && diagramBounds.value);\n});\n\nwatch(canExportDiagram, (canExport) => {\n if (!canExport) {\n closeExportMenu();\n }\n});\n\nconst narrativeFocusTarget = computed(() => {\n if (isArchitectureMode.value || overviewMode.value || !viewportReady.value) {\n return null;\n }\n\n const nodeKey = activeFrame.value?.nodeKey;\n if (!nodeKey) {\n return null;\n }\n\n const node = nodes.value.find((candidate) => candidate.id === nodeKey);\n if (!node) {\n return null;\n }\n\n const size = nodeSizes.value[node.id] ?? { width: 240, height: 120 };\n\n return {\n signature: [\n node.id,\n Math.round(node.position.x),\n Math.round(node.position.y),\n Math.round(size.width),\n Math.round(size.height),\n Math.round(containerWidth.value),\n Math.round(containerHeight.value),\n ].join(\":\"),\n x: node.position.x + size.width / 2,\n y: node.position.y + size.height / 2,\n };\n});\n\nconst narrativeFitSignature = ref(\"\");\n\nwatch(\n [viewportReady, isArchitectureMode, nodes, containerWidth, containerHeight],\n ([ready, architectureMode, currentNodes, width, height]) => {\n if (!ready || architectureMode || currentNodes.length === 0) return;\n\n const signature = [\n `${Math.round(width)}x${Math.round(height)}`,\n ...currentNodes.map(\n (node) => `${node.id}:${Math.round(node.position.x)}:${Math.round(node.position.y)}`,\n ),\n ].join(\"|\");\n\n if (signature === narrativeFitSignature.value) {\n return;\n }\n\n narrativeFitSignature.value = signature;\n\n nextTick(() => {\n void fitView({\n duration: 280,\n padding: 0.3,\n maxZoom: 0.95,\n });\n });\n },\n { immediate: true },\n);\n\nwatch(\n () => narrativeFocusTarget.value?.signature ?? \"\",\n () => {\n const target = narrativeFocusTarget.value;\n if (!target) return;\n\n const zoom = Number.isFinite(viewport.value.zoom) ? viewport.value.zoom : 1;\n\n nextTick(() => {\n void setCenter(target.x, target.y, { duration: 280, zoom });\n });\n },\n { immediate: true },\n);\n\nconst architectureFitSignature = ref(\"\");\n\nwatch(\n [viewportReady, isArchitectureMode, nodes, containerWidth, containerHeight],\n ([ready, architectureMode, currentNodes, width, height]) => {\n if (!ready || !architectureMode || currentNodes.length === 0) return;\n\n const signature = [\n `${Math.round(width)}x${Math.round(height)}`,\n ...currentNodes.map(\n (node) => `${node.id}:${Math.round(node.position.x)}:${Math.round(node.position.y)}`,\n ),\n ].join(\"|\");\n\n if (signature === architectureFitSignature.value) {\n return;\n }\n\n architectureFitSignature.value = signature;\n\n nextTick(() => {\n void fitView({\n duration: 260,\n padding: 0.18,\n maxZoom: 1.15,\n });\n });\n },\n { immediate: true },\n);\n\nwatch(isArchitectureMode, (architectureMode) => {\n if (architectureMode) {\n playing.value = false;\n narrativeFitSignature.value = \"\";\n architectureInspectorOpen.value = defaultArchitectureInspectorOpen.value;\n return;\n }\n\n narrativeFitSignature.value = \"\";\n architectureFitSignature.value = \"\";\n architectureInspectorOpen.value = defaultArchitectureInspectorOpen.value;\n});\n\nonUnmounted(() => {\n clearTimer();\n\n if (typeof document !== \"undefined\") {\n document.removeEventListener(\"pointerdown\", handleDocumentPointerDown);\n document.removeEventListener(\"keydown\", handleDocumentKeydown);\n }\n\n if (resizeObserver) {\n resizeObserver.disconnect();\n resizeObserver = null;\n }\n\n stopDocumentThemeSync();\n});\n</script>\n\n<template>\n <div\n ref=\"containerRef\"\n class=\"flaier relative h-full w-full font-sans antialiased bg-background transition-[min-height] duration-300 ease-out\"\n :style=\"{ minHeight: `${containerMinHeight}px` }\"\n :data-mode=\"isArchitectureMode ? 'architecture' : 'narrative'\"\n :data-focus-mode=\"overviewMode ? 'overview' : 'focus'\"\n :data-theme=\"uiTheme\"\n >\n <div ref=\"sceneRef\" class=\"relative w-full overflow-hidden\" :style=\"sceneStyle\">\n <div\n v-if=\"containerReady && isArchitectureMode && architectureZoneOverlays.length > 0\"\n class=\"pointer-events-none absolute inset-0 z-0\"\n >\n <div class=\"absolute inset-0\" data-zone-overlay=\"true\" :style=\"architectureZoneLayerStyle\">\n <div\n v-for=\"zone in architectureZoneOverlays\"\n :key=\"zone.id\"\n class=\"absolute rounded-2xl border border-dashed\"\n :style=\"architectureZoneCardStyle(zone)\"\n >\n <div\n class=\"absolute left-4 inline-flex items-center gap-2 rounded-full border px-2 py-1 text-[10px] font-semibold uppercase tracking-wider\"\n :style=\"architectureZoneLabelStyle(zone)\"\n >\n <span>{{ zone.label }}</span>\n <span class=\"opacity-80\"\n >{{ zone.nodeCount }} node{{ zone.nodeCount === 1 ? \"\" : \"s\" }}</span\n >\n </div>\n\n <p\n v-if=\"zone.description\"\n class=\"absolute left-4 right-4 text-[10px] leading-snug text-muted-foreground\"\n :style=\"architectureZoneDescriptionStyle(zone)\"\n >\n {{ zone.description }}\n </p>\n </div>\n </div>\n </div>\n\n <VueFlow\n v-if=\"containerReady\"\n :id=\"flowId\"\n :nodes=\"nodes\"\n :edges=\"edges\"\n :node-types=\"customNodeTypes\"\n :fit-view-on-init=\"false\"\n :elements-selectable=\"false\"\n :nodes-focusable=\"false\"\n :nodes-draggable=\"false\"\n :nodes-connectable=\"false\"\n :zoom-on-scroll=\"true\"\n :zoom-on-pinch=\"true\"\n :pan-on-drag=\"true\"\n :pan-on-scroll=\"true\"\n :min-zoom=\"0.15\"\n :max-zoom=\"2\"\n :prevent-scrolling=\"true\"\n class=\"relative z-[10] h-full w-full\"\n @init=\"onInit\"\n >\n <template #node-architecture=\"{ data }\">\n <ArchitectureNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :kind=\"toArchitectureKind(data.props.kind)\"\n :technology=\"toOptionalString(data.props.technology)\"\n :runtime=\"toOptionalString(data.props.runtime)\"\n :owner=\"toOptionalString(data.props.owner)\"\n :tier=\"toArchitectureTier(data.props.tier)\"\n :status=\"toArchitectureStatus(data.props.status)\"\n :tags=\"toStringArray(data.props.tags)\"\n :capabilities=\"toStringArray(data.props.capabilities)\"\n :description=\"toOptionalString(data.props.description)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #edge-architecture=\"edgeProps\">\n <ArchitectureSmoothEdge v-bind=\"edgeProps\" />\n </template>\n\n <template #node-trigger=\"{ data }\">\n <TriggerNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :description=\"toOptionalString(data.props.description)\"\n :color=\"toOptionalString(data.props.color)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-code=\"{ data }\">\n <CodeNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :file=\"toOptionalString(data.props.file)\"\n :language=\"toOptionalString(data.props.language)\"\n :code=\"toRequiredString(data.props.code)\"\n :comment=\"toOptionalString(data.props.comment)\"\n :story=\"toOptionalString(data.props.story)\"\n :wrap-long-lines=\"toBoolean(data.props.wrapLongLines)\"\n :magic-move-steps=\"toMagicMoveSteps(data.props.magicMoveSteps)\"\n :twoslash=\"toOptionalBoolean(data.props.twoslash)\"\n :twoslash-html=\"toTwoslashHtml(data.props.twoslashHtml)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :ui-theme=\"uiTheme\"\n :active=\"isActive(data.key)\"\n :step-index=\"codeStepIndex(data.key)\"\n />\n </template>\n\n <template #node-decision=\"{ data }\">\n <DecisionNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :condition=\"toOptionalString(data.props.condition)\"\n :description=\"toOptionalString(data.props.description)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-payload=\"{ data }\">\n <PayloadNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :payload=\"toOptionalString(data.props.payload)\"\n :before=\"toOptionalString(data.props.before)\"\n :after=\"toOptionalString(data.props.after)\"\n :format=\"toPayloadFormat(data.props.format)\"\n :description=\"toOptionalString(data.props.description)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-error=\"{ data }\">\n <ErrorNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :message=\"toRequiredString(data.props.message)\"\n :code=\"toOptionalString(data.props.code)\"\n :cause=\"toOptionalString(data.props.cause)\"\n :mitigation=\"toOptionalString(data.props.mitigation)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-description=\"{ data }\">\n <DescriptionNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :body=\"toRequiredString(data.props.body)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-link=\"{ data }\">\n <LinkNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :href=\"toRequiredString(data.props.href)\"\n :description=\"toOptionalString(data.props.description)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n </VueFlow>\n\n <div v-else class=\"h-full w-full\" />\n </div>\n\n <div\n v-if=\"showHeaderOverlay && (showFlowSelector || overlayTitle || overlayDescription)\"\n ref=\"headerDropdownRef\"\n class=\"absolute top-4 left-4 z-20 w-[min(90vw,430px)]\"\n >\n <div class=\"relative\">\n <button\n type=\"button\"\n class=\"group w-full rounded-lg border border-border/70 bg-card/85 px-3 py-2 text-left text-xs shadow-lg backdrop-blur-md transition-colors\"\n :class=\"showFlowSelector ? 'cursor-pointer hover:border-primary/45' : 'cursor-default'\"\n :disabled=\"!showFlowSelector\"\n :aria-expanded=\"showFlowSelector ? headerDropdownOpen : undefined\"\n aria-haspopup=\"listbox\"\n @click=\"toggleHeaderDropdown\"\n >\n <div class=\"flex items-start justify-between gap-3\">\n <div class=\"min-w-0\">\n <p class=\"text-[10px] font-medium uppercase tracking-wider text-muted-foreground\">\n {{ headerModeLabel }}\n </p>\n <p v-if=\"overlayTitle\" class=\"mt-1 truncate text-sm font-medium text-foreground\">\n {{ overlayTitle }}\n </p>\n <p\n v-if=\"overlayDescription\"\n class=\"mt-0.5 text-[11px] leading-relaxed text-muted-foreground break-words\"\n >\n {{ overlayDescription }}\n </p>\n </div>\n\n <svg\n v-if=\"showFlowSelector\"\n class=\"mt-0.5 h-4 w-4 shrink-0 transition-all\"\n :class=\"\n headerDropdownOpen\n ? 'rotate-180 text-foreground'\n : 'text-muted-foreground group-hover:text-foreground'\n \"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </div>\n </button>\n\n <div\n v-if=\"showFlowSelector && headerDropdownOpen\"\n class=\"absolute inset-x-0 top-[calc(100%+8px)] rounded-lg border border-border/70 bg-card/95 p-1 shadow-2xl backdrop-blur-md\"\n role=\"listbox\"\n >\n <button\n v-for=\"flow in availableFlows\"\n :key=\"flow.id\"\n type=\"button\"\n class=\"w-full rounded-md px-2.5 py-2 text-left transition-colors\"\n :class=\"\n flow.id === activeFlowId\n ? 'bg-primary/14 text-foreground'\n : 'text-foreground/90 hover:bg-muted/70'\n \"\n @click=\"handleFlowSelect(flow.id)\"\n >\n <div class=\"flex items-center justify-between gap-2\">\n <p class=\"truncate text-xs font-medium\">{{ flow.title }}</p>\n <span\n v-if=\"flow.id === activeFlowId\"\n class=\"rounded-full border border-primary/35 bg-primary/10 px-1.5 py-0.5 text-[10px] uppercase tracking-wide text-primary\"\n >\n Active\n </span>\n </div>\n <p\n v-if=\"flow.description\"\n class=\"mt-0.5 text-[11px] leading-relaxed text-muted-foreground break-words\"\n >\n {{ flow.description }}\n </p>\n </button>\n </div>\n </div>\n </div>\n\n <div\n v-if=\"showTopRightControls\"\n class=\"fn-architecture-controls absolute top-4 right-4 z-20 flex flex-col items-end gap-2\"\n >\n <div ref=\"exportMenuRef\" class=\"relative\">\n <button\n v-if=\"showExportControls\"\n type=\"button\"\n class=\"group inline-flex h-9 items-center gap-2 rounded-full border border-border/70 bg-card/85 px-3 text-[11px] text-muted-foreground shadow-lg backdrop-blur-md transition-colors hover:text-foreground disabled:cursor-default disabled:opacity-55\"\n :aria-label=\"exportButtonLabel\"\n :title=\"exportButtonLabel\"\n :disabled=\"!canExportDiagram || Boolean(exportInFlight)\"\n @click=\"toggleExportMenu\"\n >\n <svg\n class=\"h-3.5 w-3.5\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 3v12\" />\n <path d=\"m7 10 5 5 5-5\" />\n <path d=\"M4 20h16\" />\n </svg>\n <span>Export</span>\n </button>\n\n <div\n v-if=\"showExportControls && exportMenuOpen\"\n class=\"absolute right-0 top-[calc(100%+8px)] w-44 rounded-lg border border-border/70 bg-card/95 p-1 shadow-2xl backdrop-blur-md\"\n >\n <button\n type=\"button\"\n class=\"w-full rounded-md px-2.5 py-2 text-left text-xs text-foreground transition-colors hover:bg-muted/70\"\n :disabled=\"Boolean(exportInFlight)\"\n @click=\"exportDiagram('png')\"\n >\n Export PNG\n </button>\n <button\n type=\"button\"\n class=\"w-full rounded-md px-2.5 py-2 text-left text-xs text-foreground transition-colors hover:bg-muted/70\"\n :disabled=\"Boolean(exportInFlight)\"\n @click=\"exportDiagram('pdf')\"\n >\n Export PDF\n </button>\n </div>\n </div>\n\n <button\n v-if=\"showThemeToggle\"\n type=\"button\"\n class=\"fn-theme-toggle group inline-flex h-9 w-9 items-center justify-center rounded-full border border-border/70 bg-card/85 text-muted-foreground shadow-lg backdrop-blur-md transition-colors hover:text-foreground\"\n :aria-label=\"themeToggleLabel\"\n :title=\"themeToggleLabel\"\n @click=\"toggleTheme\"\n >\n <svg\n v-if=\"isLightTheme\"\n class=\"h-4 w-4\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 3a1 1 0 0 1 1 1v1a1 1 0 1 1-2 0V4a1 1 0 0 1 1-1Z\" />\n <path\n d=\"M18.36 5.64a1 1 0 0 1 1.41 0l.71.71a1 1 0 0 1-1.41 1.41l-.71-.7a1 1 0 0 1 0-1.42Z\"\n />\n <path d=\"M20 11a1 1 0 1 1 0 2h-1a1 1 0 1 1 0-2h1Z\" />\n <path\n d=\"M18.36 18.36a1 1 0 0 1 0-1.41l.71-.71a1 1 0 0 1 1.41 1.41l-.7.71a1 1 0 0 1-1.42 0Z\"\n />\n <path d=\"M12 19a1 1 0 0 1 1 1v1a1 1 0 1 1-2 0v-1a1 1 0 0 1 1-1Z\" />\n <path\n d=\"M5.64 18.36a1 1 0 0 1-1.41 0l-.71-.71a1 1 0 1 1 1.41-1.41l.71.7a1 1 0 0 1 0 1.42Z\"\n />\n <path d=\"M5 11a1 1 0 1 1 0 2H4a1 1 0 1 1 0-2h1Z\" />\n <path\n d=\"M5.64 5.64a1 1 0 0 1 0 1.41l-.71.71a1 1 0 1 1-1.41-1.41l.7-.71a1 1 0 0 1 1.42 0Z\"\n />\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n </svg>\n\n <svg\n v-else\n class=\"h-4 w-4\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 12.79A9 9 0 1 1 11.21 3a7 7 0 1 0 9.79 9.79Z\" />\n </svg>\n </button>\n\n <p\n v-if=\"showExportControls && exportError\"\n class=\"max-w-[260px] rounded-md border border-red-500/45 bg-red-500/12 px-2 py-1 text-[10px] leading-relaxed text-red-200\"\n >\n {{ exportError }}\n </p>\n </div>\n\n <div\n v-if=\"!isArchitectureMode\"\n class=\"pointer-events-none absolute inset-x-0 bottom-2 z-30 flex justify-center px-3\"\n style=\"padding-bottom: max(env(safe-area-inset-bottom), 0px)\"\n >\n <div class=\"pointer-events-auto w-full max-w-[980px]\">\n <TimelineControls\n :current-step=\"currentStep\"\n :total-steps=\"totalSteps\"\n :playing=\"playing\"\n :label=\"activeLabel\"\n :description=\"activeDescription\"\n :source-anchor-label=\"activeSourceAnchor?.label\"\n :source-anchor-href=\"activeSourceAnchor?.href\"\n :choices=\"branchChoices\"\n :selected-choice-id=\"selectedBranchChoiceId\"\n @next=\"next\"\n @prev=\"prev\"\n @go-to=\"goTo\"\n @toggle-play=\"togglePlay\"\n @choose-choice=\"chooseChoice\"\n />\n </div>\n </div>\n\n <div\n v-if=\"isArchitectureMode && showArchitectureInspectorPanel && architectureInspector\"\n class=\"fn-architecture-inspector pointer-events-none absolute bottom-3 right-0 top-16 z-30 w-[min(92vw,430px)]\"\n style=\"\n padding-right: max(env(safe-area-inset-right), 0px);\n padding-bottom: max(env(safe-area-inset-bottom), 0px);\n \"\n >\n <div class=\"absolute inset-0 overflow-visible\">\n <aside\n class=\"pointer-events-auto absolute inset-y-0 right-0 w-full transition-all duration-300 ease-out\"\n :style=\"architectureInspectorPanelStyle\"\n >\n <button\n type=\"button\"\n class=\"fn-architecture-inspector__toggle absolute right-full top-1/2 z-30 inline-flex h-20 w-8 -translate-y-1/2 translate-x-px flex-col items-center justify-center gap-1 rounded-l-lg rounded-r-none border border-border/70 border-r-0 bg-gradient-to-b from-card/95 via-card/88 to-card/78 px-0.5 text-[8px] font-semibold uppercase tracking-[0.12em] text-muted-foreground shadow-2xl backdrop-blur-xl transition-all duration-200 hover:text-foreground\"\n :aria-label=\"architectureInspectorToggleLabel\"\n :title=\"architectureInspectorToggleLabel\"\n @click=\"toggleArchitectureInspector\"\n >\n <svg\n class=\"h-2.5 w-2.5\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path v-if=\"architectureInspectorOpen\" d=\"m14.5 6-5.5 6 5.5 6\" />\n <path v-else d=\"m9.5 6 5.5 6-5.5 6\" />\n </svg>\n <span\n v-if=\"showArchitectureInspectorToggleText\"\n class=\"inline-block font-semibold leading-none\"\n style=\"writing-mode: vertical-rl; transform: rotate(180deg); letter-spacing: 0.1em\"\n >\n Details\n </span>\n </button>\n\n <div\n class=\"fn-architecture-inspector__panel flex h-full flex-col overflow-hidden rounded-2xl border border-border/60 bg-gradient-to-b from-card/95 via-card/90 to-card/82 shadow-2xl backdrop-blur-xl\"\n >\n <div class=\"border-b border-border/60 px-3 py-2.5\">\n <div class=\"flex flex-wrap items-start justify-between gap-2\">\n <div class=\"min-w-0\">\n <p class=\"text-[11px] font-semibold text-foreground leading-snug break-words\">\n {{ architectureInspector.label }}\n </p>\n\n <div v-if=\"architectureInspectorNode\" class=\"mt-1 flex flex-wrap gap-1\">\n <span\n v-if=\"architectureInspectorNodeSafe.kind\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[9px] uppercase tracking-wider text-muted-foreground\"\n >\n {{ architectureInspectorNodeSafe.kind }}\n </span>\n <span\n v-if=\"architectureInspectorNodeSafe.status\"\n class=\"inline-flex items-center rounded border border-primary/35 bg-primary/10 px-1.5 py-0.5 text-[9px] uppercase tracking-wider text-primary\"\n >\n {{ architectureInspectorNodeSafe.status }}\n </span>\n <span\n v-if=\"architectureInspectorNodeSafe.tier\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[9px] uppercase tracking-wider text-muted-foreground\"\n >\n {{ architectureInspectorNodeSafe.tier }}\n </span>\n <span\n v-if=\"architectureInspectorNodeSafe.zoneLabel\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[9px] uppercase tracking-wider text-muted-foreground\"\n >\n Zone: {{ architectureInspectorNodeSafe.zoneLabel }}\n </span>\n </div>\n </div>\n\n <a\n v-if=\"\n architectureInspector.sourceAnchor?.label &&\n architectureInspector.sourceAnchor?.href\n \"\n :href=\"architectureInspector.sourceAnchor.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"inline-flex max-w-full items-center gap-1 rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground transition-colors hover:border-primary/45 hover:text-foreground\"\n >\n <span class=\"truncate\">{{ architectureInspector.sourceAnchor.label }}</span>\n </a>\n\n <p\n v-else-if=\"architectureInspector.sourceAnchor?.label\"\n class=\"inline-flex max-w-full items-center rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground\"\n >\n <span class=\"truncate\">{{ architectureInspector.sourceAnchor.label }}</span>\n </p>\n </div>\n\n <p\n v-if=\"architectureInspector.summary\"\n class=\"mt-1.5 text-[11px] text-muted-foreground leading-relaxed whitespace-pre-wrap break-words\"\n >\n {{ architectureInspector.summary }}\n </p>\n </div>\n\n <div class=\"min-h-0 flex-1 space-y-2 overflow-y-auto px-3 py-2.5\">\n <template v-if=\"architectureInspectorNode\">\n <div class=\"rounded-lg border border-border/60 bg-muted/20 px-2 py-1.5\">\n <p\n class=\"text-[9px] font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n Core\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.technology\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Technology: {{ architectureInspectorNodeSafe.technology }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.runtime\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Runtime: {{ architectureInspectorNodeSafe.runtime }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.owner\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Owner: {{ architectureInspectorNodeSafe.owner }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.operations?.slo\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n SLO: {{ architectureInspectorNodeSafe.operations.slo }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.operations?.alert\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Alert: {{ architectureInspectorNodeSafe.operations.alert }}\n </p>\n </div>\n\n <div\n v-if=\"\n architectureInspectorNodeSafe.security ||\n architectureInspectorNodeSafe.dataAssets.length > 0\n \"\n class=\"rounded-lg border border-border/60 bg-muted/20 px-2 py-1.5\"\n >\n <p\n class=\"text-[9px] font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n Data & Security\n </p>\n <template v-if=\"architectureInspectorNodeSafe.security\">\n <p\n v-if=\"architectureInspectorNodeSafe.security.auth\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Auth: {{ architectureInspectorNodeSafe.security.auth }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.security.encryption\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Encryption: {{ architectureInspectorNodeSafe.security.encryption }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.security.pii !== undefined\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n PII: {{ architectureInspectorNodeSafe.security.pii ? \"Yes\" : \"No\" }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.security.threatModel\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Threat Model: {{ architectureInspectorNodeSafe.security.threatModel }}\n </p>\n </template>\n\n <div\n v-if=\"architectureInspectorNodeSafe.dataAssets.length > 0\"\n class=\"mt-1.5 space-y-1\"\n >\n <p\n v-for=\"asset in architectureInspectorNodeSafe.dataAssets\"\n :key=\"`${asset.name}-${asset.kind ?? ''}`\"\n class=\"text-[10px] text-foreground\"\n >\n {{ asset.name }}<span v-if=\"asset.kind\"> ({{ asset.kind }})</span\n ><span v-if=\"asset.classification\"> - {{ asset.classification }}</span\n ><span v-if=\"asset.retention\"> - {{ asset.retention }}</span>\n </p>\n </div>\n </div>\n\n <div\n v-if=\"\n architectureInspectorNodeSafe.responsibilities.length > 0 ||\n architectureInspectorNodeSafe.capabilities.length > 0 ||\n architectureInspectorNodeSafe.tags.length > 0\n \"\n class=\"rounded-lg border border-border/60 bg-muted/20 px-2 py-1.5\"\n >\n <p\n class=\"text-[9px] font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n Capabilities\n </p>\n\n <div\n v-if=\"architectureInspectorNodeSafe.capabilities.length > 0\"\n class=\"mt-1 flex flex-wrap gap-1\"\n >\n <span\n v-for=\"capability in architectureInspectorNodeSafe.capabilities\"\n :key=\"capability\"\n class=\"inline-flex items-center rounded border border-primary/35 bg-primary/10 px-1.5 py-0.5 text-[9px] text-primary\"\n >\n {{ capability }}\n </span>\n </div>\n\n <div\n v-if=\"architectureInspectorNodeSafe.tags.length > 0\"\n class=\"mt-1 flex flex-wrap gap-1\"\n >\n <span\n v-for=\"tag in architectureInspectorNodeSafe.tags\"\n :key=\"tag\"\n class=\"inline-flex items-center rounded border border-border/70 bg-card/35 px-1.5 py-0.5 text-[9px] text-muted-foreground\"\n >\n #{{ tag }}\n </span>\n </div>\n\n <ul\n v-if=\"architectureInspectorNodeSafe.responsibilities.length > 0\"\n class=\"mt-1 space-y-0.5 text-[10px] text-foreground\"\n >\n <li v-for=\"item in architectureInspectorNodeSafe.responsibilities\" :key=\"item\">\n - {{ item }}\n </li>\n </ul>\n </div>\n\n <div\n v-if=\"\n architectureInspectorNodeSafe.interfaces.length > 0 ||\n architectureInspectorNodeSafe.outgoing.length > 0 ||\n architectureInspectorNodeSafe.links.length > 0 ||\n architectureInspectorNodeSafe.operations?.runbook\n \"\n class=\"rounded-lg border border-border/60 bg-muted/20 px-2 py-1.5\"\n >\n <p\n class=\"text-[9px] font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n Interfaces & Links\n </p>\n\n <div\n v-if=\"architectureInspectorNodeSafe.interfaces.length > 0\"\n class=\"mt-1 space-y-1\"\n >\n <p\n v-for=\"iface in architectureInspectorNodeSafe.interfaces\"\n :key=\"`${iface.name}-${iface.protocol ?? ''}-${iface.direction ?? ''}`\"\n class=\"text-[10px] text-foreground\"\n >\n {{ iface.name }}<span v-if=\"iface.protocol\"> ({{ iface.protocol }})</span\n ><span v-if=\"iface.direction\"> - {{ iface.direction }}</span\n ><span v-if=\"iface.auth\"> - auth: {{ iface.auth }}</span\n ><span v-if=\"iface.contract\"> - {{ iface.contract }}</span>\n </p>\n </div>\n\n <p\n v-if=\"architectureInspectorNodeSafe.operations?.runbook\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Runbook: {{ architectureInspectorNodeSafe.operations.runbook }}\n </p>\n\n <div\n v-if=\"architectureInspectorNodeSafe.outgoing.length > 0\"\n class=\"mt-1 space-y-1\"\n >\n <p\n v-for=\"edge in architectureInspectorNodeSafe.outgoing\"\n :key=\"`${edge.target}-${edge.label ?? ''}-${edge.protocol ?? ''}`\"\n class=\"text-[10px] text-foreground\"\n >\n {{ edge.label ?? \"Connect\" }} -> {{ edge.target\n }}<span v-if=\"edge.protocol\"> ({{ edge.protocol }})</span\n ><span v-if=\"edge.transport\"> - {{ edge.transport }}</span\n ><span v-if=\"edge.auth\"> - auth: {{ edge.auth }}</span\n ><span v-if=\"edge.criticality\"> - {{ edge.criticality }}</span>\n </p>\n </div>\n\n <div\n v-if=\"architectureInspectorNodeSafe.links.length > 0\"\n class=\"mt-1 flex flex-wrap gap-1\"\n >\n <a\n v-for=\"link in architectureInspectorNodeSafe.links\"\n :key=\"`${link.label}-${link.href}`\"\n :href=\"link.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"inline-flex items-center rounded border border-border/70 bg-card/35 px-1.5 py-0.5 text-[9px] text-foreground transition-colors hover:border-primary/45\"\n >\n {{ link.label }}\n </a>\n </div>\n </div>\n </template>\n </div>\n </div>\n </aside>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport dagre from \"@dagrejs/dagre\";\nimport { useStateStore, useStateValue } from \"@json-render/vue\";\nimport {\n Position,\n VueFlow,\n type NodeProps,\n type NodeTypesObject,\n useNodesInitialized,\n useVueFlow,\n} from \"@vue-flow/core\";\nimport {\n computed,\n defineComponent,\n getCurrentInstance,\n h,\n markRaw,\n nextTick,\n onMounted,\n onUnmounted,\n ref,\n watch,\n} from \"vue\";\n\nimport {\n CODE_NODE_MAX_INLINE_CHARS,\n estimateCodeNodeCharsPerLine,\n estimateCodeNodeWidth,\n} from \"../../code-node-sizing\";\nimport { exportFlowDiagram, type DiagramExportFormat } from \"../../composables/useDiagramExport\";\nimport { useFlaierRuntime } from \"../../composables/useFlaierRuntime\";\nimport {\n hasTwoslashHints,\n hasTwoslashHtml,\n normalizeTwoslashHtml,\n normalizeTwoslashLanguage,\n} from \"../../twoslash\";\nimport type {\n ArchitectureDataAsset,\n ArchitectureInterface,\n ArchitectureLink,\n ArchitectureNodeProps,\n FlaierCustomNodeContext,\n FlaierCustomNodeDefinition,\n FlaierCustomNodeSize,\n FlaierResolvedSourceAnchor,\n ArchitectureOperations,\n ArchitectureSecurity,\n ArchitectureZone,\n EdgeTransitionKind,\n FlowEdge,\n FlowNode,\n FlowNodeData,\n FlowNodeType,\n MagicMoveStep,\n SpecElement,\n TwoslashHtml,\n} from \"../../types\";\nimport TimelineControls from \"../controls/TimelineControls.vue\";\nimport ArchitectureSmoothEdge from \"../edges/ArchitectureSmoothEdge.vue\";\nimport ArchitectureNodeVue from \"../nodes/ArchitectureNode.vue\";\nimport CodeNodeVue from \"../nodes/CodeNode.vue\";\nimport DecisionNodeVue from \"../nodes/DecisionNode.vue\";\nimport DescriptionNodeVue from \"../nodes/DescriptionNode.vue\";\nimport ErrorNodeVue from \"../nodes/ErrorNode.vue\";\nimport LinkNodeVue from \"../nodes/LinkNode.vue\";\nimport PayloadNodeVue from \"../nodes/PayloadNode.vue\";\nimport TriggerNodeVue from \"../nodes/TriggerNode.vue\";\n\nconst props = withDefaults(\n defineProps<{\n title: string;\n description?: string;\n mode?: \"narrative\" | \"architecture\";\n zones?: ArchitectureZone[];\n direction?: \"horizontal\" | \"vertical\";\n minHeight?: number;\n layoutEngine?: \"dagre\" | \"manual\";\n layoutRankSep?: number;\n layoutNodeSep?: number;\n layoutEdgeSep?: number;\n themeMode?: \"local\" | \"document\";\n showHeaderOverlay?: boolean;\n showExportControls?: boolean;\n showThemeToggle?: boolean;\n showArchitectureInspector?: boolean;\n defaultArchitectureInspectorOpen?: boolean;\n showArchitectureInspectorToggleText?: boolean;\n }>(),\n {\n mode: \"narrative\",\n direction: \"horizontal\",\n layoutEngine: \"dagre\",\n themeMode: \"local\",\n showHeaderOverlay: true,\n showExportControls: true,\n showThemeToggle: true,\n showArchitectureInspector: true,\n defaultArchitectureInspectorOpen: true,\n showArchitectureInspectorToggleText: true,\n },\n);\n\nconst TYPE_MAP: Record<string, FlowNodeType> = {\n ArchitectureNode: \"architecture\",\n TriggerNode: \"trigger\",\n CodeNode: \"code\",\n DecisionNode: \"decision\",\n PayloadNode: \"payload\",\n ErrorNode: \"error\",\n DescriptionNode: \"description\",\n LinkNode: \"link\",\n};\n\nfunction toNodeType(elementType: string): FlowNodeType | undefined {\n if (TYPE_MAP[elementType]) {\n return TYPE_MAP[elementType];\n }\n\n return customNodes.value[elementType] ? elementType : undefined;\n}\n\nfunction getCustomNodeDefinition(elementType: string): FlaierCustomNodeDefinition | undefined {\n return customNodes.value[elementType];\n}\n\nconst DEFAULT_LAYOUT_ENGINE = \"dagre\";\nconst DEFAULT_FALLBACK_GAP = 420;\nconst DEFAULT_DAGRE_RANK_SEP_HORIZONTAL = 260;\nconst DEFAULT_DAGRE_NODE_SEP_HORIZONTAL = 120;\nconst DEFAULT_DAGRE_RANK_SEP_VERTICAL = 220;\nconst DEFAULT_DAGRE_NODE_SEP_VERTICAL = 120;\nconst DEFAULT_DAGRE_EDGE_SEP = 30;\nconst OVERVIEW_ENTER_ZOOM = 0.52;\nconst OVERVIEW_EXIT_ZOOM = 0.62;\nconst FLAIER_THEME_STORAGE_KEY = \"flaier-ui-theme\";\nconst ARCHITECTURE_ZONE_MIN_CONTENT_PADDING = 44;\nconst ARCHITECTURE_ZONE_MIN_BOTTOM_PADDING = 88;\nconst ARCHITECTURE_ZONE_LABEL_TOP = 12;\nconst ARCHITECTURE_ZONE_LABEL_HEIGHT = 22;\nconst ARCHITECTURE_ZONE_DESCRIPTION_HEIGHT = 16;\nconst ARCHITECTURE_ZONE_LABEL_TO_DESCRIPTION_GAP = 6;\nconst ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP = 12;\nconst ARCHITECTURE_ZONE_NESTED_LABEL_STEP = 18;\nconst ARCHITECTURE_ZONE_CONTAINED_ZONE_GAP = 46;\nconst EDGE_TRANSITION_KINDS: EdgeTransitionKind[] = [\n \"default\",\n \"success\",\n \"error\",\n \"warning\",\n \"retry\",\n \"async\",\n];\nconst EDGE_TRANSITION_KIND_SET = new Set(EDGE_TRANSITION_KINDS);\nconst EDGE_TRANSITION_TRANSPORT_SET = new Set([\"sync\", \"async\"]);\nconst EDGE_TRANSITION_CRITICALITY_SET = new Set([\"low\", \"medium\", \"high\"]);\nconst ARCHITECTURE_NODE_KINDS: Array<NonNullable<ArchitectureNodeProps[\"kind\"]>> = [\n \"service\",\n \"database\",\n \"queue\",\n \"cache\",\n \"gateway\",\n \"external\",\n \"compute\",\n];\nconst ARCHITECTURE_NODE_KIND_SET = new Set(ARCHITECTURE_NODE_KINDS);\nconst ARCHITECTURE_NODE_STATUS_VALUES: Array<NonNullable<ArchitectureNodeProps[\"status\"]>> = [\n \"planned\",\n \"active\",\n \"degraded\",\n \"retired\",\n];\nconst ARCHITECTURE_NODE_STATUS_SET = new Set(ARCHITECTURE_NODE_STATUS_VALUES);\nconst ARCHITECTURE_NODE_TIER_VALUES: Array<NonNullable<ArchitectureNodeProps[\"tier\"]>> = [\n \"edge\",\n \"application\",\n \"integration\",\n \"data\",\n \"platform\",\n \"external\",\n];\nconst ARCHITECTURE_NODE_TIER_SET = new Set(ARCHITECTURE_NODE_TIER_VALUES);\nconst ARCHITECTURE_INTERFACE_DIRECTION_VALUES: Array<\n NonNullable<ArchitectureInterface[\"direction\"]>\n> = [\"inbound\", \"outbound\", \"bidirectional\"];\nconst ARCHITECTURE_INTERFACE_DIRECTION_SET = new Set(ARCHITECTURE_INTERFACE_DIRECTION_VALUES);\nconst ARCHITECTURE_DATA_CLASSIFICATION_VALUES: Array<\n NonNullable<ArchitectureDataAsset[\"classification\"]>\n> = [\"public\", \"internal\", \"confidential\", \"restricted\"];\nconst ARCHITECTURE_DATA_CLASSIFICATION_SET = new Set(ARCHITECTURE_DATA_CLASSIFICATION_VALUES);\nconst ARCHITECTURE_ZONE_COLOR_PALETTE = [\n \"#38bdf8\",\n \"#22c55e\",\n \"#f59e0b\",\n \"#f97316\",\n \"#a78bfa\",\n \"#14b8a6\",\n \"#fb7185\",\n];\nconst SOURCE_ANCHOR_LINK_PATTERN = /^(https?:\\/\\/|vscode:\\/\\/|idea:\\/\\/)/i;\nconst SOURCE_ANCHOR_TRAILING_LOCATION_PATTERN = /^(.*?):(\\d+)(?::(\\d+))?$/;\n\ninterface NodeSize {\n width: number;\n height: number;\n}\n\ninterface OrderedNodeElement {\n key: string;\n index: number;\n nodeType: FlowNodeType;\n element: SpecElement;\n}\n\ninterface TimelineFrame {\n nodeIndex: number;\n nodeKey: string;\n localStep: number;\n totalLocalSteps: number;\n}\n\ninterface BranchChoice {\n id: string;\n label: string;\n description?: string;\n kind?: EdgeTransitionKind;\n}\n\ninterface ParsedTransition {\n to: string;\n label?: string;\n description?: string;\n kind?: EdgeTransitionKind;\n protocol?: string;\n transport?: \"sync\" | \"async\";\n auth?: string;\n contract?: string;\n criticality?: \"low\" | \"medium\" | \"high\";\n}\n\ninterface ParsedSourceAnchor {\n label: string;\n href?: string;\n}\n\ninterface ParsedAnchorLocation {\n path: string;\n line?: number;\n column?: number;\n}\n\ninterface ResolvedArchitectureZone extends ArchitectureZone {\n padding: number;\n}\n\ninterface ArchitectureZoneOverlay {\n id: string;\n label: string;\n description?: string;\n color: string;\n x: number;\n y: number;\n width: number;\n height: number;\n nodeCount: number;\n nestingDepth: number;\n labelLane: number;\n labelOffsetY: number;\n descriptionOffsetY: number;\n}\n\ninterface ArchitectureOutgoingEdge {\n target: string;\n label?: string;\n protocol?: string;\n transport?: \"sync\" | \"async\";\n auth?: string;\n criticality?: \"low\" | \"medium\" | \"high\";\n}\n\ninterface ArchitectureInspectorArchitectureView {\n type: \"ArchitectureNode\";\n label: string;\n sourceAnchor?: ParsedSourceAnchor;\n kind?: ArchitectureNodeProps[\"kind\"];\n status?: ArchitectureNodeProps[\"status\"];\n tier?: ArchitectureNodeProps[\"tier\"];\n technology?: string;\n runtime?: string;\n owner?: string;\n zoneLabel?: string;\n summary: string;\n tags: string[];\n responsibilities: string[];\n capabilities: string[];\n interfaces: ArchitectureInterface[];\n dataAssets: ArchitectureDataAsset[];\n security?: ArchitectureSecurity;\n operations?: ArchitectureOperations;\n links: ArchitectureLink[];\n outgoing: ArchitectureOutgoingEdge[];\n}\n\ninterface ArchitectureInspectorGenericView {\n type: \"Other\";\n label: string;\n sourceAnchor?: ParsedSourceAnchor;\n summary: string;\n elementType: string;\n}\n\ntype ArchitectureInspectorView =\n | ArchitectureInspectorArchitectureView\n | ArchitectureInspectorGenericView;\n\nconst EMPTY_ARCHITECTURE_INSPECTOR_NODE: ArchitectureInspectorArchitectureView = {\n type: \"ArchitectureNode\",\n label: \"\",\n summary: \"\",\n tags: [],\n responsibilities: [],\n capabilities: [],\n interfaces: [],\n dataAssets: [],\n links: [],\n outgoing: [],\n};\n\nconst runtime = useFlaierRuntime();\nconst spec = computed(() => runtime.spec.value);\nconst customNodes = computed(() => runtime.nodes.value);\nconst availableFlows = computed(() => runtime.flowOptions.value);\nconst activeFlowId = computed(() => runtime.activeFlowId.value);\nconst activeFlow = computed(() => {\n const activeId = activeFlowId.value;\n if (!activeId) return undefined;\n return availableFlows.value.find((flow) => flow.id === activeId);\n});\nconst showFlowSelector = computed(() => availableFlows.value.length > 1);\nconst showHeaderOverlay = computed(() => props.showHeaderOverlay !== false);\nconst overlayTitle = computed(() => activeFlow.value?.title ?? props.title);\nconst overlayDescription = computed(() => activeFlow.value?.description ?? props.description);\nconst headerModeLabel = computed(() => {\n if (showFlowSelector.value) {\n return \"Flow\";\n }\n\n return isArchitectureMode.value ? \"Diagram\" : \"Narrative\";\n});\nconst headerDropdownRef = ref<HTMLDivElement | null>(null);\nconst headerDropdownOpen = ref(false);\nconst exportMenuRef = ref<HTMLDivElement | null>(null);\nconst exportMenuOpen = ref(false);\nconst exportInFlight = ref<DiagramExportFormat | null>(null);\nconst exportError = ref<string | null>(null);\nconst containerRef = ref<HTMLDivElement | null>(null);\nconst sceneRef = ref<HTMLElement | null>(null);\nconst containerReady = ref(false);\nconst containerWidth = ref(0);\nconst containerHeight = ref(0);\nconst uiTheme = ref<\"dark\" | \"light\">(\"dark\");\nlet documentThemeObserver: MutationObserver | null = null;\nlet documentThemeMediaQuery: MediaQueryList | null = null;\nlet handleDocumentThemeMediaQueryChange: ((event: MediaQueryListEvent) => void) | null = null;\nconst isLightTheme = computed(() => uiTheme.value === \"light\");\nconst themeMode = computed(() => (props.themeMode === \"document\" ? \"document\" : \"local\"));\nconst isArchitectureMode = computed(() => props.mode === \"architecture\");\nconst showExportControls = computed(() => props.showExportControls !== false);\nconst showThemeToggle = computed(() => props.showThemeToggle !== false);\nconst showArchitectureInspectorPanel = computed(() => props.showArchitectureInspector !== false);\nconst defaultArchitectureInspectorOpen = computed(\n () => props.defaultArchitectureInspectorOpen !== false,\n);\nconst showArchitectureInspectorToggleText = computed(\n () => props.showArchitectureInspectorToggleText !== false,\n);\nconst showTopRightControls = computed(() => {\n return (\n showExportControls.value ||\n showThemeToggle.value ||\n (showExportControls.value && Boolean(exportError.value))\n );\n});\nconst architectureInspectorOpen = ref(props.defaultArchitectureInspectorOpen !== false);\nconst themeToggleLabel = computed(() => {\n return isLightTheme.value ? \"Switch to dark mode\" : \"Switch to light mode\";\n});\n\nconst architectureInspectorToggleLabel = computed(() => {\n return architectureInspectorOpen.value\n ? \"Hide architecture details sidebar\"\n : \"Show architecture details sidebar\";\n});\n\nconst exportButtonLabel = computed(() => {\n if (exportInFlight.value === \"png\") {\n return \"Exporting PNG...\";\n }\n\n if (exportInFlight.value === \"pdf\") {\n return \"Exporting PDF...\";\n }\n\n return \"Export full diagram\";\n});\n\nfunction toggleTheme() {\n if (themeMode.value === \"document\") {\n applyDocumentTheme(isLightTheme.value ? \"dark\" : \"light\");\n return;\n }\n\n uiTheme.value = isLightTheme.value ? \"dark\" : \"light\";\n}\n\nfunction toggleArchitectureInspector() {\n architectureInspectorOpen.value = !architectureInspectorOpen.value;\n}\n\nfunction normalizeTheme(value: unknown): \"dark\" | \"light\" | null {\n if (value === \"dark\" || value === \"light\") {\n return value;\n }\n\n return null;\n}\n\nfunction readStoredTheme() {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n try {\n return normalizeTheme(window.localStorage.getItem(FLAIER_THEME_STORAGE_KEY));\n } catch {\n return null;\n }\n}\n\nfunction getPreferredSystemTheme(): \"dark\" | \"light\" {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") {\n return \"dark\";\n }\n\n return window.matchMedia(\"(prefers-color-scheme: light)\").matches ? \"light\" : \"dark\";\n}\n\nfunction getDocumentTheme(): \"dark\" | \"light\" | null {\n if (typeof document === \"undefined\") {\n return null;\n }\n\n const root = document.documentElement;\n const dataTheme = root.getAttribute(\"data-theme\")?.trim().toLowerCase();\n\n if (dataTheme === \"dark\" || dataTheme === \"light\") {\n return dataTheme;\n }\n\n if (root.classList.contains(\"dark\")) {\n return \"dark\";\n }\n\n if (root.classList.contains(\"light\")) {\n return \"light\";\n }\n\n const colorScheme = root.style.colorScheme?.trim().toLowerCase();\n if (colorScheme === \"dark\" || colorScheme === \"light\") {\n return colorScheme;\n }\n\n return null;\n}\n\nfunction applyDocumentTheme(theme: \"dark\" | \"light\") {\n if (typeof document === \"undefined\") {\n return;\n }\n\n const root = document.documentElement;\n root.classList.toggle(\"dark\", theme === \"dark\");\n root.style.colorScheme = theme;\n}\n\nfunction persistTheme(theme: \"dark\" | \"light\") {\n if (typeof window === \"undefined\") {\n return;\n }\n\n try {\n window.localStorage.setItem(FLAIER_THEME_STORAGE_KEY, theme);\n } catch {\n // no-op when storage is unavailable\n }\n}\n\nfunction syncDocumentTheme() {\n uiTheme.value = getDocumentTheme() ?? getPreferredSystemTheme();\n}\n\nfunction startDocumentThemeSync() {\n if (typeof document !== \"undefined\" && typeof MutationObserver !== \"undefined\") {\n if (!documentThemeObserver) {\n documentThemeObserver = new MutationObserver(() => {\n syncDocumentTheme();\n });\n\n documentThemeObserver.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\", \"style\", \"data-theme\"],\n });\n }\n }\n\n if (typeof window !== \"undefined\" && typeof window.matchMedia === \"function\") {\n if (!documentThemeMediaQuery) {\n documentThemeMediaQuery = window.matchMedia(\"(prefers-color-scheme: light)\");\n }\n\n if (!handleDocumentThemeMediaQueryChange) {\n handleDocumentThemeMediaQueryChange = () => {\n syncDocumentTheme();\n };\n\n if (typeof documentThemeMediaQuery.addEventListener === \"function\") {\n documentThemeMediaQuery.addEventListener(\"change\", handleDocumentThemeMediaQueryChange);\n } else {\n documentThemeMediaQuery.addListener(handleDocumentThemeMediaQueryChange);\n }\n }\n }\n}\n\nfunction stopDocumentThemeSync() {\n if (documentThemeObserver) {\n documentThemeObserver.disconnect();\n documentThemeObserver = null;\n }\n\n if (documentThemeMediaQuery && handleDocumentThemeMediaQueryChange) {\n if (typeof documentThemeMediaQuery.removeEventListener === \"function\") {\n documentThemeMediaQuery.removeEventListener(\"change\", handleDocumentThemeMediaQueryChange);\n } else {\n documentThemeMediaQuery.removeListener(handleDocumentThemeMediaQueryChange);\n }\n }\n\n handleDocumentThemeMediaQueryChange = null;\n documentThemeMediaQuery = null;\n}\n\nfunction toggleHeaderDropdown() {\n if (!showFlowSelector.value) return;\n closeExportMenu();\n headerDropdownOpen.value = !headerDropdownOpen.value;\n}\n\nfunction closeHeaderDropdown() {\n headerDropdownOpen.value = false;\n}\n\nfunction toggleExportMenu() {\n if (exportInFlight.value) return;\n if (!canExportDiagram.value) return;\n\n closeHeaderDropdown();\n exportMenuOpen.value = !exportMenuOpen.value;\n}\n\nfunction closeExportMenu() {\n exportMenuOpen.value = false;\n}\n\nfunction handleFlowSelect(flowId: string) {\n if (!flowId) return;\n\n runtime.setActiveFlow(flowId);\n headerDropdownOpen.value = false;\n closeExportMenu();\n}\n\nwatch(showFlowSelector, (show) => {\n if (!show) {\n headerDropdownOpen.value = false;\n }\n});\n\nwatch(activeFlowId, () => {\n headerDropdownOpen.value = false;\n closeExportMenu();\n});\n\nwatch(uiTheme, (theme) => {\n if (themeMode.value === \"document\") {\n return;\n }\n\n persistTheme(theme);\n});\n\nwatch(\n themeMode,\n (mode) => {\n if (mode === \"document\") {\n startDocumentThemeSync();\n syncDocumentTheme();\n return;\n }\n\n stopDocumentThemeSync();\n uiTheme.value = readStoredTheme() ?? getPreferredSystemTheme();\n },\n { immediate: true },\n);\n\nconst rootElement = computed(() => {\n const activeSpec = spec.value;\n if (!activeSpec) return undefined;\n return activeSpec.elements[activeSpec.root];\n});\n\nconst orderedNodeElements = computed<OrderedNodeElement[]>(() => {\n const activeSpec = spec.value;\n const root = rootElement.value;\n\n if (!activeSpec || !root?.children?.length) return [];\n\n const result: OrderedNodeElement[] = [];\n const queue = [...root.children];\n const seen = new Set<string>();\n\n while (queue.length > 0) {\n const key = queue.shift();\n if (!key || seen.has(key)) continue;\n\n const element = activeSpec.elements[key];\n if (!element) continue;\n\n const nodeType = toNodeType(element.type);\n if (!nodeType) continue;\n\n seen.add(key);\n result.push({ key, index: result.length, nodeType, element });\n\n for (const childKey of element.children ?? []) {\n if (!seen.has(childKey)) {\n queue.push(childKey);\n }\n }\n }\n\n return result;\n});\n\nconst orderedNodeByKey = computed<Record<string, OrderedNodeElement>>(() => {\n const map: Record<string, OrderedNodeElement> = {};\n\n for (const node of orderedNodeElements.value) {\n map[node.key] = node;\n }\n\n return map;\n});\n\nconst rootLinearNextByKey = computed<Record<string, string>>(() => {\n const root = rootElement.value;\n if (!root?.children?.length) return {};\n const rootChildren = root.children;\n\n const map: Record<string, string> = {};\n\n rootChildren.forEach((key, index) => {\n const nextKey = rootChildren[index + 1];\n if (!nextKey) return;\n\n if (orderedNodeByKey.value[key] && orderedNodeByKey.value[nextKey]) {\n map[key] = nextKey;\n }\n });\n\n return map;\n});\n\nconst transitionMetaBySource = computed<Record<string, Record<string, ParsedTransition>>>(() => {\n const map: Record<string, Record<string, ParsedTransition>> = {};\n\n for (const node of orderedNodeElements.value) {\n const transitions = toTransitions(node.element.props.transitions).filter((transition) =>\n Boolean(orderedNodeByKey.value[transition.to]),\n );\n\n if (transitions.length === 0) continue;\n\n const byTarget: Record<string, ParsedTransition> = {};\n for (const transition of transitions) {\n if (byTarget[transition.to]) continue;\n byTarget[transition.to] = transition;\n }\n\n if (Object.keys(byTarget).length > 0) {\n map[node.key] = byTarget;\n }\n }\n\n return map;\n});\n\nconst outgoingNodeKeys = computed<Record<string, string[]>>(() => {\n const map: Record<string, string[]> = {};\n\n for (const node of orderedNodeElements.value) {\n const transitionTargets = toTransitions(node.element.props.transitions)\n .map((transition) => transition.to)\n .filter((key) => Boolean(orderedNodeByKey.value[key]));\n\n const explicit = (node.element.children ?? []).filter((key) =>\n Boolean(orderedNodeByKey.value[key]),\n );\n\n const combined = mergeOutgoingTargets(transitionTargets, explicit);\n\n if (combined.length > 0) {\n map[node.key] = combined;\n continue;\n }\n\n const fallback = rootLinearNextByKey.value[node.key];\n map[node.key] = fallback ? [fallback] : [];\n }\n\n return map;\n});\n\nconst incomingNodeKeys = computed<Record<string, string[]>>(() => {\n const map: Record<string, string[]> = {};\n\n for (const node of orderedNodeElements.value) {\n map[node.key] = [];\n }\n\n for (const [source, targets] of Object.entries(outgoingNodeKeys.value)) {\n for (const target of targets) {\n if (!map[target]) continue;\n map[target].push(source);\n }\n }\n\n return map;\n});\n\nconst startNodeKey = computed(() => {\n const root = rootElement.value;\n if (!root?.children?.length) return undefined;\n\n return root.children.find((key) => Boolean(orderedNodeByKey.value[key]));\n});\n\nfunction toOptionalString(value: unknown) {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction toStringArray(value: unknown) {\n if (!Array.isArray(value)) {\n return [];\n }\n\n return value\n .map((entry) => toTrimmedNonEmptyString(entry))\n .filter((entry): entry is string => Boolean(entry));\n}\n\nfunction toTrimmedNonEmptyString(value: unknown) {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction toRequiredString(value: unknown) {\n return toOptionalString(value) ?? \"\";\n}\n\nfunction toBoolean(value: unknown, fallback = false) {\n return typeof value === \"boolean\" ? value : fallback;\n}\n\nfunction toOptionalBoolean(value: unknown) {\n return typeof value === \"boolean\" ? value : undefined;\n}\n\nfunction toTwoslashHtml(value: unknown): TwoslashHtml | undefined {\n return normalizeTwoslashHtml(value);\n}\n\nfunction toPayloadFormat(value: unknown): \"json\" | \"yaml\" | \"text\" | undefined {\n if (value === \"json\" || value === \"yaml\" || value === \"text\") {\n return value;\n }\n\n return undefined;\n}\n\nfunction toArchitectureKind(value: unknown): ArchitectureNodeProps[\"kind\"] | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n if (ARCHITECTURE_NODE_KIND_SET.has(value as NonNullable<ArchitectureNodeProps[\"kind\"]>)) {\n return value as ArchitectureNodeProps[\"kind\"];\n }\n\n return undefined;\n}\n\nfunction toArchitectureZoneId(value: unknown) {\n return toTrimmedNonEmptyString(value);\n}\n\nfunction toArchitectureStatus(value: unknown): ArchitectureNodeProps[\"status\"] | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n if (ARCHITECTURE_NODE_STATUS_SET.has(value as NonNullable<ArchitectureNodeProps[\"status\"]>)) {\n return value as ArchitectureNodeProps[\"status\"];\n }\n\n return undefined;\n}\n\nfunction toArchitectureTier(value: unknown): ArchitectureNodeProps[\"tier\"] | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n if (ARCHITECTURE_NODE_TIER_SET.has(value as NonNullable<ArchitectureNodeProps[\"tier\"]>)) {\n return value as ArchitectureNodeProps[\"tier\"];\n }\n\n return undefined;\n}\n\nfunction toArchitectureInterfaces(value: unknown): ArchitectureInterface[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n const result: ArchitectureInterface[] = [];\n\n for (const rawEntry of value) {\n if (!rawEntry || typeof rawEntry !== \"object\") {\n continue;\n }\n\n const entry = rawEntry as Record<string, unknown>;\n const name = toTrimmedNonEmptyString(entry.name);\n if (!name) {\n continue;\n }\n\n const directionRaw = toTrimmedNonEmptyString(entry.direction);\n const direction =\n directionRaw &&\n ARCHITECTURE_INTERFACE_DIRECTION_SET.has(\n directionRaw as NonNullable<ArchitectureInterface[\"direction\"]>,\n )\n ? (directionRaw as ArchitectureInterface[\"direction\"])\n : undefined;\n\n result.push({\n name,\n protocol: toTrimmedNonEmptyString(entry.protocol),\n direction,\n contract: toTrimmedNonEmptyString(entry.contract),\n auth: toTrimmedNonEmptyString(entry.auth),\n notes: toTrimmedNonEmptyString(entry.notes),\n });\n }\n\n return result;\n}\n\nfunction toArchitectureDataAssets(value: unknown): ArchitectureDataAsset[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n const result: ArchitectureDataAsset[] = [];\n\n for (const rawEntry of value) {\n if (!rawEntry || typeof rawEntry !== \"object\") {\n continue;\n }\n\n const entry = rawEntry as Record<string, unknown>;\n const name = toTrimmedNonEmptyString(entry.name);\n if (!name) {\n continue;\n }\n\n const classificationRaw = toTrimmedNonEmptyString(entry.classification);\n const classification =\n classificationRaw &&\n ARCHITECTURE_DATA_CLASSIFICATION_SET.has(\n classificationRaw as NonNullable<ArchitectureDataAsset[\"classification\"]>,\n )\n ? (classificationRaw as ArchitectureDataAsset[\"classification\"])\n : undefined;\n\n result.push({\n name,\n kind: toTrimmedNonEmptyString(entry.kind),\n classification,\n retention: toTrimmedNonEmptyString(entry.retention),\n notes: toTrimmedNonEmptyString(entry.notes),\n });\n }\n\n return result;\n}\n\nfunction toArchitectureSecurity(value: unknown): ArchitectureSecurity | undefined {\n if (!value || typeof value !== \"object\") {\n return undefined;\n }\n\n const record = value as Record<string, unknown>;\n const security = {\n auth: toTrimmedNonEmptyString(record.auth),\n encryption: toTrimmedNonEmptyString(record.encryption),\n pii: toOptionalBoolean(record.pii),\n threatModel: toTrimmedNonEmptyString(record.threatModel),\n } satisfies ArchitectureSecurity;\n\n if (\n !security.auth &&\n !security.encryption &&\n security.pii === undefined &&\n !security.threatModel\n ) {\n return undefined;\n }\n\n return security;\n}\n\nfunction toArchitectureOperations(value: unknown): ArchitectureOperations | undefined {\n if (!value || typeof value !== \"object\") {\n return undefined;\n }\n\n const record = value as Record<string, unknown>;\n const operations = {\n owner: toTrimmedNonEmptyString(record.owner),\n slo: toTrimmedNonEmptyString(record.slo),\n alert: toTrimmedNonEmptyString(record.alert),\n runbook: toTrimmedNonEmptyString(record.runbook),\n } satisfies ArchitectureOperations;\n\n if (!operations.owner && !operations.slo && !operations.alert && !operations.runbook) {\n return undefined;\n }\n\n return operations;\n}\n\nfunction toArchitectureLinks(value: unknown): ArchitectureLink[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n const result: ArchitectureLink[] = [];\n\n for (const rawEntry of value) {\n if (!rawEntry || typeof rawEntry !== \"object\") {\n continue;\n }\n\n const entry = rawEntry as Record<string, unknown>;\n const label = toTrimmedNonEmptyString(entry.label);\n const href = toTrimmedNonEmptyString(entry.href);\n if (!label || !href) {\n continue;\n }\n\n result.push({\n label,\n href,\n });\n }\n\n return result;\n}\n\nfunction toArchitectureZones(value: unknown): ResolvedArchitectureZone[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n const seen = new Set<string>();\n const result: ResolvedArchitectureZone[] = [];\n\n for (const rawEntry of value) {\n if (!rawEntry || typeof rawEntry !== \"object\") {\n continue;\n }\n\n const entry = rawEntry as Record<string, unknown>;\n const id = toTrimmedNonEmptyString(entry.id);\n const label = toTrimmedNonEmptyString(entry.label);\n if (!id || !label || seen.has(id)) {\n continue;\n }\n\n seen.add(id);\n\n const paddingRaw = entry.padding;\n const padding =\n typeof paddingRaw === \"number\" && Number.isFinite(paddingRaw)\n ? Math.max(28, Math.min(180, Math.round(paddingRaw)))\n : 62;\n\n result.push({\n id,\n label,\n description: toTrimmedNonEmptyString(entry.description),\n color: toTrimmedNonEmptyString(entry.color),\n padding,\n });\n }\n\n return result;\n}\n\nfunction humanizeZoneId(value: string) {\n return value\n .replace(/[-_]+/g, \" \")\n .replace(/\\s+/g, \" \")\n .trim()\n .replace(/(^|\\s)\\w/g, (char) => char.toUpperCase());\n}\n\nfunction resolveZoneColor(index: number, explicitColor?: string) {\n return (\n explicitColor ||\n ARCHITECTURE_ZONE_COLOR_PALETTE[index % ARCHITECTURE_ZONE_COLOR_PALETTE.length] ||\n \"#38bdf8\"\n );\n}\n\nfunction toHexChannel(value: string) {\n return Number.parseInt(value, 16);\n}\n\nfunction hexToRgb(value: string) {\n const hex = value.trim().replace(/^#/, \"\");\n if (hex.length === 3) {\n const r = toHexChannel(`${hex[0]}${hex[0]}`);\n const g = toHexChannel(`${hex[1]}${hex[1]}`);\n const b = toHexChannel(`${hex[2]}${hex[2]}`);\n if ([r, g, b].every((channel) => Number.isFinite(channel))) {\n return { r, g, b };\n }\n\n return undefined;\n }\n\n if (hex.length === 6) {\n const r = toHexChannel(hex.slice(0, 2));\n const g = toHexChannel(hex.slice(2, 4));\n const b = toHexChannel(hex.slice(4, 6));\n if ([r, g, b].every((channel) => Number.isFinite(channel))) {\n return { r, g, b };\n }\n }\n\n return undefined;\n}\n\nfunction withAlpha(color: string, alpha: number) {\n const rgb = hexToRgb(color);\n if (!rgb) {\n return color;\n }\n\n return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`;\n}\n\nfunction toPositiveInteger(value: unknown) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n return undefined;\n }\n\n const asInteger = Math.floor(value);\n return asInteger > 0 ? asInteger : undefined;\n}\n\nfunction parseInlineSourceAnchorLocation(value: string): ParsedAnchorLocation | undefined {\n const trimmed = value.trim();\n if (!trimmed) return undefined;\n\n const matched = SOURCE_ANCHOR_TRAILING_LOCATION_PATTERN.exec(trimmed);\n if (!matched) {\n return {\n path: trimmed,\n };\n }\n\n const rawPath = matched[1]?.trim();\n const rawLine = matched[2];\n const rawColumn = matched[3];\n\n if (!rawPath || !rawLine) {\n return {\n path: trimmed,\n };\n }\n\n const line = Number(rawLine);\n const column = rawColumn ? Number(rawColumn) : undefined;\n\n return {\n path: rawPath,\n line: Number.isFinite(line) && line > 0 ? Math.floor(line) : undefined,\n column: Number.isFinite(column) && (column ?? 0) > 0 ? Math.floor(column as number) : undefined,\n };\n}\n\nfunction toVsCodeFileHref(path: string, line?: number, column?: number) {\n const normalizedPath = path.trim().replace(/\\\\/g, \"/\");\n if (!normalizedPath) return undefined;\n\n const encodedPath = encodeURI(normalizedPath);\n const linePart = line ? `:${line}` : \"\";\n const columnPart = line && column ? `:${column}` : \"\";\n\n return `vscode://file/${encodedPath}${linePart}${columnPart}`;\n}\n\nfunction resolveSourceAnchorHref(\n path: string,\n line?: number,\n column?: number,\n explicitHref?: string,\n) {\n if (explicitHref) {\n return explicitHref;\n }\n\n if (SOURCE_ANCHOR_LINK_PATTERN.test(path)) {\n return path;\n }\n\n return toVsCodeFileHref(path, line, column);\n}\n\nfunction toSourceAnchor(value: unknown): ParsedSourceAnchor | undefined {\n const inlineAnchor = toTrimmedNonEmptyString(value);\n if (inlineAnchor) {\n const parsed = parseInlineSourceAnchorLocation(inlineAnchor);\n\n return {\n label: inlineAnchor,\n href: parsed ? resolveSourceAnchorHref(parsed.path, parsed.line, parsed.column) : undefined,\n };\n }\n\n if (!value || typeof value !== \"object\") {\n return undefined;\n }\n\n const record = value as Record<string, unknown>;\n const path = toTrimmedNonEmptyString(record.path);\n if (!path) {\n return undefined;\n }\n\n const line = toPositiveInteger(record.line);\n const column = toPositiveInteger(record.column);\n const explicitLabel = toTrimmedNonEmptyString(record.label);\n const explicitHref = toTrimmedNonEmptyString(record.href);\n\n const location = [path];\n if (line !== undefined) {\n location.push(String(line));\n\n if (column !== undefined) {\n location.push(String(column));\n }\n }\n\n const label = explicitLabel ?? location.join(\":\");\n\n return {\n label,\n href: resolveSourceAnchorHref(path, line, column, explicitHref),\n };\n}\n\nfunction resolveNodeSourceAnchor(nodeProps: Record<string, unknown>) {\n const explicit = toSourceAnchor(nodeProps.sourceAnchor);\n if (explicit) {\n return explicit;\n }\n\n const fileFallback = toTrimmedNonEmptyString(nodeProps.file);\n if (!fileFallback) {\n return undefined;\n }\n\n return {\n label: fileFallback,\n } satisfies ParsedSourceAnchor;\n}\n\nfunction createCustomNodeContext(\n node: OrderedNodeElement,\n): FlaierCustomNodeContext<Record<string, unknown>> {\n return {\n key: node.key,\n elementType: node.element.type,\n props: node.element.props,\n sourceAnchor: resolveNodeSourceAnchor(node.element.props) as\n | FlaierResolvedSourceAnchor\n | undefined,\n };\n}\n\nfunction toCustomNodeSize(value: FlaierCustomNodeSize | undefined): NodeSize | undefined {\n if (!value) {\n return undefined;\n }\n\n const width = Number(value.width);\n const height = Number(value.height);\n\n if (!Number.isFinite(width) || !Number.isFinite(height)) {\n return undefined;\n }\n\n return {\n width: Math.max(120, Math.round(width)),\n height: Math.max(72, Math.round(height)),\n };\n}\n\nfunction getNodeSummary(node: OrderedNodeElement) {\n const customNode = getCustomNodeDefinition(node.element.type);\n if (customNode?.getSummary) {\n return customNode.getSummary(createCustomNodeContext(node)) ?? \"\";\n }\n\n if (node.element.type === \"CodeNode\") {\n return (\n toTrimmedNonEmptyString(node.element.props.story) ??\n toTrimmedNonEmptyString(node.element.props.comment) ??\n \"\"\n );\n }\n\n if (node.element.type === \"DescriptionNode\") {\n return toTrimmedNonEmptyString(node.element.props.body) ?? \"\";\n }\n\n if (node.element.type === \"DecisionNode\") {\n return (\n toTrimmedNonEmptyString(node.element.props.description) ??\n toTrimmedNonEmptyString(node.element.props.condition) ??\n \"\"\n );\n }\n\n if (node.element.type === \"PayloadNode\") {\n return toTrimmedNonEmptyString(node.element.props.description) ?? \"\";\n }\n\n if (node.element.type === \"ErrorNode\") {\n const message = toTrimmedNonEmptyString(node.element.props.message);\n const cause = toTrimmedNonEmptyString(node.element.props.cause);\n const mitigation = toTrimmedNonEmptyString(node.element.props.mitigation);\n\n return [message, cause ? `Cause: ${cause}` : \"\", mitigation ? `Mitigation: ${mitigation}` : \"\"]\n .filter((value): value is string => typeof value === \"string\" && value.length > 0)\n .join(\" \");\n }\n\n if (node.element.type === \"ArchitectureNode\") {\n const technology = toTrimmedNonEmptyString(node.element.props.technology);\n const description = toTrimmedNonEmptyString(node.element.props.description);\n\n return [technology ? `Technology: ${technology}` : \"\", description ?? \"\"]\n .filter((value): value is string => typeof value === \"string\" && value.length > 0)\n .join(\" \");\n }\n\n return toTrimmedNonEmptyString(node.element.props.description) ?? \"\";\n}\n\nfunction createCustomNodeRenderer(\n elementType: string,\n definition: FlaierCustomNodeDefinition,\n displayName: string,\n) {\n return markRaw(\n defineComponent<NodeProps<FlowNodeData>>({\n name: `Flaier${displayName}Node`,\n props: [\n \"id\",\n \"type\",\n \"selected\",\n \"connectable\",\n \"position\",\n \"dimensions\",\n \"label\",\n \"isValidTargetPos\",\n \"isValidSourcePos\",\n \"parent\",\n \"parentNodeId\",\n \"dragging\",\n \"resizing\",\n \"zIndex\",\n \"targetPosition\",\n \"sourcePosition\",\n \"dragHandle\",\n \"data\",\n \"events\",\n ],\n setup(nodeProps) {\n return () =>\n h(definition.component, {\n ...nodeProps.data?.props,\n active: nodeProps.data?.active,\n nodeKey: nodeProps.data?.key,\n elementType: nodeProps.data?.elementType ?? elementType,\n sourceAnchor: nodeProps.data?.sourceAnchor,\n });\n },\n }),\n );\n}\n\nconst customNodeTypes = computed<NodeTypesObject>(() => {\n return Object.fromEntries(\n Object.entries(customNodes.value).map(([elementType, definition]) => {\n const displayName = elementType.replace(/[^a-z0-9]+/gi, \"\") || \"Custom\";\n\n return [elementType, createCustomNodeRenderer(elementType, definition, displayName)];\n }),\n );\n});\n\nfunction codeNodeTwoslashEnabled(element: SpecElement) {\n if (element.type !== \"CodeNode\") return false;\n\n if (!normalizeTwoslashLanguage(toOptionalString(element.props.language))) {\n return false;\n }\n\n if (!hasTwoslashHtml(toTwoslashHtml(element.props.twoslashHtml))) {\n return false;\n }\n\n const requested = toOptionalBoolean(element.props.twoslash);\n if (requested === true) return true;\n if (requested === false) return false;\n\n const variants = [\n toRequiredString(element.props.code),\n ...toMagicMoveSteps(element.props.magicMoveSteps).map((step) => step.code),\n ];\n\n return variants.some((code) => hasTwoslashHints(code));\n}\n\nfunction toPositiveNumber(value: unknown, fallback: number, min = 1) {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return Math.max(min, Math.floor(value));\n }\n\n return fallback;\n}\n\nfunction toMagicMoveSteps(value: unknown): MagicMoveStep[] {\n if (!Array.isArray(value)) return [];\n\n return value\n .filter((item): item is MagicMoveStep => {\n if (!item || typeof item !== \"object\") return false;\n\n const record = item as Record<string, unknown>;\n if (typeof record.code !== \"string\") return false;\n\n const optionalKeys: Array<\"title\" | \"comment\" | \"story\" | \"speaker\"> = [\n \"title\",\n \"comment\",\n \"story\",\n \"speaker\",\n ];\n\n return optionalKeys.every((key) => {\n const current = record[key];\n return current === undefined || typeof current === \"string\";\n });\n })\n .map((item) => ({\n code: item.code,\n title: toOptionalString(item.title),\n comment: toOptionalString(item.comment),\n story: toOptionalString(item.story),\n speaker: toOptionalString(item.speaker),\n }));\n}\n\nfunction toTransitionKind(value: unknown): EdgeTransitionKind | undefined {\n if (typeof value !== \"string\") return undefined;\n return EDGE_TRANSITION_KIND_SET.has(value as EdgeTransitionKind)\n ? (value as EdgeTransitionKind)\n : undefined;\n}\n\nfunction toTransitionTransport(value: unknown): \"sync\" | \"async\" | undefined {\n if (typeof value !== \"string\") return undefined;\n return EDGE_TRANSITION_TRANSPORT_SET.has(value) ? (value as \"sync\" | \"async\") : undefined;\n}\n\nfunction toTransitionCriticality(value: unknown): \"low\" | \"medium\" | \"high\" | undefined {\n if (typeof value !== \"string\") return undefined;\n return EDGE_TRANSITION_CRITICALITY_SET.has(value)\n ? (value as \"low\" | \"medium\" | \"high\")\n : undefined;\n}\n\nfunction toTransitions(value: unknown): ParsedTransition[] {\n if (!Array.isArray(value)) return [];\n\n return value\n .filter((item): item is Record<string, unknown> => {\n if (!item || typeof item !== \"object\") return false;\n if (!toOptionalString(item.to)) return false;\n\n const label = item.label;\n const description = item.description;\n const kind = item.kind;\n const protocol = item.protocol;\n const transport = item.transport;\n const auth = item.auth;\n const contract = item.contract;\n const criticality = item.criticality;\n\n if (label !== undefined && typeof label !== \"string\") return false;\n if (description !== undefined && typeof description !== \"string\") return false;\n if (kind !== undefined && !toTransitionKind(kind)) return false;\n if (protocol !== undefined && typeof protocol !== \"string\") return false;\n if (transport !== undefined && !toTransitionTransport(transport)) return false;\n if (auth !== undefined && typeof auth !== \"string\") return false;\n if (contract !== undefined && typeof contract !== \"string\") return false;\n if (criticality !== undefined && !toTransitionCriticality(criticality)) return false;\n\n return true;\n })\n .map((item) => ({\n to: toRequiredString(item.to),\n label: toOptionalString(item.label),\n description: toOptionalString(item.description),\n kind: toTransitionKind(item.kind),\n protocol: toOptionalString(item.protocol),\n transport: toTransitionTransport(item.transport),\n auth: toOptionalString(item.auth),\n contract: toOptionalString(item.contract),\n criticality: toTransitionCriticality(item.criticality),\n }));\n}\n\nfunction resolveTransitionEdgeLabel(transition?: ParsedTransition) {\n if (!transition) {\n return undefined;\n }\n\n const metadataParts = [transition.protocol, transition.transport, transition.criticality].filter(\n (value): value is string => Boolean(value),\n );\n\n if (transition.label) {\n return metadataParts.length > 0\n ? `${transition.label} (${metadataParts.join(\" | \")})`\n : transition.label;\n }\n\n if (metadataParts.length > 0) {\n return metadataParts.join(\" | \");\n }\n\n return undefined;\n}\n\nfunction mergeOutgoingTargets(primary: string[], secondary: string[]) {\n const merged: string[] = [];\n const seen = new Set<string>();\n\n for (const target of [...primary, ...secondary]) {\n if (!target || seen.has(target)) continue;\n\n seen.add(target);\n merged.push(target);\n }\n\n return merged;\n}\n\nfunction getNodeFrameCount(element: SpecElement) {\n if (element.type !== \"CodeNode\") return 1;\n\n const magicMoveSteps = toMagicMoveSteps(element.props.magicMoveSteps);\n const baseSteps = Math.max(1, magicMoveSteps.length);\n\n if (magicMoveSteps.length > 0 && codeNodeTwoslashEnabled(element)) {\n return baseSteps + 1;\n }\n\n return baseSteps;\n}\n\nfunction getCodeNodeMaxLines(element: SpecElement) {\n const rootCodeLines = toRequiredString(element.props.code).split(\"\\n\").length;\n const stepLines = toMagicMoveSteps(element.props.magicMoveSteps).map(\n (step) => step.code.split(\"\\n\").length,\n );\n\n return Math.max(rootCodeLines, ...stepLines);\n}\n\nfunction getCodeNodeMaxLineLength(element: SpecElement) {\n const variants = [\n toRequiredString(element.props.code),\n ...toMagicMoveSteps(element.props.magicMoveSteps).map((step) => step.code),\n ];\n\n return variants.reduce((max, code) => {\n const lineMax = code\n .split(\"\\n\")\n .reduce((lineLengthMax, line) => Math.max(lineLengthMax, line.length), 0);\n\n return Math.max(max, lineMax);\n }, 0);\n}\n\nfunction estimateWrappedLines(text: string, charsPerLine = 48) {\n return text\n .split(\"\\n\")\n .reduce((total, line) => total + Math.max(1, Math.ceil(line.length / charsPerLine)), 0);\n}\n\nfunction getCodeNodeWrappedLines(element: SpecElement, charsPerLine = 44) {\n const variants = [\n toRequiredString(element.props.code),\n ...toMagicMoveSteps(element.props.magicMoveSteps).map((step) => step.code),\n ];\n\n return variants.reduce((max, code) => {\n return Math.max(max, estimateWrappedLines(code, charsPerLine));\n }, 1);\n}\n\nfunction hasCodeNodeStoryMeta(element: SpecElement) {\n return toMagicMoveSteps(element.props.magicMoveSteps).some((step) => step.title || step.speaker);\n}\n\nfunction getCodeNodeStoryLines(element: SpecElement) {\n const variants = [\n toOptionalString(element.props.story),\n toOptionalString(element.props.comment),\n ...toMagicMoveSteps(element.props.magicMoveSteps).flatMap((step) => [step.story, step.comment]),\n ].filter((value): value is string => typeof value === \"string\" && value.length > 0);\n\n if (variants.length === 0) return 0;\n\n return variants.reduce((max, current) => Math.max(max, estimateWrappedLines(current)), 1);\n}\n\nfunction estimateNodeTextLines(value: unknown, charsPerLine: number) {\n const text = toOptionalString(value);\n if (!text) return 0;\n return estimateWrappedLines(text, charsPerLine);\n}\n\nfunction estimateCodeNodeSize(element: SpecElement): NodeSize {\n const maxLineLength = getCodeNodeMaxLineLength(element);\n const nodeWidth = estimateCodeNodeWidth(maxLineLength);\n const codeCharsPerLine = estimateCodeNodeCharsPerLine(nodeWidth);\n const autoWrapEnabled = maxLineLength > CODE_NODE_MAX_INLINE_CHARS;\n const wrapEnabled = toBoolean(element.props.wrapLongLines) || autoWrapEnabled;\n\n const codeLines = wrapEnabled\n ? getCodeNodeWrappedLines(element, codeCharsPerLine)\n : getCodeNodeMaxLines(element);\n const storyLines = getCodeNodeStoryLines(element);\n const storyHasMeta = hasCodeNodeStoryMeta(element);\n\n const codeViewportHeight = wrapEnabled\n ? Math.min(400, Math.max(190, 72 + codeLines * 16))\n : Math.min(340, Math.max(160, 84 + codeLines * 17));\n\n const storyViewportHeight =\n storyLines > 0 ? Math.min(220, Math.max(88, (storyHasMeta ? 56 : 34) + storyLines * 18)) : 0;\n\n return {\n width: nodeWidth,\n height: Math.min(760, Math.max(230, 42 + codeViewportHeight + storyViewportHeight + 14)),\n };\n}\n\nfunction estimateNodeSize(node: OrderedNodeElement): NodeSize {\n const { element } = node;\n const customNode = getCustomNodeDefinition(element.type);\n\n if (customNode?.estimateSize) {\n const customSize = toCustomNodeSize(customNode.estimateSize(createCustomNodeContext(node)));\n if (customSize) {\n return customSize;\n }\n }\n\n if (customNode) {\n return {\n width: 240,\n height: 120,\n };\n }\n\n if (element.type === \"ArchitectureNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 28));\n const technologyLines = estimateNodeTextLines(element.props.technology, 30);\n const ownerLines = estimateNodeTextLines(element.props.owner, 30);\n const runtimeLines = estimateNodeTextLines(element.props.runtime, 30);\n const descriptionLines = estimateNodeTextLines(element.props.description, 34);\n const capabilityCount = Math.min(4, toStringArray(element.props.capabilities).length);\n const tagCount = Math.min(4, toStringArray(element.props.tags).length);\n const chipRows =\n (capabilityCount > 0 ? Math.ceil(capabilityCount / 2) : 0) + (tagCount > 0 ? 1 : 0);\n const metaRows =\n toArchitectureStatus(element.props.status) || toArchitectureTier(element.props.tier) ? 1 : 0;\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 270,\n height: Math.min(\n 460,\n Math.max(\n 144,\n 58 +\n labelLines * 19 +\n technologyLines * 14 +\n ownerLines * 12 +\n runtimeLines * 12 +\n descriptionLines * 15 +\n metaRows * 16 +\n chipRows * 18 +\n anchorHeight,\n ),\n ),\n };\n }\n\n if (element.type === \"CodeNode\") {\n return estimateCodeNodeSize(element);\n }\n\n if (element.type === \"TriggerNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 24));\n const descriptionLines = estimateNodeTextLines(element.props.description, 30);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 220,\n height: Math.min(\n 300,\n Math.max(100, 46 + labelLines * 18 + descriptionLines * 15 + anchorHeight),\n ),\n };\n }\n\n if (element.type === \"DecisionNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 26));\n const conditionLines = estimateNodeTextLines(element.props.condition, 34);\n const descriptionLines = estimateNodeTextLines(element.props.description, 34);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 250,\n height: Math.min(\n 360,\n Math.max(\n 122,\n 50 + labelLines * 18 + conditionLines * 16 + descriptionLines * 15 + anchorHeight,\n ),\n ),\n };\n }\n\n if (element.type === \"PayloadNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 32));\n const descriptionLines = estimateNodeTextLines(element.props.description, 34);\n const beforeLines = estimateNodeTextLines(element.props.before, 40);\n const afterLines = estimateNodeTextLines(element.props.after, 40);\n const payloadLines = estimateNodeTextLines(element.props.payload, 40);\n const bodyLines = Math.max(payloadLines, beforeLines + afterLines);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 300,\n height: Math.min(\n 540,\n Math.max(160, 60 + labelLines * 18 + descriptionLines * 14 + bodyLines * 10 + anchorHeight),\n ),\n };\n }\n\n if (element.type === \"ErrorNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 30));\n const messageLines = Math.max(1, estimateNodeTextLines(element.props.message, 34));\n const causeLines = estimateNodeTextLines(element.props.cause, 34);\n const mitigationLines = estimateNodeTextLines(element.props.mitigation, 34);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 280,\n height: Math.min(\n 440,\n Math.max(\n 140,\n 58 +\n labelLines * 18 +\n messageLines * 16 +\n causeLines * 15 +\n mitigationLines * 15 +\n anchorHeight,\n ),\n ),\n };\n }\n\n if (element.type === \"DescriptionNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 26));\n const bodyLines = Math.max(1, estimateNodeTextLines(element.props.body, 30));\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 240,\n height: Math.min(360, Math.max(118, 44 + labelLines * 18 + bodyLines * 16 + anchorHeight)),\n };\n }\n\n if (element.type === \"LinkNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 24));\n const descriptionLines = estimateNodeTextLines(element.props.description, 30);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 220,\n height: Math.min(\n 300,\n Math.max(98, 42 + labelLines * 18 + descriptionLines * 15 + anchorHeight),\n ),\n };\n }\n\n return {\n width: 240,\n height: 120,\n };\n}\n\nconst selectedBranchByNode = ref<Record<string, string>>({});\nconst pathFrames = ref<TimelineFrame[]>([]);\n\nfunction createFramesForNode(nodeKey: string): TimelineFrame[] {\n const node = orderedNodeByKey.value[nodeKey];\n if (!node) return [];\n\n const totalLocalSteps = getNodeFrameCount(node.element);\n\n return Array.from({ length: totalLocalSteps }, (_, localStep) => ({\n nodeIndex: node.index,\n nodeKey,\n localStep,\n totalLocalSteps,\n }));\n}\n\nfunction resolveNextNode(nodeKey: string, options: string[]) {\n const selected = selectedBranchByNode.value[nodeKey];\n if (selected && options.includes(selected)) {\n return selected;\n }\n\n return options[0];\n}\n\nfunction buildGuidedPath(startKey: string, maxFrames = 450): TimelineFrame[] {\n const frames: TimelineFrame[] = [];\n const visitedEdges = new Map<string, number>();\n let currentKey: string | undefined = startKey;\n\n while (currentKey && frames.length < maxFrames) {\n const nodeFrames = createFramesForNode(currentKey);\n if (nodeFrames.length === 0) break;\n\n frames.push(...nodeFrames);\n\n const options = outgoingNodeKeys.value[currentKey] ?? [];\n if (options.length === 0) break;\n\n const nextKey = resolveNextNode(currentKey, options);\n if (!nextKey) break;\n\n const edgeKey = `${currentKey}->${nextKey}`;\n const edgeVisits = (visitedEdges.get(edgeKey) ?? 0) + 1;\n visitedEdges.set(edgeKey, edgeVisits);\n if (edgeVisits > 2) break;\n\n currentKey = nextKey;\n }\n\n return frames;\n}\n\nfunction findNearestFrameIndex(frames: TimelineFrame[], nodeKey: string, anchor = 0) {\n let bestIndex = -1;\n let bestDistance = Number.POSITIVE_INFINITY;\n\n for (let index = 0; index < frames.length; index += 1) {\n if (frames[index]?.nodeKey !== nodeKey) continue;\n\n const distance = Math.abs(index - anchor);\n if (distance < bestDistance) {\n bestDistance = distance;\n bestIndex = index;\n }\n }\n\n return bestIndex;\n}\n\nfunction sortOptionsForTraversal(sourceKey: string, options: string[]) {\n const selected = selectedBranchByNode.value[sourceKey];\n\n return [...options].sort((a, b) => {\n const aSelected = a === selected;\n const bSelected = b === selected;\n\n if (aSelected !== bSelected) {\n return aSelected ? -1 : 1;\n }\n\n const aIndex = orderedNodeByKey.value[a]?.index ?? Number.MAX_SAFE_INTEGER;\n const bIndex = orderedNodeByKey.value[b]?.index ?? Number.MAX_SAFE_INTEGER;\n\n return aIndex - bIndex;\n });\n}\n\nfunction findPathKeysToNode(startKey: string, targetKey: string) {\n if (startKey === targetKey) {\n return [startKey];\n }\n\n const queue: Array<{ key: string; path: string[]; depth: number }> = [\n {\n key: startKey,\n path: [startKey],\n depth: 0,\n },\n ];\n\n const visitedDepth = new Map<string, number>([[startKey, 0]]);\n const maxDepth = Math.max(8, orderedNodeElements.value.length + 8);\n const maxIterations = Math.max(\n 80,\n orderedNodeElements.value.length * orderedNodeElements.value.length * 2,\n );\n let guard = 0;\n\n while (queue.length > 0 && guard < maxIterations) {\n guard += 1;\n\n const current = queue.shift();\n if (!current) continue;\n if (current.depth >= maxDepth) continue;\n\n const options = sortOptionsForTraversal(current.key, outgoingNodeKeys.value[current.key] ?? []);\n\n for (const option of options) {\n if (!orderedNodeByKey.value[option]) continue;\n\n const nextDepth = current.depth + 1;\n if (option === targetKey) {\n return [...current.path, option];\n }\n\n const knownDepth = visitedDepth.get(option);\n if (knownDepth !== undefined && knownDepth <= nextDepth) {\n continue;\n }\n\n visitedDepth.set(option, nextDepth);\n queue.push({\n key: option,\n path: [...current.path, option],\n depth: nextDepth,\n });\n }\n }\n\n return null;\n}\n\nfunction applyBranchSelectionsForPath(pathKeys: string[]) {\n if (pathKeys.length < 2) return;\n\n const nextSelected = { ...selectedBranchByNode.value };\n\n for (let index = 0; index < pathKeys.length - 1; index += 1) {\n const source = pathKeys[index];\n const target = pathKeys[index + 1];\n if (!source || !target) continue;\n\n const options = outgoingNodeKeys.value[source] ?? [];\n if (options.length > 1 && options.includes(target)) {\n nextSelected[source] = target;\n }\n }\n\n selectedBranchByNode.value = nextSelected;\n}\n\nconst totalSteps = computed(() => pathFrames.value.length);\nconst maxStepIndex = computed(() => Math.max(0, totalSteps.value - 1));\n\nconst { set } = useStateStore();\nconst currentStepState = useStateValue<number>(\"/currentStep\");\nconst playingState = useStateValue<boolean>(\"/playing\");\n\nfunction clampStep(value: number) {\n if (!Number.isFinite(value)) return 0;\n const step = Math.floor(value);\n return Math.max(0, Math.min(step, maxStepIndex.value));\n}\n\nconst currentStep = computed<number>({\n get() {\n return clampStep(Number(currentStepState.value ?? 0));\n },\n set(value: number) {\n set(\"/currentStep\", clampStep(value));\n },\n});\n\nconst playing = computed<boolean>({\n get() {\n return Boolean(playingState.value ?? false);\n },\n set(value: boolean) {\n set(\"/playing\", value);\n },\n});\n\nwatch(\n [startNodeKey, orderedNodeElements, isArchitectureMode],\n ([start, , architectureMode]) => {\n if (architectureMode) {\n selectedBranchByNode.value = {};\n pathFrames.value = [];\n currentStep.value = 0;\n playing.value = false;\n return;\n }\n\n selectedBranchByNode.value = {};\n\n if (!start) {\n pathFrames.value = [];\n currentStep.value = 0;\n return;\n }\n\n const built = buildGuidedPath(start);\n pathFrames.value = built.length > 0 ? built : createFramesForNode(start);\n currentStep.value = clampStep(Number(currentStepState.value ?? 0));\n },\n { immediate: true },\n);\n\nwatch(totalSteps, () => {\n currentStep.value = clampStep(currentStep.value);\n});\n\nconst intervalMs = computed(() => {\n const value = Number(runtime.interval.value);\n if (!Number.isFinite(value) || value <= 0) return 3000;\n return Math.max(250, Math.floor(value));\n});\n\nlet timer: ReturnType<typeof setInterval> | null = null;\n\nfunction clearTimer() {\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n}\n\nfunction next() {\n if (isArchitectureMode.value) {\n return false;\n }\n\n if (currentStep.value >= totalSteps.value - 1) {\n return false;\n }\n\n currentStep.value += 1;\n return true;\n}\n\nwatch(\n [playing, totalSteps, intervalMs],\n ([isPlaying, steps, interval]) => {\n clearTimer();\n\n if (!isPlaying || steps <= 1) return;\n\n timer = setInterval(() => {\n const advanced = next();\n if (!advanced) {\n playing.value = false;\n }\n }, interval);\n },\n { immediate: true },\n);\n\nfunction prev() {\n if (isArchitectureMode.value) {\n return;\n }\n\n if (currentStep.value > 0) {\n currentStep.value -= 1;\n }\n}\n\nfunction goTo(step: number) {\n if (isArchitectureMode.value) {\n return;\n }\n\n currentStep.value = clampStep(step);\n}\n\nfunction togglePlay() {\n if (isArchitectureMode.value) {\n playing.value = false;\n return;\n }\n\n if (totalSteps.value <= 1) {\n playing.value = false;\n return;\n }\n\n playing.value = !playing.value;\n}\n\nconst activeFrame = computed(() => pathFrames.value[currentStep.value]);\nconst nextPlannedNodeKey = computed(() => pathFrames.value[currentStep.value + 1]?.nodeKey);\n\nfunction jumpToNode(nodeKey: string) {\n if (!orderedNodeByKey.value[nodeKey]) return;\n\n playing.value = false;\n\n const existingIndex = findNearestFrameIndex(pathFrames.value, nodeKey, currentStep.value);\n if (existingIndex >= 0) {\n currentStep.value = existingIndex;\n return;\n }\n\n const start = startNodeKey.value;\n if (!start) {\n const standaloneFrames = createFramesForNode(nodeKey);\n if (standaloneFrames.length === 0) return;\n\n pathFrames.value = standaloneFrames;\n currentStep.value = 0;\n return;\n }\n\n const pathKeys = findPathKeysToNode(start, nodeKey);\n if (pathKeys) {\n applyBranchSelectionsForPath(pathKeys);\n }\n\n const rebuiltFrames = buildGuidedPath(start);\n pathFrames.value = rebuiltFrames.length > 0 ? rebuiltFrames : createFramesForNode(start);\n\n const rebuiltIndex = findNearestFrameIndex(pathFrames.value, nodeKey, currentStep.value);\n if (rebuiltIndex >= 0) {\n currentStep.value = rebuiltIndex;\n return;\n }\n\n const standaloneFrames = createFramesForNode(nodeKey);\n if (standaloneFrames.length === 0) return;\n\n pathFrames.value = standaloneFrames;\n currentStep.value = 0;\n}\n\nconst resolvedLayoutEngine = computed<\"dagre\" | \"manual\">(() => {\n return props.layoutEngine === \"manual\" ? \"manual\" : DEFAULT_LAYOUT_ENGINE;\n});\n\nconst resolvedLayoutRankSep = computed(() => {\n const fallback =\n props.direction === \"vertical\"\n ? DEFAULT_DAGRE_RANK_SEP_VERTICAL\n : DEFAULT_DAGRE_RANK_SEP_HORIZONTAL;\n\n return toPositiveNumber(props.layoutRankSep, fallback, 80);\n});\n\nconst resolvedLayoutNodeSep = computed(() => {\n const fallback =\n props.direction === \"vertical\"\n ? DEFAULT_DAGRE_NODE_SEP_VERTICAL\n : DEFAULT_DAGRE_NODE_SEP_HORIZONTAL;\n\n return toPositiveNumber(props.layoutNodeSep, fallback, 40);\n});\n\nconst resolvedLayoutEdgeSep = computed(() => {\n return toPositiveNumber(props.layoutEdgeSep, DEFAULT_DAGRE_EDGE_SEP, 8);\n});\n\nfunction createFallbackLayoutPositions(\n nodes: OrderedNodeElement[],\n rankGap = DEFAULT_FALLBACK_GAP,\n) {\n const mainGap = Math.max(80, rankGap);\n const positions: Record<string, { x: number; y: number }> = {};\n\n for (const node of nodes) {\n if (props.direction === \"vertical\") {\n positions[node.key] = { x: 0, y: node.index * mainGap };\n continue;\n }\n\n positions[node.key] = { x: node.index * mainGap, y: 0 };\n }\n\n return positions;\n}\n\nfunction normalizePositions(positions: Record<string, { x: number; y: number }>) {\n if (Object.keys(positions).length === 0) {\n return positions;\n }\n\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n\n for (const position of Object.values(positions)) {\n minX = Math.min(minX, position.x);\n minY = Math.min(minY, position.y);\n }\n\n for (const key of Object.keys(positions)) {\n const currentPosition = positions[key];\n if (!currentPosition) continue;\n\n positions[key] = {\n x: currentPosition.x - minX,\n y: currentPosition.y - minY,\n };\n }\n\n return positions;\n}\n\nfunction createManualLayoutPositions(\n orderedNodes: OrderedNodeElement[],\n rankGap: number,\n laneGap: number,\n) {\n if (orderedNodes.length === 0) return {};\n\n const depthByKey: Record<string, number> = {};\n for (const node of orderedNodes) {\n depthByKey[node.key] = Number.NEGATIVE_INFINITY;\n }\n\n const startKey = startNodeKey.value ?? orderedNodes[0]?.key;\n if (!startKey) {\n return createFallbackLayoutPositions(orderedNodes, rankGap);\n }\n\n depthByKey[startKey] = 0;\n\n const queue: string[] = [startKey];\n const maxDepth = Math.max(0, orderedNodes.length - 1);\n let guard = 0;\n const maxIterations = Math.max(24, orderedNodes.length * orderedNodes.length);\n\n while (queue.length > 0 && guard < maxIterations) {\n guard += 1;\n\n const key = queue.shift();\n if (!key) continue;\n\n const baseDepth = depthByKey[key] ?? Number.NEGATIVE_INFINITY;\n if (!Number.isFinite(baseDepth)) continue;\n\n for (const target of outgoingNodeKeys.value[key] ?? []) {\n if (!(target in depthByKey)) continue;\n\n const candidateDepth = Math.min(maxDepth, baseDepth + 1);\n const currentDepth = depthByKey[target] ?? Number.NEGATIVE_INFINITY;\n\n if (candidateDepth > currentDepth) {\n depthByKey[target] = candidateDepth;\n queue.push(target);\n }\n }\n }\n\n let fallbackDepth = 0;\n for (const node of orderedNodes) {\n if (Number.isFinite(depthByKey[node.key])) continue;\n\n depthByKey[node.key] = Math.min(maxDepth, fallbackDepth);\n fallbackDepth += 1;\n }\n\n const layers: Record<number, string[]> = {};\n for (const node of orderedNodes) {\n const depth = depthByKey[node.key] ?? 0;\n if (!layers[depth]) {\n layers[depth] = [];\n }\n\n layers[depth].push(node.key);\n }\n\n const laneByKey: Record<string, number> = {};\n const sortedDepths = Object.keys(layers)\n .map(Number)\n .sort((a, b) => a - b);\n\n for (const depth of sortedDepths) {\n const layerKeys = [...(layers[depth] ?? [])];\n\n layerKeys.sort((a, b) => {\n const aParents = (incomingNodeKeys.value[a] ?? []).filter((parent) => {\n const parentDepth = depthByKey[parent] ?? Number.NEGATIVE_INFINITY;\n return Number.isFinite(parentDepth) && parentDepth < depth;\n });\n const bParents = (incomingNodeKeys.value[b] ?? []).filter((parent) => {\n const parentDepth = depthByKey[parent] ?? Number.NEGATIVE_INFINITY;\n return Number.isFinite(parentDepth) && parentDepth < depth;\n });\n\n const aAnchor =\n aParents.length > 0\n ? aParents.reduce((sum, parent) => sum + (laneByKey[parent] ?? 0), 0) / aParents.length\n : 0;\n const bAnchor =\n bParents.length > 0\n ? bParents.reduce((sum, parent) => sum + (laneByKey[parent] ?? 0), 0) / bParents.length\n : 0;\n\n if (aAnchor === bAnchor) {\n const aIndex = orderedNodeByKey.value[a]?.index ?? 0;\n const bIndex = orderedNodeByKey.value[b]?.index ?? 0;\n return aIndex - bIndex;\n }\n\n return aAnchor - bAnchor;\n });\n\n const count = layerKeys.length;\n layerKeys.forEach((key, index) => {\n laneByKey[key] = (index - (count - 1) / 2) * laneGap;\n });\n }\n\n const positions: Record<string, { x: number; y: number }> = {};\n\n for (const node of orderedNodes) {\n const depth = depthByKey[node.key] ?? 0;\n const lane = laneByKey[node.key] ?? 0;\n\n if (props.direction === \"vertical\") {\n positions[node.key] = {\n x: Math.round(lane),\n y: Math.round(depth * rankGap),\n };\n continue;\n }\n\n positions[node.key] = {\n x: Math.round(depth * rankGap),\n y: Math.round(lane),\n };\n }\n\n return normalizePositions(positions);\n}\n\nconst nodeSizes = computed<Record<string, NodeSize>>(() => {\n const sizes: Record<string, NodeSize> = {};\n\n for (const node of orderedNodeElements.value) {\n sizes[node.key] = estimateNodeSize(node);\n }\n\n return sizes;\n});\n\nconst architectureZoneDefinitions = computed<ResolvedArchitectureZone[]>(() => {\n if (!isArchitectureMode.value) {\n return [];\n }\n\n const rootZones = toArchitectureZones(props.zones ?? rootElement.value?.props.zones);\n const byId = new Map<string, ResolvedArchitectureZone>();\n\n for (const zone of rootZones) {\n byId.set(zone.id, zone);\n }\n\n for (const node of orderedNodeElements.value) {\n const zoneId = toArchitectureZoneId(node.element.props.zone);\n if (!zoneId || byId.has(zoneId)) {\n continue;\n }\n\n byId.set(zoneId, {\n id: zoneId,\n label: humanizeZoneId(zoneId),\n padding: 62,\n });\n }\n\n return Array.from(byId.values());\n});\n\nconst architectureZoneLabelById = computed<Record<string, string>>(() => {\n const map: Record<string, string> = {};\n\n for (const zone of architectureZoneDefinitions.value) {\n map[zone.id] = zone.label;\n }\n\n return map;\n});\n\nconst architectureNodeZoneByKey = computed<Record<string, string>>(() => {\n const map: Record<string, string> = {};\n\n for (const node of orderedNodeElements.value) {\n const zoneId = toArchitectureZoneId(node.element.props.zone);\n if (!zoneId) {\n continue;\n }\n\n map[node.key] = zoneId;\n }\n\n return map;\n});\n\nconst architectureZoneOverlays = computed<ArchitectureZoneOverlay[]>(() => {\n if (!isArchitectureMode.value) {\n return [];\n }\n\n const rawOverlays: Array<{\n id: string;\n label: string;\n description?: string;\n color: string;\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n padding: number;\n nodeCount: number;\n sourceIndex: number;\n }> = [];\n\n architectureZoneDefinitions.value.forEach((zone, index) => {\n const members = orderedNodeElements.value.filter(\n (node) => architectureNodeZoneByKey.value[node.key] === zone.id,\n );\n if (members.length === 0) {\n return;\n }\n\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n\n for (const member of members) {\n const position = layoutPositions.value[member.key];\n if (!position) {\n continue;\n }\n\n const size = nodeSizes.value[member.key] ?? { width: 240, height: 120 };\n\n minX = Math.min(minX, position.x);\n minY = Math.min(minY, position.y);\n maxX = Math.max(maxX, position.x + size.width);\n maxY = Math.max(maxY, position.y + size.height);\n }\n\n if (\n !Number.isFinite(minX) ||\n !Number.isFinite(minY) ||\n !Number.isFinite(maxX) ||\n !Number.isFinite(maxY)\n ) {\n return;\n }\n\n const padding = zone.padding;\n rawOverlays.push({\n id: zone.id,\n label: zone.label,\n description: zone.description,\n color: resolveZoneColor(index, zone.color),\n minX,\n minY,\n maxX,\n maxY,\n padding,\n nodeCount: members.length,\n sourceIndex: index,\n });\n });\n\n const provisionalBounds = rawOverlays.map((overlay) => ({\n id: overlay.id,\n x: overlay.minX - overlay.padding,\n y: overlay.minY - overlay.padding,\n width: overlay.maxX - overlay.minX + overlay.padding * 2,\n height: overlay.maxY - overlay.minY + overlay.padding * 2,\n }));\n\n const nestingDepthById = new Map<string, number>();\n const containsNestedZoneById = new Map<string, boolean>();\n\n for (const current of provisionalBounds) {\n const depth = provisionalBounds.reduce((count, candidate) => {\n if (candidate.id === current.id) {\n return count;\n }\n\n const containsCurrent =\n candidate.x <= current.x + 12 &&\n candidate.y <= current.y + 12 &&\n candidate.x + candidate.width >= current.x + current.width - 12 &&\n candidate.y + candidate.height >= current.y + current.height - 12;\n\n return containsCurrent ? count + 1 : count;\n }, 0);\n\n nestingDepthById.set(current.id, depth);\n containsNestedZoneById.set(\n current.id,\n provisionalBounds.some((candidate) => {\n if (candidate.id === current.id) {\n return false;\n }\n\n return (\n current.x <= candidate.x + 12 &&\n current.y <= candidate.y + 12 &&\n current.x + current.width >= candidate.x + candidate.width - 12 &&\n current.y + current.height >= candidate.y + candidate.height - 12\n );\n }),\n );\n }\n\n const overlappingZoneIds = new Set<string>();\n for (let index = 0; index < provisionalBounds.length; index += 1) {\n const current = provisionalBounds[index];\n if (!current) {\n continue;\n }\n\n for (let compareIndex = index + 1; compareIndex < provisionalBounds.length; compareIndex += 1) {\n const candidate = provisionalBounds[compareIndex];\n if (!candidate) {\n continue;\n }\n\n const overlaps =\n current.x < candidate.x + candidate.width &&\n current.x + current.width > candidate.x &&\n current.y < candidate.y + candidate.height &&\n current.y + current.height > candidate.y;\n\n if (!overlaps) {\n continue;\n }\n\n overlappingZoneIds.add(current.id);\n overlappingZoneIds.add(candidate.id);\n }\n }\n\n const labelLaneById = new Map<string, number>();\n const placedLabelBoxes: Array<{\n id: string;\n lane: number;\n x: number;\n y: number;\n width: number;\n height: number;\n }> = [];\n const sortedForLabelPlacement = rawOverlays\n .map((overlay) => {\n const sidePadding = Math.max(overlay.padding, ARCHITECTURE_ZONE_MIN_CONTENT_PADDING);\n const descriptionReserve = overlay.description\n ? ARCHITECTURE_ZONE_DESCRIPTION_HEIGHT + ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP\n : 0;\n const topPadding =\n sidePadding +\n ARCHITECTURE_ZONE_LABEL_HEIGHT +\n ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP +\n descriptionReserve;\n const width = Math.min(\n Math.max(132, overlay.label.length * 7 + String(overlay.nodeCount).length * 14 + 86),\n Math.max(148, overlay.maxX - overlay.minX + sidePadding * 2 - 28),\n );\n\n return {\n id: overlay.id,\n x: overlay.minX - sidePadding + 16,\n y: overlay.minY - topPadding + ARCHITECTURE_ZONE_LABEL_TOP,\n width,\n };\n })\n .sort((a, b) => {\n if (a.y !== b.y) {\n return a.y - b.y;\n }\n\n return a.x - b.x;\n });\n\n for (const labelCandidate of sortedForLabelPlacement) {\n let lane = 0;\n\n while (\n placedLabelBoxes.some((placed) => {\n if (placed.lane !== lane) {\n return false;\n }\n\n const currentY = labelCandidate.y + lane * ARCHITECTURE_ZONE_NESTED_LABEL_STEP;\n return (\n labelCandidate.x < placed.x + placed.width &&\n labelCandidate.x + labelCandidate.width > placed.x &&\n currentY < placed.y + placed.height &&\n currentY + ARCHITECTURE_ZONE_LABEL_HEIGHT > placed.y\n );\n })\n ) {\n lane += 1;\n }\n\n labelLaneById.set(labelCandidate.id, lane);\n placedLabelBoxes.push({\n id: labelCandidate.id,\n lane,\n x: labelCandidate.x,\n y: labelCandidate.y + lane * ARCHITECTURE_ZONE_NESTED_LABEL_STEP,\n width: labelCandidate.width,\n height: ARCHITECTURE_ZONE_LABEL_HEIGHT,\n });\n }\n\n const maxLabelLane = placedLabelBoxes.reduce((max, placed) => Math.max(max, placed.lane), 0);\n\n return rawOverlays\n .map((overlay) => {\n const nestingDepth = nestingDepthById.get(overlay.id) ?? 0;\n const nestedZoneGap = containsNestedZoneById.get(overlay.id)\n ? ARCHITECTURE_ZONE_CONTAINED_ZONE_GAP\n : 0;\n const baseSidePadding = Math.max(overlay.padding, ARCHITECTURE_ZONE_MIN_CONTENT_PADDING);\n const sidePadding = baseSidePadding + nestedZoneGap;\n const bottomPadding =\n Math.max(baseSidePadding, ARCHITECTURE_ZONE_MIN_BOTTOM_PADDING) + nestedZoneGap;\n const labelLane = labelLaneById.get(overlay.id) ?? 0;\n const labelOffsetY =\n ARCHITECTURE_ZONE_LABEL_TOP + labelLane * ARCHITECTURE_ZONE_NESTED_LABEL_STEP;\n const showDescription = Boolean(overlay.description) && !overlappingZoneIds.has(overlay.id);\n const descriptionOffsetY =\n labelOffsetY + ARCHITECTURE_ZONE_LABEL_HEIGHT + ARCHITECTURE_ZONE_LABEL_TO_DESCRIPTION_GAP;\n const descriptionReserve = showDescription\n ? ARCHITECTURE_ZONE_DESCRIPTION_HEIGHT + ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP\n : 0;\n const topPadding =\n sidePadding +\n ARCHITECTURE_ZONE_LABEL_HEIGHT +\n ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP +\n descriptionReserve +\n maxLabelLane * ARCHITECTURE_ZONE_NESTED_LABEL_STEP;\n\n return {\n id: overlay.id,\n label: overlay.label,\n description: showDescription ? overlay.description : undefined,\n color: overlay.color,\n x: Math.round(overlay.minX - sidePadding),\n y: Math.round(overlay.minY - topPadding),\n width: Math.max(120, Math.round(overlay.maxX - overlay.minX + sidePadding * 2)),\n height: Math.max(100, Math.round(overlay.maxY - overlay.minY + topPadding + bottomPadding)),\n nodeCount: overlay.nodeCount,\n nestingDepth,\n labelLane,\n labelOffsetY,\n descriptionOffsetY,\n sourceIndex: overlay.sourceIndex,\n };\n })\n .sort((a, b) => {\n const areaDiff = b.width * b.height - a.width * a.height;\n if (areaDiff !== 0) {\n return areaDiff;\n }\n\n return a.sourceIndex - b.sourceIndex;\n })\n .map(({ sourceIndex: _sourceIndex, ...overlay }) => overlay);\n});\n\nfunction architectureZoneCardStyle(zone: ArchitectureZoneOverlay) {\n return {\n left: `${zone.x}px`,\n top: `${zone.y}px`,\n width: `${zone.width}px`,\n height: `${zone.height}px`,\n borderColor: withAlpha(zone.color, 0.38),\n background: `linear-gradient(180deg, ${withAlpha(zone.color, 0.1)} 0%, ${withAlpha(zone.color, 0.045)} 62%, ${withAlpha(zone.color, 0.03)} 100%)`,\n boxShadow: `inset 0 0 0 1px ${withAlpha(zone.color, 0.1)}`,\n };\n}\n\nfunction architectureZoneLabelStyle(zone: ArchitectureZoneOverlay) {\n return {\n top: `${zone.labelOffsetY}px`,\n borderColor: withAlpha(zone.color, 0.55),\n background: withAlpha(zone.color, 0.18),\n color: zone.color,\n };\n}\n\nfunction architectureZoneDescriptionStyle(zone: ArchitectureZoneOverlay) {\n return {\n top: `${zone.descriptionOffsetY}px`,\n };\n}\n\nconst layoutPositions = computed<Record<string, { x: number; y: number }>>(() => {\n const orderedNodes = orderedNodeElements.value;\n if (orderedNodes.length === 0) return {};\n\n const rankGap = resolvedLayoutRankSep.value;\n const nodeGap = resolvedLayoutNodeSep.value;\n const edgeGap = resolvedLayoutEdgeSep.value;\n const fallback = createFallbackLayoutPositions(orderedNodes, rankGap);\n\n if (resolvedLayoutEngine.value === \"manual\") {\n return createManualLayoutPositions(orderedNodes, rankGap, nodeGap);\n }\n\n const graph = new dagre.graphlib.Graph();\n graph.setDefaultEdgeLabel(() => ({}));\n graph.setGraph({\n rankdir: props.direction === \"vertical\" ? \"TB\" : \"LR\",\n ranker: \"network-simplex\",\n acyclicer: \"greedy\",\n align: \"UL\",\n marginx: 36,\n marginy: 36,\n ranksep: rankGap,\n nodesep: nodeGap,\n edgesep: edgeGap,\n });\n\n for (const node of orderedNodes) {\n const size = nodeSizes.value[node.key] ?? { width: 240, height: 120 };\n\n graph.setNode(node.key, {\n width: size.width,\n height: size.height,\n });\n }\n\n for (const node of orderedNodes) {\n const targets = outgoingNodeKeys.value[node.key] ?? [];\n const preferredTarget = resolveNextNode(node.key, targets);\n\n for (const target of targets) {\n if (!orderedNodeByKey.value[target]) continue;\n\n graph.setEdge(node.key, target, {\n minlen: 1,\n weight: target === preferredTarget ? 3 : 1,\n });\n }\n }\n\n try {\n dagre.layout(graph);\n } catch {\n return fallback;\n }\n\n const positions: Record<string, { x: number; y: number }> = {};\n\n for (const node of orderedNodes) {\n const layoutNode = graph.node(node.key);\n if (!layoutNode || typeof layoutNode.x !== \"number\" || typeof layoutNode.y !== \"number\") {\n continue;\n }\n\n const size = nodeSizes.value[node.key] ?? { width: 240, height: 120 };\n\n positions[node.key] = {\n x: Math.round(layoutNode.x - size.width / 2),\n y: Math.round(layoutNode.y - size.height / 2),\n };\n }\n\n if (Object.keys(positions).length === 0) {\n return fallback;\n }\n\n return normalizePositions(positions);\n});\n\nconst nodes = computed<FlowNode[]>(() => {\n const fallbackPositions = createFallbackLayoutPositions(\n orderedNodeElements.value,\n resolvedLayoutRankSep.value,\n );\n\n return orderedNodeElements.value.map(({ key, nodeType, element, index }) => ({\n id: key,\n type: nodeType,\n targetPosition: Position.Left,\n sourcePosition: Position.Right,\n position:\n layoutPositions.value[key] ??\n fallbackPositions[key] ??\n (props.direction === \"vertical\"\n ? { x: 0, y: index * DEFAULT_FALLBACK_GAP }\n : { x: index * DEFAULT_FALLBACK_GAP, y: 0 }),\n data: {\n key,\n type: nodeType,\n elementType: element.type,\n props: element.props,\n active: isActive(key),\n sourceAnchor: resolveNodeSourceAnchor(element.props),\n index,\n },\n }));\n});\n\nconst edges = computed<FlowEdge[]>(() => {\n const result: FlowEdge[] = [];\n\n for (const node of orderedNodeElements.value) {\n const targets = outgoingNodeKeys.value[node.key] ?? [];\n\n for (const target of targets) {\n if (!orderedNodeByKey.value[target]) continue;\n\n const isActiveEdge =\n !isArchitectureMode.value &&\n activeFrame.value?.nodeKey === node.key &&\n nextPlannedNodeKey.value === target;\n const transition = transitionMetaBySource.value[node.key]?.[target];\n const edgeClasses = [\n isActiveEdge ? \"active-edge\" : null,\n transition?.kind ? `edge-kind-${transition.kind}` : null,\n ].filter((value): value is string => Boolean(value));\n\n const edgeLabel = resolveTransitionEdgeLabel(transition);\n const hasLabel = Boolean(edgeLabel);\n\n result.push({\n id: `e-${node.key}-${target}`,\n source: node.key,\n target,\n type: isArchitectureMode.value ? \"architecture\" : \"smoothstep\",\n animated: !isArchitectureMode.value,\n class: edgeClasses.length > 0 ? edgeClasses.join(\" \") : undefined,\n label: edgeLabel,\n labelShowBg: hasLabel && !isArchitectureMode.value,\n labelBgPadding: hasLabel && !isArchitectureMode.value ? [6, 3] : undefined,\n labelBgBorderRadius: hasLabel && !isArchitectureMode.value ? 6 : undefined,\n labelBgStyle:\n hasLabel && !isArchitectureMode.value\n ? { fill: \"var(--color-card)\", fillOpacity: 0.985, stroke: \"var(--color-border)\" }\n : undefined,\n labelStyle:\n hasLabel && !isArchitectureMode.value\n ? {\n fill: \"var(--color-foreground)\",\n fontSize: \"10px\",\n fontWeight: 600,\n }\n : undefined,\n });\n }\n }\n\n return result;\n});\n\nconst diagramBounds = computed(() => {\n if (nodes.value.length === 0) {\n return null;\n }\n\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n\n for (const node of nodes.value) {\n const size = nodeSizes.value[node.id] ?? { width: 240, height: 120 };\n minX = Math.min(minX, node.position.x);\n minY = Math.min(minY, node.position.y);\n maxX = Math.max(maxX, node.position.x + size.width);\n maxY = Math.max(maxY, node.position.y + size.height);\n }\n\n for (const zone of architectureZoneOverlays.value) {\n minX = Math.min(minX, zone.x);\n minY = Math.min(minY, zone.y);\n maxX = Math.max(maxX, zone.x + zone.width);\n maxY = Math.max(maxY, zone.y + zone.height);\n }\n\n if (\n !Number.isFinite(minX) ||\n !Number.isFinite(minY) ||\n !Number.isFinite(maxX) ||\n !Number.isFinite(maxY)\n ) {\n return null;\n }\n\n return {\n x: Math.floor(minX),\n y: Math.floor(minY),\n width: Math.max(1, Math.ceil(maxX - minX)),\n height: Math.max(1, Math.ceil(maxY - minY)),\n };\n});\n\nfunction createExportFileBaseName() {\n const rawName = activeFlow.value?.id ?? overlayTitle.value ?? props.title ?? \"flow-diagram\";\n\n const slug = rawName\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n return slug || \"flow-diagram\";\n}\n\nasync function exportDiagram(format: DiagramExportFormat) {\n if (exportInFlight.value) return;\n if (!canExportDiagram.value) return;\n\n const flowElement = sceneRef.value;\n const bounds = diagramBounds.value;\n\n if (!flowElement || !bounds) {\n exportError.value = \"Diagram is still initializing. Try again in a moment.\";\n return;\n }\n\n exportError.value = null;\n exportMenuOpen.value = false;\n exportInFlight.value = format;\n\n try {\n await exportFlowDiagram({\n flowElement,\n theme: uiTheme.value,\n bounds,\n fileNameBase: createExportFileBaseName(),\n format,\n });\n } catch (error) {\n exportError.value =\n error instanceof Error ? error.message : `Failed to export ${format.toUpperCase()} diagram.`;\n } finally {\n exportInFlight.value = null;\n }\n}\n\nfunction isActive(nodeKey: string) {\n if (isArchitectureMode.value) {\n return true;\n }\n\n return activeFrame.value?.nodeKey === nodeKey;\n}\n\nfunction codeStepIndex(nodeKey: string) {\n if (activeFrame.value?.nodeKey !== nodeKey) {\n return 0;\n }\n\n return activeFrame.value.localStep;\n}\n\nconst activeNode = computed(() => {\n const key = activeFrame.value?.nodeKey;\n if (!key) return undefined;\n return orderedNodeByKey.value[key];\n});\n\nconst activeLocalStep = computed(() => activeFrame.value?.localStep ?? 0);\n\nconst activeLabel = computed(() => {\n const node = activeNode.value;\n if (!node) return \"\";\n\n const base = toOptionalString(node.element.props.label) ?? \"\";\n\n if (node.element.type !== \"CodeNode\") {\n return base;\n }\n\n const steps = toMagicMoveSteps(node.element.props.magicMoveSteps);\n if (steps.length === 0) return base;\n\n const title = steps[Math.min(activeLocalStep.value, steps.length - 1)]?.title;\n return title ? `${base} - ${title}` : base;\n});\n\nconst activeDescription = computed(() => {\n const node = activeNode.value;\n if (!node) return \"\";\n\n if (node.element.type === \"CodeNode\") {\n const steps = toMagicMoveSteps(node.element.props.magicMoveSteps);\n const defaultStory =\n toOptionalString(node.element.props.story) ?? toOptionalString(node.element.props.comment);\n\n if (steps.length > 0) {\n const beat = steps[Math.min(activeLocalStep.value, steps.length - 1)];\n\n return beat?.story ?? beat?.comment ?? defaultStory ?? \"\";\n }\n\n return defaultStory ?? \"\";\n }\n\n return getNodeSummary(node);\n});\n\nconst activeSourceAnchor = computed(() => {\n const node = activeNode.value;\n if (!node) return undefined;\n\n return resolveNodeSourceAnchor(node.element.props);\n});\n\nconst architectureSelectedNodeKey = ref<string | null>(null);\n\nconst architectureSelectedNode = computed(() => {\n if (!isArchitectureMode.value) {\n return undefined;\n }\n\n const selected = architectureSelectedNodeKey.value;\n if (selected && orderedNodeByKey.value[selected]) {\n return orderedNodeByKey.value[selected];\n }\n\n return orderedNodeElements.value[0];\n});\n\nwatch(\n [isArchitectureMode, orderedNodeElements],\n ([architectureMode, ordered]) => {\n if (!architectureMode) {\n architectureSelectedNodeKey.value = null;\n return;\n }\n\n const selected = architectureSelectedNodeKey.value;\n if (selected && ordered.some((node) => node.key === selected)) {\n return;\n }\n\n architectureSelectedNodeKey.value = ordered[0]?.key ?? null;\n },\n { immediate: true },\n);\n\nconst architectureInspector = computed<ArchitectureInspectorView | null>(() => {\n const node = architectureSelectedNode.value;\n if (!node) {\n return null;\n }\n\n const label = toTrimmedNonEmptyString(node.element.props.label) ?? node.key;\n const sourceAnchor = resolveNodeSourceAnchor(node.element.props);\n\n if (node.element.type !== \"ArchitectureNode\") {\n return {\n type: \"Other\",\n label,\n summary: getNodeSummary(node),\n sourceAnchor,\n elementType: node.element.type,\n };\n }\n\n const zoneId = toArchitectureZoneId(node.element.props.zone);\n const zoneLabel = zoneId\n ? (architectureZoneLabelById.value[zoneId] ?? humanizeZoneId(zoneId))\n : undefined;\n const interfaces = toArchitectureInterfaces(node.element.props.interfaces);\n const dataAssets = toArchitectureDataAssets(node.element.props.data);\n const security = toArchitectureSecurity(node.element.props.security);\n const operations = toArchitectureOperations(node.element.props.operations);\n const links = toArchitectureLinks(node.element.props.links);\n const outgoing: ArchitectureOutgoingEdge[] = [];\n\n for (const targetKey of outgoingNodeKeys.value[node.key] ?? []) {\n const targetNode = orderedNodeByKey.value[targetKey];\n if (!targetNode) {\n continue;\n }\n\n const transition = transitionMetaBySource.value[node.key]?.[targetKey];\n\n outgoing.push({\n target: toTrimmedNonEmptyString(targetNode.element.props.label) ?? targetKey,\n label: transition?.label,\n protocol: transition?.protocol,\n transport: transition?.transport,\n auth: transition?.auth,\n criticality: transition?.criticality,\n });\n }\n\n return {\n type: \"ArchitectureNode\",\n label,\n kind: toArchitectureKind(node.element.props.kind),\n status: toArchitectureStatus(node.element.props.status),\n tier: toArchitectureTier(node.element.props.tier),\n technology: toTrimmedNonEmptyString(node.element.props.technology),\n runtime: toTrimmedNonEmptyString(node.element.props.runtime),\n owner: toTrimmedNonEmptyString(node.element.props.owner),\n zoneLabel,\n summary: toTrimmedNonEmptyString(node.element.props.description) ?? \"\",\n tags: toStringArray(node.element.props.tags),\n responsibilities: toStringArray(node.element.props.responsibilities),\n capabilities: toStringArray(node.element.props.capabilities),\n interfaces,\n dataAssets,\n security,\n operations,\n links,\n outgoing,\n sourceAnchor,\n };\n});\n\nconst architectureInspectorNode = computed<ArchitectureInspectorArchitectureView | null>(() => {\n const inspector = architectureInspector.value;\n if (!inspector || inspector.type !== \"ArchitectureNode\") {\n return null;\n }\n\n return inspector;\n});\n\nconst architectureInspectorNodeSafe = computed(() => {\n return architectureInspectorNode.value ?? EMPTY_ARCHITECTURE_INSPECTOR_NODE;\n});\n\nconst architectureInspectorPanelStyle = computed(() => {\n return {\n transform: architectureInspectorOpen.value ? \"translateX(0)\" : \"translateX(100%)\",\n };\n});\n\nconst branchChoices = computed<BranchChoice[]>(() => {\n if (isArchitectureMode.value) {\n return [];\n }\n\n const node = activeNode.value;\n const frame = activeFrame.value;\n if (!node || !frame) return [];\n\n if (frame.localStep < frame.totalLocalSteps - 1) {\n return [];\n }\n\n const options = outgoingNodeKeys.value[node.key] ?? [];\n if (options.length <= 1) return [];\n\n const result: BranchChoice[] = [];\n\n for (const id of options) {\n const target = orderedNodeByKey.value[id];\n if (!target) continue;\n\n const transition = transitionMetaBySource.value[node.key]?.[id];\n\n const targetLabel = toOptionalString(target.element.props.label) ?? id;\n const targetDescription = getNodeSummary(target);\n\n result.push({\n id,\n label: transition?.label ?? targetLabel,\n description: transition?.description ?? targetDescription,\n kind: transition?.kind,\n });\n }\n\n return result;\n});\n\nconst selectedBranchChoiceId = computed(() => {\n const node = activeNode.value;\n if (!node || branchChoices.value.length === 0) return undefined;\n\n const selected = selectedBranchByNode.value[node.key];\n if (selected) return selected;\n\n return nextPlannedNodeKey.value;\n});\n\nfunction chooseChoice(choiceId: string) {\n const node = activeNode.value;\n if (!node) return;\n\n const options = outgoingNodeKeys.value[node.key] ?? [];\n if (!options.includes(choiceId)) return;\n\n selectedBranchByNode.value = {\n ...selectedBranchByNode.value,\n [node.key]: choiceId,\n };\n\n const prefix = pathFrames.value.slice(0, currentStep.value + 1);\n const suffix = buildGuidedPath(choiceId);\n\n pathFrames.value = [...prefix, ...suffix];\n\n if (pathFrames.value.length > currentStep.value + 1) {\n currentStep.value += 1;\n }\n}\n\nconst containerMinHeight = computed(() => {\n const provided = Number(props.minHeight);\n if (Number.isFinite(provided) && provided >= 320) {\n return Math.floor(provided);\n }\n\n if (isArchitectureMode.value) {\n return 620;\n }\n\n const node = activeNode.value ?? orderedNodeElements.value[0];\n if (!node || node.element.type !== \"CodeNode\") {\n return 520;\n }\n\n const maxLineLength = getCodeNodeMaxLineLength(node.element);\n const nodeWidth = estimateCodeNodeWidth(maxLineLength);\n const codeCharsPerLine = estimateCodeNodeCharsPerLine(nodeWidth);\n const autoWrapEnabled = maxLineLength > CODE_NODE_MAX_INLINE_CHARS;\n const wrapEnabled = toBoolean(node.element.props.wrapLongLines) || autoWrapEnabled;\n\n const codeLines = wrapEnabled\n ? getCodeNodeWrappedLines(node.element, codeCharsPerLine)\n : getCodeNodeMaxLines(node.element);\n const storyLines = getCodeNodeStoryLines(node.element);\n const storyHasMeta = hasCodeNodeStoryMeta(node.element);\n\n const codeViewportHeight = wrapEnabled\n ? Math.min(400, Math.max(190, 72 + codeLines * 16))\n : Math.min(340, Math.max(160, 84 + codeLines * 17));\n\n const storyViewportHeight =\n storyLines > 0 ? Math.min(220, Math.max(88, (storyHasMeta ? 56 : 34) + storyLines * 18)) : 0;\n\n return Math.min(880, Math.max(560, codeViewportHeight + storyViewportHeight + 300));\n});\n\nconst instance = getCurrentInstance();\nconst flowId = `flaier-${instance?.uid ?? 0}`;\nconst { fitView, onNodeClick, onViewportChange, setCenter, viewport } = useVueFlow(flowId);\nconst nodesInitialized = useNodesInitialized();\nconst paneReady = ref(false);\nconst overviewMode = ref(false);\nlet resizeObserver: ResizeObserver | null = null;\n\nconst architectureZoneLayerStyle = computed(() => {\n const x = Number.isFinite(viewport.value.x) ? viewport.value.x : 0;\n const y = Number.isFinite(viewport.value.y) ? viewport.value.y : 0;\n const zoom = Number.isFinite(viewport.value.zoom) ? viewport.value.zoom : 1;\n\n return {\n transform: `translate(${x}px, ${y}px) scale(${zoom})`,\n transformOrigin: \"0 0\",\n };\n});\n\nfunction handleDocumentPointerDown(event: PointerEvent) {\n const target = event.target as Node | null;\n if (!target) return;\n\n if (headerDropdownOpen.value && !headerDropdownRef.value?.contains(target)) {\n closeHeaderDropdown();\n }\n\n if (exportMenuOpen.value && !exportMenuRef.value?.contains(target)) {\n closeExportMenu();\n }\n}\n\nfunction isEditableTarget(target: EventTarget | null) {\n if (!(target instanceof HTMLElement)) {\n return false;\n }\n\n if (target.isContentEditable) {\n return true;\n }\n\n const tagName = target.tagName;\n if (tagName === \"INPUT\" || tagName === \"TEXTAREA\" || tagName === \"SELECT\") {\n return true;\n }\n\n return Boolean(target.closest('[contenteditable=\"true\"]'));\n}\n\nfunction handleDocumentKeydown(event: KeyboardEvent) {\n if (event.key === \"Escape\") {\n closeHeaderDropdown();\n closeExportMenu();\n\n if (isArchitectureMode.value) {\n architectureInspectorOpen.value = false;\n }\n\n return;\n }\n\n if (event.defaultPrevented) return;\n if (event.metaKey || event.ctrlKey || event.altKey) return;\n if (isEditableTarget(event.target)) return;\n if (isArchitectureMode.value) return;\n\n if (event.key === \"ArrowRight\" || event.key === \"ArrowDown\") {\n event.preventDefault();\n next();\n return;\n }\n\n if (event.key === \"ArrowLeft\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n prev();\n return;\n }\n\n if (/^[1-9]$/.test(event.key)) {\n const index = Number(event.key) - 1;\n const choice = branchChoices.value[index];\n if (!choice) return;\n\n event.preventDefault();\n chooseChoice(choice.id);\n }\n}\n\nfunction syncOverviewModeFromZoom(zoom: number) {\n if (overviewMode.value) {\n if (zoom >= OVERVIEW_EXIT_ZOOM) {\n overviewMode.value = false;\n }\n\n return;\n }\n\n if (zoom <= OVERVIEW_ENTER_ZOOM) {\n overviewMode.value = true;\n }\n}\n\nwatch(\n () => viewport.value.zoom,\n (zoom) => {\n if (!Number.isFinite(zoom)) return;\n\n syncOverviewModeFromZoom(zoom);\n },\n { immediate: true },\n);\n\nonViewportChange((transform) => {\n if (!Number.isFinite(transform.zoom)) return;\n\n syncOverviewModeFromZoom(transform.zoom);\n});\n\nonNodeClick(({ node }) => {\n if (isArchitectureMode.value) {\n architectureSelectedNodeKey.value = node.id;\n architectureInspectorOpen.value = true;\n return;\n }\n\n jumpToNode(node.id);\n});\n\nfunction updateContainerReady() {\n const element = containerRef.value;\n containerWidth.value = element?.clientWidth ?? 0;\n containerHeight.value = element?.clientHeight ?? 0;\n containerReady.value = containerWidth.value > 0 && containerHeight.value > 0;\n}\n\nconst sceneStyle = computed<Record<string, string>>(() => ({\n height: `${Math.max(containerHeight.value, containerMinHeight.value)}px`,\n}));\n\nonMounted(() => {\n if (typeof document !== \"undefined\") {\n document.addEventListener(\"pointerdown\", handleDocumentPointerDown);\n document.addEventListener(\"keydown\", handleDocumentKeydown);\n }\n\n nextTick(() => {\n updateContainerReady();\n\n if (typeof ResizeObserver === \"undefined\") return;\n\n resizeObserver = new ResizeObserver(() => {\n updateContainerReady();\n });\n\n if (containerRef.value) {\n resizeObserver.observe(containerRef.value);\n }\n });\n});\n\nfunction onInit() {\n paneReady.value = true;\n}\n\nconst viewportReady = computed(\n () => paneReady.value && nodesInitialized.value && containerReady.value && nodes.value.length > 0,\n);\n\nconst canExportDiagram = computed(() => {\n return Boolean(viewportReady.value && diagramBounds.value);\n});\n\nwatch(canExportDiagram, (canExport) => {\n if (!canExport) {\n closeExportMenu();\n }\n});\n\nconst narrativeFocusTarget = computed(() => {\n if (isArchitectureMode.value || overviewMode.value || !viewportReady.value) {\n return null;\n }\n\n const nodeKey = activeFrame.value?.nodeKey;\n if (!nodeKey) {\n return null;\n }\n\n const node = nodes.value.find((candidate) => candidate.id === nodeKey);\n if (!node) {\n return null;\n }\n\n const size = nodeSizes.value[node.id] ?? { width: 240, height: 120 };\n\n return {\n signature: [\n node.id,\n Math.round(node.position.x),\n Math.round(node.position.y),\n Math.round(size.width),\n Math.round(size.height),\n Math.round(containerWidth.value),\n Math.round(containerHeight.value),\n ].join(\":\"),\n x: node.position.x + size.width / 2,\n y: node.position.y + size.height / 2,\n };\n});\n\nconst narrativeFitSignature = ref(\"\");\n\nwatch(\n [viewportReady, isArchitectureMode, nodes, containerWidth, containerHeight],\n ([ready, architectureMode, currentNodes, width, height]) => {\n if (!ready || architectureMode || currentNodes.length === 0) return;\n\n const signature = [\n `${Math.round(width)}x${Math.round(height)}`,\n ...currentNodes.map(\n (node) => `${node.id}:${Math.round(node.position.x)}:${Math.round(node.position.y)}`,\n ),\n ].join(\"|\");\n\n if (signature === narrativeFitSignature.value) {\n return;\n }\n\n narrativeFitSignature.value = signature;\n\n nextTick(() => {\n void fitView({\n duration: 280,\n padding: 0.3,\n maxZoom: 0.95,\n });\n });\n },\n { immediate: true },\n);\n\nwatch(\n () => narrativeFocusTarget.value?.signature ?? \"\",\n () => {\n const target = narrativeFocusTarget.value;\n if (!target) return;\n\n const zoom = Number.isFinite(viewport.value.zoom) ? viewport.value.zoom : 1;\n\n nextTick(() => {\n void setCenter(target.x, target.y, { duration: 280, zoom });\n });\n },\n { immediate: true },\n);\n\nconst architectureFitSignature = ref(\"\");\n\nwatch(\n [viewportReady, isArchitectureMode, nodes, containerWidth, containerHeight],\n ([ready, architectureMode, currentNodes, width, height]) => {\n if (!ready || !architectureMode || currentNodes.length === 0) return;\n\n const signature = [\n `${Math.round(width)}x${Math.round(height)}`,\n ...currentNodes.map(\n (node) => `${node.id}:${Math.round(node.position.x)}:${Math.round(node.position.y)}`,\n ),\n ].join(\"|\");\n\n if (signature === architectureFitSignature.value) {\n return;\n }\n\n architectureFitSignature.value = signature;\n\n nextTick(() => {\n void fitView({\n duration: 260,\n padding: 0.18,\n maxZoom: 1.15,\n });\n });\n },\n { immediate: true },\n);\n\nwatch(isArchitectureMode, (architectureMode) => {\n if (architectureMode) {\n playing.value = false;\n narrativeFitSignature.value = \"\";\n architectureInspectorOpen.value = defaultArchitectureInspectorOpen.value;\n return;\n }\n\n narrativeFitSignature.value = \"\";\n architectureFitSignature.value = \"\";\n architectureInspectorOpen.value = defaultArchitectureInspectorOpen.value;\n});\n\nonUnmounted(() => {\n clearTimer();\n\n if (typeof document !== \"undefined\") {\n document.removeEventListener(\"pointerdown\", handleDocumentPointerDown);\n document.removeEventListener(\"keydown\", handleDocumentKeydown);\n }\n\n if (resizeObserver) {\n resizeObserver.disconnect();\n resizeObserver = null;\n }\n\n stopDocumentThemeSync();\n});\n</script>\n\n<template>\n <div\n ref=\"containerRef\"\n class=\"flaier relative h-full w-full font-sans antialiased bg-background transition-[min-height] duration-300 ease-out\"\n :style=\"{ minHeight: `${containerMinHeight}px` }\"\n :data-mode=\"isArchitectureMode ? 'architecture' : 'narrative'\"\n :data-focus-mode=\"overviewMode ? 'overview' : 'focus'\"\n :data-theme=\"uiTheme\"\n >\n <div ref=\"sceneRef\" class=\"relative w-full overflow-hidden\" :style=\"sceneStyle\">\n <div\n v-if=\"containerReady && isArchitectureMode && architectureZoneOverlays.length > 0\"\n class=\"pointer-events-none absolute inset-0 z-0\"\n >\n <div class=\"absolute inset-0\" data-zone-overlay=\"true\" :style=\"architectureZoneLayerStyle\">\n <div\n v-for=\"zone in architectureZoneOverlays\"\n :key=\"zone.id\"\n class=\"absolute rounded-2xl border border-dashed\"\n :style=\"architectureZoneCardStyle(zone)\"\n >\n <div\n class=\"absolute left-4 inline-flex items-center gap-2 rounded-full border px-2 py-1 text-[10px] font-semibold uppercase tracking-wider\"\n :style=\"architectureZoneLabelStyle(zone)\"\n >\n <span>{{ zone.label }}</span>\n <span class=\"opacity-80\"\n >{{ zone.nodeCount }} node{{ zone.nodeCount === 1 ? \"\" : \"s\" }}</span\n >\n </div>\n\n <p\n v-if=\"zone.description\"\n class=\"absolute left-4 right-4 text-[10px] leading-snug text-muted-foreground\"\n :style=\"architectureZoneDescriptionStyle(zone)\"\n >\n {{ zone.description }}\n </p>\n </div>\n </div>\n </div>\n\n <VueFlow\n v-if=\"containerReady\"\n :id=\"flowId\"\n :nodes=\"nodes\"\n :edges=\"edges\"\n :node-types=\"customNodeTypes\"\n :fit-view-on-init=\"false\"\n :elements-selectable=\"false\"\n :nodes-focusable=\"false\"\n :nodes-draggable=\"false\"\n :nodes-connectable=\"false\"\n :zoom-on-scroll=\"true\"\n :zoom-on-pinch=\"true\"\n :pan-on-drag=\"true\"\n :pan-on-scroll=\"true\"\n :min-zoom=\"0.15\"\n :max-zoom=\"2\"\n :prevent-scrolling=\"true\"\n class=\"relative z-[10] h-full w-full\"\n @init=\"onInit\"\n >\n <template #node-architecture=\"{ data }\">\n <ArchitectureNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :kind=\"toArchitectureKind(data.props.kind)\"\n :technology=\"toOptionalString(data.props.technology)\"\n :runtime=\"toOptionalString(data.props.runtime)\"\n :owner=\"toOptionalString(data.props.owner)\"\n :tier=\"toArchitectureTier(data.props.tier)\"\n :status=\"toArchitectureStatus(data.props.status)\"\n :tags=\"toStringArray(data.props.tags)\"\n :capabilities=\"toStringArray(data.props.capabilities)\"\n :description=\"toOptionalString(data.props.description)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #edge-architecture=\"edgeProps\">\n <ArchitectureSmoothEdge v-bind=\"edgeProps\" />\n </template>\n\n <template #node-trigger=\"{ data }\">\n <TriggerNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :description=\"toOptionalString(data.props.description)\"\n :color=\"toOptionalString(data.props.color)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-code=\"{ data }\">\n <CodeNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :file=\"toOptionalString(data.props.file)\"\n :language=\"toOptionalString(data.props.language)\"\n :code=\"toRequiredString(data.props.code)\"\n :comment=\"toOptionalString(data.props.comment)\"\n :story=\"toOptionalString(data.props.story)\"\n :wrap-long-lines=\"toBoolean(data.props.wrapLongLines)\"\n :magic-move-steps=\"toMagicMoveSteps(data.props.magicMoveSteps)\"\n :twoslash=\"toOptionalBoolean(data.props.twoslash)\"\n :twoslash-html=\"toTwoslashHtml(data.props.twoslashHtml)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :ui-theme=\"uiTheme\"\n :active=\"isActive(data.key)\"\n :step-index=\"codeStepIndex(data.key)\"\n />\n </template>\n\n <template #node-decision=\"{ data }\">\n <DecisionNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :condition=\"toOptionalString(data.props.condition)\"\n :description=\"toOptionalString(data.props.description)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-payload=\"{ data }\">\n <PayloadNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :payload=\"toOptionalString(data.props.payload)\"\n :before=\"toOptionalString(data.props.before)\"\n :after=\"toOptionalString(data.props.after)\"\n :format=\"toPayloadFormat(data.props.format)\"\n :description=\"toOptionalString(data.props.description)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-error=\"{ data }\">\n <ErrorNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :message=\"toRequiredString(data.props.message)\"\n :code=\"toOptionalString(data.props.code)\"\n :cause=\"toOptionalString(data.props.cause)\"\n :mitigation=\"toOptionalString(data.props.mitigation)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-description=\"{ data }\">\n <DescriptionNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :body=\"toRequiredString(data.props.body)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-link=\"{ data }\">\n <LinkNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :href=\"toRequiredString(data.props.href)\"\n :description=\"toOptionalString(data.props.description)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n </VueFlow>\n\n <div v-else class=\"h-full w-full\" />\n </div>\n\n <div\n v-if=\"showHeaderOverlay && (showFlowSelector || overlayTitle || overlayDescription)\"\n ref=\"headerDropdownRef\"\n class=\"absolute top-4 left-4 z-20 w-[min(90vw,430px)]\"\n >\n <div class=\"relative\">\n <button\n type=\"button\"\n class=\"group w-full rounded-lg border border-border/70 bg-card/85 px-3 py-2 text-left text-xs shadow-lg backdrop-blur-md transition-colors\"\n :class=\"showFlowSelector ? 'cursor-pointer hover:border-primary/45' : 'cursor-default'\"\n :disabled=\"!showFlowSelector\"\n :aria-expanded=\"showFlowSelector ? headerDropdownOpen : undefined\"\n aria-haspopup=\"listbox\"\n @click=\"toggleHeaderDropdown\"\n >\n <div class=\"flex items-start justify-between gap-3\">\n <div class=\"min-w-0\">\n <p class=\"text-[10px] font-medium uppercase tracking-wider text-muted-foreground\">\n {{ headerModeLabel }}\n </p>\n <p v-if=\"overlayTitle\" class=\"mt-1 truncate text-sm font-medium text-foreground\">\n {{ overlayTitle }}\n </p>\n <p\n v-if=\"overlayDescription\"\n class=\"mt-0.5 text-[11px] leading-relaxed text-muted-foreground break-words\"\n >\n {{ overlayDescription }}\n </p>\n </div>\n\n <svg\n v-if=\"showFlowSelector\"\n class=\"mt-0.5 h-4 w-4 shrink-0 transition-all\"\n :class=\"\n headerDropdownOpen\n ? 'rotate-180 text-foreground'\n : 'text-muted-foreground group-hover:text-foreground'\n \"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </div>\n </button>\n\n <div\n v-if=\"showFlowSelector && headerDropdownOpen\"\n class=\"absolute inset-x-0 top-[calc(100%+8px)] rounded-lg border border-border/70 bg-card/95 p-1 shadow-2xl backdrop-blur-md\"\n role=\"listbox\"\n >\n <button\n v-for=\"flow in availableFlows\"\n :key=\"flow.id\"\n type=\"button\"\n class=\"w-full rounded-md px-2.5 py-2 text-left transition-colors\"\n :class=\"\n flow.id === activeFlowId\n ? 'bg-primary/14 text-foreground'\n : 'text-foreground/90 hover:bg-muted/70'\n \"\n @click=\"handleFlowSelect(flow.id)\"\n >\n <div class=\"flex items-center justify-between gap-2\">\n <p class=\"truncate text-xs font-medium\">{{ flow.title }}</p>\n <span\n v-if=\"flow.id === activeFlowId\"\n class=\"rounded-full border border-primary/35 bg-primary/10 px-1.5 py-0.5 text-[10px] uppercase tracking-wide text-primary\"\n >\n Active\n </span>\n </div>\n <p\n v-if=\"flow.description\"\n class=\"mt-0.5 text-[11px] leading-relaxed text-muted-foreground break-words\"\n >\n {{ flow.description }}\n </p>\n </button>\n </div>\n </div>\n </div>\n\n <div\n v-if=\"showTopRightControls\"\n class=\"fn-architecture-controls absolute top-4 right-4 z-20 flex flex-col items-end gap-2\"\n >\n <div ref=\"exportMenuRef\" class=\"relative\">\n <button\n v-if=\"showExportControls\"\n type=\"button\"\n class=\"group inline-flex h-9 items-center gap-2 rounded-full border border-border/70 bg-card/85 px-3 text-[11px] text-muted-foreground shadow-lg backdrop-blur-md transition-colors hover:text-foreground disabled:cursor-default disabled:opacity-55\"\n :aria-label=\"exportButtonLabel\"\n :title=\"exportButtonLabel\"\n :disabled=\"!canExportDiagram || Boolean(exportInFlight)\"\n @click=\"toggleExportMenu\"\n >\n <svg\n class=\"h-3.5 w-3.5\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 3v12\" />\n <path d=\"m7 10 5 5 5-5\" />\n <path d=\"M4 20h16\" />\n </svg>\n <span>Export</span>\n </button>\n\n <div\n v-if=\"showExportControls && exportMenuOpen\"\n class=\"absolute right-0 top-[calc(100%+8px)] w-44 rounded-lg border border-border/70 bg-card/95 p-1 shadow-2xl backdrop-blur-md\"\n >\n <button\n type=\"button\"\n class=\"w-full rounded-md px-2.5 py-2 text-left text-xs text-foreground transition-colors hover:bg-muted/70\"\n :disabled=\"Boolean(exportInFlight)\"\n @click=\"exportDiagram('png')\"\n >\n Export PNG\n </button>\n <button\n type=\"button\"\n class=\"w-full rounded-md px-2.5 py-2 text-left text-xs text-foreground transition-colors hover:bg-muted/70\"\n :disabled=\"Boolean(exportInFlight)\"\n @click=\"exportDiagram('pdf')\"\n >\n Export PDF\n </button>\n </div>\n </div>\n\n <button\n v-if=\"showThemeToggle\"\n type=\"button\"\n class=\"fn-theme-toggle group inline-flex h-9 w-9 items-center justify-center rounded-full border border-border/70 bg-card/85 text-muted-foreground shadow-lg backdrop-blur-md transition-colors hover:text-foreground\"\n :aria-label=\"themeToggleLabel\"\n :title=\"themeToggleLabel\"\n @click=\"toggleTheme\"\n >\n <svg\n v-if=\"isLightTheme\"\n class=\"h-4 w-4\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 3a1 1 0 0 1 1 1v1a1 1 0 1 1-2 0V4a1 1 0 0 1 1-1Z\" />\n <path\n d=\"M18.36 5.64a1 1 0 0 1 1.41 0l.71.71a1 1 0 0 1-1.41 1.41l-.71-.7a1 1 0 0 1 0-1.42Z\"\n />\n <path d=\"M20 11a1 1 0 1 1 0 2h-1a1 1 0 1 1 0-2h1Z\" />\n <path\n d=\"M18.36 18.36a1 1 0 0 1 0-1.41l.71-.71a1 1 0 0 1 1.41 1.41l-.7.71a1 1 0 0 1-1.42 0Z\"\n />\n <path d=\"M12 19a1 1 0 0 1 1 1v1a1 1 0 1 1-2 0v-1a1 1 0 0 1 1-1Z\" />\n <path\n d=\"M5.64 18.36a1 1 0 0 1-1.41 0l-.71-.71a1 1 0 1 1 1.41-1.41l.71.7a1 1 0 0 1 0 1.42Z\"\n />\n <path d=\"M5 11a1 1 0 1 1 0 2H4a1 1 0 1 1 0-2h1Z\" />\n <path\n d=\"M5.64 5.64a1 1 0 0 1 0 1.41l-.71.71a1 1 0 1 1-1.41-1.41l.7-.71a1 1 0 0 1 1.42 0Z\"\n />\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n </svg>\n\n <svg\n v-else\n class=\"h-4 w-4\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 12.79A9 9 0 1 1 11.21 3a7 7 0 1 0 9.79 9.79Z\" />\n </svg>\n </button>\n\n <p\n v-if=\"showExportControls && exportError\"\n class=\"max-w-[260px] rounded-md border border-red-500/45 bg-red-500/12 px-2 py-1 text-[10px] leading-relaxed text-red-200\"\n >\n {{ exportError }}\n </p>\n </div>\n\n <div\n v-if=\"!isArchitectureMode\"\n class=\"pointer-events-none absolute inset-x-0 bottom-2 z-30 flex justify-center px-3\"\n style=\"padding-bottom: max(env(safe-area-inset-bottom), 0px)\"\n >\n <div class=\"pointer-events-auto w-full max-w-[980px]\">\n <TimelineControls\n :current-step=\"currentStep\"\n :total-steps=\"totalSteps\"\n :playing=\"playing\"\n :label=\"activeLabel\"\n :description=\"activeDescription\"\n :source-anchor-label=\"activeSourceAnchor?.label\"\n :source-anchor-href=\"activeSourceAnchor?.href\"\n :choices=\"branchChoices\"\n :selected-choice-id=\"selectedBranchChoiceId\"\n @next=\"next\"\n @prev=\"prev\"\n @go-to=\"goTo\"\n @toggle-play=\"togglePlay\"\n @choose-choice=\"chooseChoice\"\n />\n </div>\n </div>\n\n <div\n v-if=\"isArchitectureMode && showArchitectureInspectorPanel && architectureInspector\"\n class=\"fn-architecture-inspector pointer-events-none absolute bottom-3 right-0 top-16 z-30 w-[min(92vw,430px)]\"\n style=\"\n padding-right: max(env(safe-area-inset-right), 0px);\n padding-bottom: max(env(safe-area-inset-bottom), 0px);\n \"\n >\n <div class=\"absolute inset-0 overflow-visible\">\n <aside\n class=\"pointer-events-auto absolute inset-y-0 right-0 w-full transition-all duration-300 ease-out\"\n :style=\"architectureInspectorPanelStyle\"\n >\n <button\n type=\"button\"\n class=\"fn-architecture-inspector__toggle absolute right-full top-1/2 z-30 inline-flex h-20 w-8 -translate-y-1/2 translate-x-px flex-col items-center justify-center gap-1 rounded-l-lg rounded-r-none border border-border/70 border-r-0 bg-gradient-to-b from-card/95 via-card/88 to-card/78 px-0.5 text-[8px] font-semibold uppercase tracking-[0.12em] text-muted-foreground shadow-2xl backdrop-blur-xl transition-all duration-200 hover:text-foreground\"\n :aria-label=\"architectureInspectorToggleLabel\"\n :title=\"architectureInspectorToggleLabel\"\n @click=\"toggleArchitectureInspector\"\n >\n <svg\n class=\"h-2.5 w-2.5\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path v-if=\"architectureInspectorOpen\" d=\"m14.5 6-5.5 6 5.5 6\" />\n <path v-else d=\"m9.5 6 5.5 6-5.5 6\" />\n </svg>\n <span\n v-if=\"showArchitectureInspectorToggleText\"\n class=\"inline-block font-semibold leading-none\"\n style=\"writing-mode: vertical-rl; transform: rotate(180deg); letter-spacing: 0.1em\"\n >\n Details\n </span>\n </button>\n\n <div\n class=\"fn-architecture-inspector__panel flex h-full flex-col overflow-hidden rounded-2xl border border-border/60 bg-gradient-to-b from-card/95 via-card/90 to-card/82 shadow-2xl backdrop-blur-xl\"\n >\n <div class=\"border-b border-border/60 px-3 py-2.5\">\n <div class=\"flex flex-wrap items-start justify-between gap-2\">\n <div class=\"min-w-0\">\n <p class=\"text-[11px] font-semibold text-foreground leading-snug break-words\">\n {{ architectureInspector.label }}\n </p>\n\n <div v-if=\"architectureInspectorNode\" class=\"mt-1 flex flex-wrap gap-1\">\n <span\n v-if=\"architectureInspectorNodeSafe.kind\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[9px] uppercase tracking-wider text-muted-foreground\"\n >\n {{ architectureInspectorNodeSafe.kind }}\n </span>\n <span\n v-if=\"architectureInspectorNodeSafe.status\"\n class=\"inline-flex items-center rounded border border-primary/35 bg-primary/10 px-1.5 py-0.5 text-[9px] uppercase tracking-wider text-primary\"\n >\n {{ architectureInspectorNodeSafe.status }}\n </span>\n <span\n v-if=\"architectureInspectorNodeSafe.tier\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[9px] uppercase tracking-wider text-muted-foreground\"\n >\n {{ architectureInspectorNodeSafe.tier }}\n </span>\n <span\n v-if=\"architectureInspectorNodeSafe.zoneLabel\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[9px] uppercase tracking-wider text-muted-foreground\"\n >\n Zone: {{ architectureInspectorNodeSafe.zoneLabel }}\n </span>\n </div>\n </div>\n\n <a\n v-if=\"\n architectureInspector.sourceAnchor?.label &&\n architectureInspector.sourceAnchor?.href\n \"\n :href=\"architectureInspector.sourceAnchor.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"inline-flex max-w-full items-center gap-1 rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground transition-colors hover:border-primary/45 hover:text-foreground\"\n >\n <span class=\"truncate\">{{ architectureInspector.sourceAnchor.label }}</span>\n </a>\n\n <p\n v-else-if=\"architectureInspector.sourceAnchor?.label\"\n class=\"inline-flex max-w-full items-center rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground\"\n >\n <span class=\"truncate\">{{ architectureInspector.sourceAnchor.label }}</span>\n </p>\n </div>\n\n <p\n v-if=\"architectureInspector.summary\"\n class=\"mt-1.5 text-[11px] text-muted-foreground leading-relaxed whitespace-pre-wrap break-words\"\n >\n {{ architectureInspector.summary }}\n </p>\n </div>\n\n <div class=\"min-h-0 flex-1 space-y-2 overflow-y-auto px-3 py-2.5\">\n <template v-if=\"architectureInspectorNode\">\n <div class=\"rounded-lg border border-border/60 bg-muted/20 px-2 py-1.5\">\n <p\n class=\"text-[9px] font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n Core\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.technology\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Technology: {{ architectureInspectorNodeSafe.technology }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.runtime\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Runtime: {{ architectureInspectorNodeSafe.runtime }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.owner\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Owner: {{ architectureInspectorNodeSafe.owner }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.operations?.slo\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n SLO: {{ architectureInspectorNodeSafe.operations.slo }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.operations?.alert\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Alert: {{ architectureInspectorNodeSafe.operations.alert }}\n </p>\n </div>\n\n <div\n v-if=\"\n architectureInspectorNodeSafe.security ||\n architectureInspectorNodeSafe.dataAssets.length > 0\n \"\n class=\"rounded-lg border border-border/60 bg-muted/20 px-2 py-1.5\"\n >\n <p\n class=\"text-[9px] font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n Data & Security\n </p>\n <template v-if=\"architectureInspectorNodeSafe.security\">\n <p\n v-if=\"architectureInspectorNodeSafe.security.auth\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Auth: {{ architectureInspectorNodeSafe.security.auth }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.security.encryption\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Encryption: {{ architectureInspectorNodeSafe.security.encryption }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.security.pii !== undefined\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n PII: {{ architectureInspectorNodeSafe.security.pii ? \"Yes\" : \"No\" }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.security.threatModel\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Threat Model: {{ architectureInspectorNodeSafe.security.threatModel }}\n </p>\n </template>\n\n <div\n v-if=\"architectureInspectorNodeSafe.dataAssets.length > 0\"\n class=\"mt-1.5 space-y-1\"\n >\n <p\n v-for=\"asset in architectureInspectorNodeSafe.dataAssets\"\n :key=\"`${asset.name}-${asset.kind ?? ''}`\"\n class=\"text-[10px] text-foreground\"\n >\n {{ asset.name }}<span v-if=\"asset.kind\"> ({{ asset.kind }})</span\n ><span v-if=\"asset.classification\"> - {{ asset.classification }}</span\n ><span v-if=\"asset.retention\"> - {{ asset.retention }}</span>\n </p>\n </div>\n </div>\n\n <div\n v-if=\"\n architectureInspectorNodeSafe.responsibilities.length > 0 ||\n architectureInspectorNodeSafe.capabilities.length > 0 ||\n architectureInspectorNodeSafe.tags.length > 0\n \"\n class=\"rounded-lg border border-border/60 bg-muted/20 px-2 py-1.5\"\n >\n <p\n class=\"text-[9px] font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n Capabilities\n </p>\n\n <div\n v-if=\"architectureInspectorNodeSafe.capabilities.length > 0\"\n class=\"mt-1 flex flex-wrap gap-1\"\n >\n <span\n v-for=\"capability in architectureInspectorNodeSafe.capabilities\"\n :key=\"capability\"\n class=\"inline-flex items-center rounded border border-primary/35 bg-primary/10 px-1.5 py-0.5 text-[9px] text-primary\"\n >\n {{ capability }}\n </span>\n </div>\n\n <div\n v-if=\"architectureInspectorNodeSafe.tags.length > 0\"\n class=\"mt-1 flex flex-wrap gap-1\"\n >\n <span\n v-for=\"tag in architectureInspectorNodeSafe.tags\"\n :key=\"tag\"\n class=\"inline-flex items-center rounded border border-border/70 bg-card/35 px-1.5 py-0.5 text-[9px] text-muted-foreground\"\n >\n #{{ tag }}\n </span>\n </div>\n\n <ul\n v-if=\"architectureInspectorNodeSafe.responsibilities.length > 0\"\n class=\"mt-1 space-y-0.5 text-[10px] text-foreground\"\n >\n <li v-for=\"item in architectureInspectorNodeSafe.responsibilities\" :key=\"item\">\n - {{ item }}\n </li>\n </ul>\n </div>\n\n <div\n v-if=\"\n architectureInspectorNodeSafe.interfaces.length > 0 ||\n architectureInspectorNodeSafe.outgoing.length > 0 ||\n architectureInspectorNodeSafe.links.length > 0 ||\n architectureInspectorNodeSafe.operations?.runbook\n \"\n class=\"rounded-lg border border-border/60 bg-muted/20 px-2 py-1.5\"\n >\n <p\n class=\"text-[9px] font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n Interfaces & Links\n </p>\n\n <div\n v-if=\"architectureInspectorNodeSafe.interfaces.length > 0\"\n class=\"mt-1 space-y-1\"\n >\n <p\n v-for=\"iface in architectureInspectorNodeSafe.interfaces\"\n :key=\"`${iface.name}-${iface.protocol ?? ''}-${iface.direction ?? ''}`\"\n class=\"text-[10px] text-foreground\"\n >\n {{ iface.name }}<span v-if=\"iface.protocol\"> ({{ iface.protocol }})</span\n ><span v-if=\"iface.direction\"> - {{ iface.direction }}</span\n ><span v-if=\"iface.auth\"> - auth: {{ iface.auth }}</span\n ><span v-if=\"iface.contract\"> - {{ iface.contract }}</span>\n </p>\n </div>\n\n <p\n v-if=\"architectureInspectorNodeSafe.operations?.runbook\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Runbook: {{ architectureInspectorNodeSafe.operations.runbook }}\n </p>\n\n <div\n v-if=\"architectureInspectorNodeSafe.outgoing.length > 0\"\n class=\"mt-1 space-y-1\"\n >\n <p\n v-for=\"edge in architectureInspectorNodeSafe.outgoing\"\n :key=\"`${edge.target}-${edge.label ?? ''}-${edge.protocol ?? ''}`\"\n class=\"text-[10px] text-foreground\"\n >\n {{ edge.label ?? \"Connect\" }} -> {{ edge.target\n }}<span v-if=\"edge.protocol\"> ({{ edge.protocol }})</span\n ><span v-if=\"edge.transport\"> - {{ edge.transport }}</span\n ><span v-if=\"edge.auth\"> - auth: {{ edge.auth }}</span\n ><span v-if=\"edge.criticality\"> - {{ edge.criticality }}</span>\n </p>\n </div>\n\n <div\n v-if=\"architectureInspectorNodeSafe.links.length > 0\"\n class=\"mt-1 flex flex-wrap gap-1\"\n >\n <a\n v-for=\"link in architectureInspectorNodeSafe.links\"\n :key=\"`${link.label}-${link.href}`\"\n :href=\"link.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"inline-flex items-center rounded border border-border/70 bg-card/35 px-1.5 py-0.5 text-[9px] text-foreground transition-colors hover:border-primary/45\"\n >\n {{ link.label }}\n </a>\n </div>\n </div>\n </template>\n </div>\n </div>\n </aside>\n </div>\n </div>\n </div>\n</template>\n","import { h } from \"vue\";\nimport type { ComponentFn, ComponentRegistry } from \"@json-render/vue\";\nimport { defineRegistry } from \"@json-render/vue\";\nimport { catalog, createFlaierCatalog } from \"./catalog\";\nimport FlowTimelineRenderer from \"./components/renderer/FlowTimelineRenderer.vue\";\nimport { createFlaierCustomRegistryComponents } from \"./custom-nodes\";\nimport type { FlaierCatalogOptions } from \"./types\";\n\nconst FlowTimelineComponent: ComponentFn<typeof catalog, \"FlowTimeline\"> = ({ props }) =>\n h(FlowTimelineRenderer, {\n title: props.title,\n description: props.description,\n mode: props.mode,\n zones: props.zones,\n direction: props.direction,\n minHeight: props.minHeight,\n layoutEngine: props.layoutEngine,\n layoutRankSep: props.layoutRankSep,\n layoutNodeSep: props.layoutNodeSep,\n layoutEdgeSep: props.layoutEdgeSep,\n themeMode: props.themeMode,\n showHeaderOverlay: props.showHeaderOverlay,\n showExportControls: props.showExportControls,\n showThemeToggle: props.showThemeToggle,\n showArchitectureInspector: props.showArchitectureInspector,\n defaultArchitectureInspectorOpen: props.defaultArchitectureInspectorOpen,\n showArchitectureInspectorToggleText: props.showArchitectureInspectorToggleText,\n });\n\nconst ArchitectureNodeComponent: ComponentFn<typeof catalog, \"ArchitectureNode\"> = () => null;\nconst TriggerNodeComponent: ComponentFn<typeof catalog, \"TriggerNode\"> = () => null;\nconst CodeNodeComponent: ComponentFn<typeof catalog, \"CodeNode\"> = () => null;\nconst DecisionNodeComponent: ComponentFn<typeof catalog, \"DecisionNode\"> = () => null;\nconst PayloadNodeComponent: ComponentFn<typeof catalog, \"PayloadNode\"> = () => null;\nconst ErrorNodeComponent: ComponentFn<typeof catalog, \"ErrorNode\"> = () => null;\nconst DescriptionNodeComponent: ComponentFn<typeof catalog, \"DescriptionNode\"> = () => null;\nconst LinkNodeComponent: ComponentFn<typeof catalog, \"LinkNode\"> = () => null;\n\nconst baseRegistryResult = defineRegistry(catalog, {\n components: {\n FlowTimeline: FlowTimelineComponent,\n ArchitectureNode: ArchitectureNodeComponent,\n TriggerNode: TriggerNodeComponent,\n CodeNode: CodeNodeComponent,\n DecisionNode: DecisionNodeComponent,\n PayloadNode: PayloadNodeComponent,\n ErrorNode: ErrorNodeComponent,\n DescriptionNode: DescriptionNodeComponent,\n LinkNode: LinkNodeComponent,\n },\n});\n\nexport const registry = baseRegistryResult.registry;\n\nexport function createFlaierRendererRegistry<\n TNodes extends NonNullable<FlaierCatalogOptions[\"nodes\"]>,\n>(options?: FlaierCatalogOptions<TNodes>): ComponentRegistry {\n return {\n ...registry,\n ...createFlaierCustomRegistryComponents(options?.nodes),\n };\n}\n\nexport function createFlaierRegistry<TNodes extends NonNullable<FlaierCatalogOptions[\"nodes\"]>>(\n options?: FlaierCatalogOptions<TNodes>,\n) {\n return {\n catalog: createFlaierCatalog(options),\n registry: createFlaierRendererRegistry(options),\n };\n}\n","<script setup lang=\"ts\">\nimport { ActionProvider, Renderer, StateProvider, VisibilityProvider } from \"@json-render/vue\";\nimport { autoFixSpec, formatSpecIssues, type Spec, validateSpec } from \"@json-render/core\";\nimport { computed, provide, ref, toRef, watch } from \"vue\";\nimport { flaierRuntimeKey } from \"../context\";\nimport { normalizeFlaierCustomNodes } from \"../custom-nodes\";\nimport { createFlaierRendererRegistry } from \"../registry\";\nimport type {\n FlaierFlowOption,\n FlaierManifest,\n FlaierManifestFlow,\n FlaierProps,\n FlaierSource,\n FlaierSpec,\n} from \"../types\";\n\nconst props = withDefaults(defineProps<FlaierProps>(), {\n autoPlay: false,\n interval: 3000,\n});\n\nconst emit = defineEmits<{\n loaded: [spec: FlaierSpec];\n \"load-error\": [message: string];\n \"state-change\": [changes: Array<{ path: string; value: unknown }>];\n}>();\n\ninterface ResolvedFlowDocument {\n id: string;\n title?: string;\n description?: string;\n tags?: string[];\n entrypoints?: string[];\n source: FlaierSpec | string;\n}\n\nconst resolvedSpec = ref<FlaierSpec | null>(null);\nconst loading = ref(false);\nconst loadError = ref<string | null>(null);\nconst specVersion = ref(0);\nconst flowDocuments = ref<ResolvedFlowDocument[]>([]);\nconst flowOptions = ref<FlaierFlowOption[]>([]);\nconst activeFlowId = ref<string | null>(null);\n\nlet sourceRequestId = 0;\nlet flowRequestId = 0;\n\nconst customNodes = computed(() => normalizeFlaierCustomNodes(props.nodes));\nconst rendererRegistry = computed(() => createFlaierRendererRegistry({ nodes: customNodes.value }));\n\nprovide(flaierRuntimeKey, {\n spec: resolvedSpec,\n interval: toRef(props, \"interval\"),\n nodes: customNodes,\n flowOptions,\n activeFlowId,\n setActiveFlow,\n});\n\nwatch(\n [() => props.src, () => props.themeMode],\n () => {\n void loadSourceCollection();\n },\n { immediate: true },\n);\n\nconst initialState = computed<Record<string, unknown>>(() => {\n const specState = (resolvedSpec.value?.state ?? {}) as Record<string, unknown>;\n const parsedCurrentStep = Number(specState.currentStep);\n\n return {\n ...specState,\n currentStep: Number.isFinite(parsedCurrentStep)\n ? Math.max(0, Math.floor(parsedCurrentStep))\n : 0,\n playing: props.autoPlay ? true : Boolean(specState.playing),\n };\n});\n\nconst providerKey = computed(() => {\n const spec = resolvedSpec.value;\n if (!spec) return \"flaier-empty\";\n return `${specVersion.value}-${spec.root}-${Object.keys(spec.elements).length}-${props.autoPlay ? \"auto\" : \"manual\"}-${props.themeMode ?? \"spec\"}`;\n});\n\nasync function loadSourceCollection() {\n const requestId = ++sourceRequestId;\n\n loading.value = true;\n loadError.value = null;\n resolvedSpec.value = null;\n\n try {\n const resolved = await resolveFlowDocuments(props.src);\n if (requestId !== sourceRequestId) return;\n\n if (resolved.flows.length === 0) {\n throw new Error(\"No flow specs were found in source.\");\n }\n\n flowDocuments.value = resolved.flows;\n syncFlowOptions();\n\n const nextActive = pickActiveFlowId(resolved.defaultFlowId);\n activeFlowId.value = nextActive;\n\n if (!nextActive) {\n resolvedSpec.value = null;\n return;\n }\n\n await loadFlowSpec(nextActive, requestId);\n } catch (error) {\n if (requestId !== sourceRequestId) return;\n\n const message = error instanceof Error ? error.message : \"Failed to load flaier source.\";\n\n loadError.value = message;\n resolvedSpec.value = null;\n flowDocuments.value = [];\n flowOptions.value = [];\n activeFlowId.value = null;\n emit(\"load-error\", message);\n } finally {\n if (requestId === sourceRequestId) {\n loading.value = false;\n }\n }\n}\n\nfunction pickActiveFlowId(defaultFlowId?: string) {\n if (defaultFlowId && flowDocuments.value.some((flow) => flow.id === defaultFlowId)) {\n return defaultFlowId;\n }\n\n const current = activeFlowId.value;\n if (current && flowDocuments.value.some((flow) => flow.id === current)) {\n return current;\n }\n\n return flowDocuments.value[0]?.id ?? null;\n}\n\nfunction setActiveFlow(flowId: string) {\n if (flowId === activeFlowId.value) return;\n if (!flowDocuments.value.some((flow) => flow.id === flowId)) return;\n\n activeFlowId.value = flowId;\n void activateFlow(flowId);\n}\n\nasync function activateFlow(flowId: string) {\n const sourceIdAtStart = sourceRequestId;\n\n loading.value = true;\n loadError.value = null;\n\n try {\n await loadFlowSpec(flowId, sourceIdAtStart);\n } catch (error) {\n if (sourceIdAtStart !== sourceRequestId) return;\n\n const message = error instanceof Error ? error.message : `Failed to load flow \"${flowId}\".`;\n\n loadError.value = message;\n resolvedSpec.value = null;\n emit(\"load-error\", message);\n } finally {\n if (sourceIdAtStart === sourceRequestId) {\n loading.value = false;\n }\n }\n}\n\nasync function loadFlowSpec(flowId: string, sourceIdAtStart: number) {\n const requestId = ++flowRequestId;\n const flow = flowDocuments.value.find((item) => item.id === flowId);\n\n if (!flow) {\n throw new Error(`Flow \"${flowId}\" was not found in loaded manifest.`);\n }\n\n const incoming = await resolveSpecSource(flow.source);\n if (sourceIdAtStart !== sourceRequestId || requestId !== flowRequestId) {\n return;\n }\n\n const fixed = autoFixSpec(incoming as Spec);\n const validation = validateSpec(fixed.spec);\n\n if (!validation.valid) {\n console.warn(`[flaier] Invalid spec:\\n${formatSpecIssues(validation.issues)}`);\n }\n\n const nextSpec = applyThemeModeOverride(fixed.spec as FlaierSpec);\n resolvedSpec.value = nextSpec;\n specVersion.value += 1;\n\n patchFlowMetadata(flowId, nextSpec);\n emit(\"loaded\", nextSpec);\n}\n\nasync function resolveFlowDocuments(source: FlaierSource) {\n if (typeof source !== \"string\") {\n if (isFlaierManifest(source)) {\n return normalizeManifest(source);\n }\n\n if (isFlaierSpec(source)) {\n return normalizeSingleSpec(cloneSpec(source));\n }\n\n throw new Error(\"Invalid flaier source object.\");\n }\n\n const { payload, resolvedUrl } = await fetchJsonSource(source);\n\n if (isFlaierManifest(payload)) {\n return normalizeManifest(payload, resolvedUrl);\n }\n\n if (isFlaierSpec(payload)) {\n return normalizeSingleSpec(cloneSpec(payload));\n }\n\n throw new Error(`Fetched JSON from \"${source}\" is neither a flow spec nor a manifest.`);\n}\n\nasync function resolveSpecSource(source: FlaierSpec | string): Promise<FlaierSpec> {\n if (typeof source !== \"string\") {\n return cloneSpec(source);\n }\n\n const { payload } = await fetchJsonSource(source);\n if (!isFlaierSpec(payload)) {\n throw new Error(`Fetched JSON from \"${source}\" is not a valid flow spec.`);\n }\n\n return cloneSpec(payload);\n}\n\nfunction normalizeSingleSpec(spec: FlaierSpec) {\n const metadata = getSpecMetadata(spec);\n\n return {\n flows: [\n {\n id: metadata.id,\n title: metadata.title,\n description: metadata.description,\n source: spec,\n },\n ] satisfies ResolvedFlowDocument[],\n defaultFlowId: metadata.id,\n };\n}\n\nfunction normalizeManifest(manifest: FlaierManifest, baseUrl?: string) {\n const seenIds = new Set<string>();\n const flows: ResolvedFlowDocument[] = [];\n\n for (const entry of manifest.flows) {\n const normalized = normalizeManifestEntry(entry, baseUrl);\n if (!normalized) continue;\n\n if (seenIds.has(normalized.id)) {\n throw new Error(`Duplicate flow id \"${normalized.id}\" in manifest.`);\n }\n\n seenIds.add(normalized.id);\n flows.push(normalized);\n }\n\n if (flows.length === 0) {\n throw new Error(\"Manifest does not contain any valid flows.\");\n }\n\n const defaultFlowId =\n typeof manifest.defaultFlowId === \"string\" && seenIds.has(manifest.defaultFlowId)\n ? manifest.defaultFlowId\n : flows[0]?.id;\n\n return {\n flows,\n defaultFlowId,\n };\n}\n\nfunction normalizeManifestEntry(\n entry: FlaierManifestFlow,\n baseUrl?: string,\n): ResolvedFlowDocument | null {\n const id = typeof entry.id === \"string\" ? entry.id.trim() : \"\";\n if (!id) return null;\n\n const resolvedSource = normalizeFlowSource(entry.src, baseUrl);\n if (!resolvedSource) {\n throw new Error(`Flow \"${id}\" has an invalid src value.`);\n }\n\n return {\n id,\n title: toOptionalString(entry.title),\n description: toOptionalString(entry.description),\n tags: toStringArray(entry.tags),\n entrypoints: toStringArray(entry.entrypoints),\n source: resolvedSource,\n };\n}\n\nfunction normalizeFlowSource(value: unknown, baseUrl?: string): FlaierSpec | string | null {\n if (typeof value === \"string\") {\n return resolveRelativeSource(value, baseUrl);\n }\n\n if (isFlaierSpec(value)) {\n return cloneSpec(value);\n }\n\n return null;\n}\n\nfunction syncFlowOptions() {\n flowOptions.value = flowDocuments.value.map((flow) => ({\n id: flow.id,\n title: flow.title ?? flow.id,\n description: flow.description,\n tags: flow.tags,\n entrypoints: flow.entrypoints,\n }));\n}\n\nfunction patchFlowMetadata(flowId: string, spec: FlaierSpec) {\n const metadata = getSpecMetadata(spec);\n let changed = false;\n\n flowDocuments.value = flowDocuments.value.map((flow) => {\n if (flow.id !== flowId) return flow;\n\n const nextTitle = flow.title ?? metadata.title;\n const nextDescription = flow.description ?? metadata.description;\n\n if (nextTitle === flow.title && nextDescription === flow.description) {\n return flow;\n }\n\n changed = true;\n return {\n ...flow,\n title: nextTitle,\n description: nextDescription,\n };\n });\n\n if (changed) {\n syncFlowOptions();\n }\n}\n\nfunction getSpecMetadata(spec: FlaierSpec) {\n const rootElement = spec.elements[spec.root];\n const rootProps = isObject(rootElement?.props) ? rootElement.props : {};\n const title = toOptionalString(rootProps.title);\n const description = toOptionalString(rootProps.description);\n const fallbackId = toOptionalString(spec.root) ?? \"flow\";\n\n return {\n id: slugifyId(title ?? fallbackId),\n title,\n description,\n };\n}\n\nfunction applyThemeModeOverride(spec: FlaierSpec): FlaierSpec {\n const override = props.themeMode;\n if (!override) {\n return spec;\n }\n\n const rootElement = spec.elements[spec.root];\n if (!rootElement || rootElement.type !== \"FlowTimeline\" || !isObject(rootElement.props)) {\n return spec;\n }\n\n if (rootElement.props.themeMode === override) {\n return spec;\n }\n\n return {\n ...spec,\n elements: {\n ...spec.elements,\n [spec.root]: {\n ...rootElement,\n props: {\n ...rootElement.props,\n themeMode: override,\n },\n },\n },\n };\n}\n\nfunction slugifyId(value: string) {\n const slug = value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n return slug || \"flow\";\n}\n\nfunction resolveRelativeSource(value: string, baseUrl?: string) {\n if (!baseUrl) return value;\n\n try {\n return new URL(value, baseUrl).toString();\n } catch {\n return value;\n }\n}\n\nfunction createFetchCandidates(source: string) {\n const trimmed = source.trim();\n if (!trimmed) return [];\n\n const hasJsonSuffix = /\\.json(?:[?#].*)?$/i.test(trimmed);\n const candidates: string[] = [trimmed];\n\n if (!hasJsonSuffix && !isLikelyFlowSpecEndpoint(trimmed)) {\n candidates.push(appendManifestJsonPath(trimmed));\n }\n\n return Array.from(new Set(candidates));\n}\n\nfunction isLikelyFlowSpecEndpoint(value: string) {\n return /\\/api\\/flows\\/spec\\/[^/?#]+(?:[?#].*)?$/i.test(value);\n}\n\nfunction appendManifestJsonPath(value: string) {\n const hashSplit = value.split(\"#\", 2);\n const pathAndQuery = hashSplit[0] ?? \"\";\n const hash = hashSplit[1] ?? \"\";\n\n const querySplit = pathAndQuery.split(\"?\", 2);\n const path = querySplit[0] ?? \"\";\n const query = querySplit[1] ?? \"\";\n\n const normalizedPath = path.endsWith(\"/\") ? path : `${path}/`;\n const manifestPath = `${normalizedPath}manifest.json`;\n const withQuery = query ? `${manifestPath}?${query}` : manifestPath;\n\n return hash ? `${withQuery}#${hash}` : withQuery;\n}\n\nasync function fetchJsonSource(source: string) {\n const candidates = createFetchCandidates(source);\n\n if (candidates.length === 0) {\n throw new Error(\"Flow source path cannot be empty.\");\n }\n\n let lastError: Error | null = null;\n\n for (const candidate of candidates) {\n try {\n const response = await fetch(candidate);\n if (!response.ok) {\n lastError = new Error(\n `Failed to fetch \"${candidate}\" (${response.status} ${response.statusText})`,\n );\n continue;\n }\n\n const payload = (await response.json()) as unknown;\n\n return {\n payload,\n resolvedUrl: resolveRelativeSource(\n candidate,\n typeof window !== \"undefined\" ? window.location.href : undefined,\n ),\n };\n } catch (error) {\n lastError =\n error instanceof Error ? error : new Error(`Failed to load source \"${candidate}\".`);\n }\n }\n\n throw lastError ?? new Error(`Failed to load source \"${source}\".`);\n}\n\nfunction cloneSpec(spec: FlaierSpec): FlaierSpec {\n return JSON.parse(JSON.stringify(spec)) as FlaierSpec;\n}\n\nfunction isFlaierManifest(value: unknown): value is FlaierManifest {\n if (!isObject(value)) return false;\n return Array.isArray(value.flows);\n}\n\nfunction isFlaierSpec(value: unknown): value is FlaierSpec {\n if (!isObject(value)) return false;\n if (typeof value.root !== \"string\") return false;\n if (!isObject(value.elements)) return false;\n return true;\n}\n\nfunction toOptionalString(value: unknown) {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\nfunction toStringArray(value: unknown) {\n if (!Array.isArray(value)) return undefined;\n\n const result = value.filter(\n (entry): entry is string => typeof entry === \"string\" && entry.length > 0,\n );\n return result.length > 0 ? result : undefined;\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction handleStateChange(changes: Array<{ path: string; value: unknown }>) {\n emit(\"state-change\", changes);\n}\n</script>\n\n<template>\n <div class=\"flaier relative h-full w-full min-h-[320px]\">\n <div\n v-if=\"loading\"\n class=\"flex h-full w-full items-center justify-center text-sm text-muted-foreground\"\n >\n Loading flow spec...\n </div>\n\n <div\n v-else-if=\"loadError\"\n class=\"flex h-full w-full items-center justify-center px-6 text-center text-sm text-red-300\"\n >\n {{ loadError }}\n </div>\n\n <StateProvider\n v-else-if=\"resolvedSpec\"\n :key=\"providerKey\"\n :initial-state=\"initialState\"\n :on-state-change=\"handleStateChange\"\n >\n <ActionProvider>\n <VisibilityProvider>\n <Renderer :spec=\"resolvedSpec\" :registry=\"rendererRegistry\" />\n </VisibilityProvider>\n </ActionProvider>\n </StateProvider>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { ActionProvider, Renderer, StateProvider, VisibilityProvider } from \"@json-render/vue\";\nimport { autoFixSpec, formatSpecIssues, type Spec, validateSpec } from \"@json-render/core\";\nimport { computed, provide, ref, toRef, watch } from \"vue\";\nimport { flaierRuntimeKey } from \"../context\";\nimport { normalizeFlaierCustomNodes } from \"../custom-nodes\";\nimport { createFlaierRendererRegistry } from \"../registry\";\nimport type {\n FlaierFlowOption,\n FlaierManifest,\n FlaierManifestFlow,\n FlaierProps,\n FlaierSource,\n FlaierSpec,\n} from \"../types\";\n\nconst props = withDefaults(defineProps<FlaierProps>(), {\n autoPlay: false,\n interval: 3000,\n});\n\nconst emit = defineEmits<{\n loaded: [spec: FlaierSpec];\n \"load-error\": [message: string];\n \"state-change\": [changes: Array<{ path: string; value: unknown }>];\n}>();\n\ninterface ResolvedFlowDocument {\n id: string;\n title?: string;\n description?: string;\n tags?: string[];\n entrypoints?: string[];\n source: FlaierSpec | string;\n}\n\nconst resolvedSpec = ref<FlaierSpec | null>(null);\nconst loading = ref(false);\nconst loadError = ref<string | null>(null);\nconst specVersion = ref(0);\nconst flowDocuments = ref<ResolvedFlowDocument[]>([]);\nconst flowOptions = ref<FlaierFlowOption[]>([]);\nconst activeFlowId = ref<string | null>(null);\n\nlet sourceRequestId = 0;\nlet flowRequestId = 0;\n\nconst customNodes = computed(() => normalizeFlaierCustomNodes(props.nodes));\nconst rendererRegistry = computed(() => createFlaierRendererRegistry({ nodes: customNodes.value }));\n\nprovide(flaierRuntimeKey, {\n spec: resolvedSpec,\n interval: toRef(props, \"interval\"),\n nodes: customNodes,\n flowOptions,\n activeFlowId,\n setActiveFlow,\n});\n\nwatch(\n [() => props.src, () => props.themeMode],\n () => {\n void loadSourceCollection();\n },\n { immediate: true },\n);\n\nconst initialState = computed<Record<string, unknown>>(() => {\n const specState = (resolvedSpec.value?.state ?? {}) as Record<string, unknown>;\n const parsedCurrentStep = Number(specState.currentStep);\n\n return {\n ...specState,\n currentStep: Number.isFinite(parsedCurrentStep)\n ? Math.max(0, Math.floor(parsedCurrentStep))\n : 0,\n playing: props.autoPlay ? true : Boolean(specState.playing),\n };\n});\n\nconst providerKey = computed(() => {\n const spec = resolvedSpec.value;\n if (!spec) return \"flaier-empty\";\n return `${specVersion.value}-${spec.root}-${Object.keys(spec.elements).length}-${props.autoPlay ? \"auto\" : \"manual\"}-${props.themeMode ?? \"spec\"}`;\n});\n\nasync function loadSourceCollection() {\n const requestId = ++sourceRequestId;\n\n loading.value = true;\n loadError.value = null;\n resolvedSpec.value = null;\n\n try {\n const resolved = await resolveFlowDocuments(props.src);\n if (requestId !== sourceRequestId) return;\n\n if (resolved.flows.length === 0) {\n throw new Error(\"No flow specs were found in source.\");\n }\n\n flowDocuments.value = resolved.flows;\n syncFlowOptions();\n\n const nextActive = pickActiveFlowId(resolved.defaultFlowId);\n activeFlowId.value = nextActive;\n\n if (!nextActive) {\n resolvedSpec.value = null;\n return;\n }\n\n await loadFlowSpec(nextActive, requestId);\n } catch (error) {\n if (requestId !== sourceRequestId) return;\n\n const message = error instanceof Error ? error.message : \"Failed to load flaier source.\";\n\n loadError.value = message;\n resolvedSpec.value = null;\n flowDocuments.value = [];\n flowOptions.value = [];\n activeFlowId.value = null;\n emit(\"load-error\", message);\n } finally {\n if (requestId === sourceRequestId) {\n loading.value = false;\n }\n }\n}\n\nfunction pickActiveFlowId(defaultFlowId?: string) {\n if (defaultFlowId && flowDocuments.value.some((flow) => flow.id === defaultFlowId)) {\n return defaultFlowId;\n }\n\n const current = activeFlowId.value;\n if (current && flowDocuments.value.some((flow) => flow.id === current)) {\n return current;\n }\n\n return flowDocuments.value[0]?.id ?? null;\n}\n\nfunction setActiveFlow(flowId: string) {\n if (flowId === activeFlowId.value) return;\n if (!flowDocuments.value.some((flow) => flow.id === flowId)) return;\n\n activeFlowId.value = flowId;\n void activateFlow(flowId);\n}\n\nasync function activateFlow(flowId: string) {\n const sourceIdAtStart = sourceRequestId;\n\n loading.value = true;\n loadError.value = null;\n\n try {\n await loadFlowSpec(flowId, sourceIdAtStart);\n } catch (error) {\n if (sourceIdAtStart !== sourceRequestId) return;\n\n const message = error instanceof Error ? error.message : `Failed to load flow \"${flowId}\".`;\n\n loadError.value = message;\n resolvedSpec.value = null;\n emit(\"load-error\", message);\n } finally {\n if (sourceIdAtStart === sourceRequestId) {\n loading.value = false;\n }\n }\n}\n\nasync function loadFlowSpec(flowId: string, sourceIdAtStart: number) {\n const requestId = ++flowRequestId;\n const flow = flowDocuments.value.find((item) => item.id === flowId);\n\n if (!flow) {\n throw new Error(`Flow \"${flowId}\" was not found in loaded manifest.`);\n }\n\n const incoming = await resolveSpecSource(flow.source);\n if (sourceIdAtStart !== sourceRequestId || requestId !== flowRequestId) {\n return;\n }\n\n const fixed = autoFixSpec(incoming as Spec);\n const validation = validateSpec(fixed.spec);\n\n if (!validation.valid) {\n console.warn(`[flaier] Invalid spec:\\n${formatSpecIssues(validation.issues)}`);\n }\n\n const nextSpec = applyThemeModeOverride(fixed.spec as FlaierSpec);\n resolvedSpec.value = nextSpec;\n specVersion.value += 1;\n\n patchFlowMetadata(flowId, nextSpec);\n emit(\"loaded\", nextSpec);\n}\n\nasync function resolveFlowDocuments(source: FlaierSource) {\n if (typeof source !== \"string\") {\n if (isFlaierManifest(source)) {\n return normalizeManifest(source);\n }\n\n if (isFlaierSpec(source)) {\n return normalizeSingleSpec(cloneSpec(source));\n }\n\n throw new Error(\"Invalid flaier source object.\");\n }\n\n const { payload, resolvedUrl } = await fetchJsonSource(source);\n\n if (isFlaierManifest(payload)) {\n return normalizeManifest(payload, resolvedUrl);\n }\n\n if (isFlaierSpec(payload)) {\n return normalizeSingleSpec(cloneSpec(payload));\n }\n\n throw new Error(`Fetched JSON from \"${source}\" is neither a flow spec nor a manifest.`);\n}\n\nasync function resolveSpecSource(source: FlaierSpec | string): Promise<FlaierSpec> {\n if (typeof source !== \"string\") {\n return cloneSpec(source);\n }\n\n const { payload } = await fetchJsonSource(source);\n if (!isFlaierSpec(payload)) {\n throw new Error(`Fetched JSON from \"${source}\" is not a valid flow spec.`);\n }\n\n return cloneSpec(payload);\n}\n\nfunction normalizeSingleSpec(spec: FlaierSpec) {\n const metadata = getSpecMetadata(spec);\n\n return {\n flows: [\n {\n id: metadata.id,\n title: metadata.title,\n description: metadata.description,\n source: spec,\n },\n ] satisfies ResolvedFlowDocument[],\n defaultFlowId: metadata.id,\n };\n}\n\nfunction normalizeManifest(manifest: FlaierManifest, baseUrl?: string) {\n const seenIds = new Set<string>();\n const flows: ResolvedFlowDocument[] = [];\n\n for (const entry of manifest.flows) {\n const normalized = normalizeManifestEntry(entry, baseUrl);\n if (!normalized) continue;\n\n if (seenIds.has(normalized.id)) {\n throw new Error(`Duplicate flow id \"${normalized.id}\" in manifest.`);\n }\n\n seenIds.add(normalized.id);\n flows.push(normalized);\n }\n\n if (flows.length === 0) {\n throw new Error(\"Manifest does not contain any valid flows.\");\n }\n\n const defaultFlowId =\n typeof manifest.defaultFlowId === \"string\" && seenIds.has(manifest.defaultFlowId)\n ? manifest.defaultFlowId\n : flows[0]?.id;\n\n return {\n flows,\n defaultFlowId,\n };\n}\n\nfunction normalizeManifestEntry(\n entry: FlaierManifestFlow,\n baseUrl?: string,\n): ResolvedFlowDocument | null {\n const id = typeof entry.id === \"string\" ? entry.id.trim() : \"\";\n if (!id) return null;\n\n const resolvedSource = normalizeFlowSource(entry.src, baseUrl);\n if (!resolvedSource) {\n throw new Error(`Flow \"${id}\" has an invalid src value.`);\n }\n\n return {\n id,\n title: toOptionalString(entry.title),\n description: toOptionalString(entry.description),\n tags: toStringArray(entry.tags),\n entrypoints: toStringArray(entry.entrypoints),\n source: resolvedSource,\n };\n}\n\nfunction normalizeFlowSource(value: unknown, baseUrl?: string): FlaierSpec | string | null {\n if (typeof value === \"string\") {\n return resolveRelativeSource(value, baseUrl);\n }\n\n if (isFlaierSpec(value)) {\n return cloneSpec(value);\n }\n\n return null;\n}\n\nfunction syncFlowOptions() {\n flowOptions.value = flowDocuments.value.map((flow) => ({\n id: flow.id,\n title: flow.title ?? flow.id,\n description: flow.description,\n tags: flow.tags,\n entrypoints: flow.entrypoints,\n }));\n}\n\nfunction patchFlowMetadata(flowId: string, spec: FlaierSpec) {\n const metadata = getSpecMetadata(spec);\n let changed = false;\n\n flowDocuments.value = flowDocuments.value.map((flow) => {\n if (flow.id !== flowId) return flow;\n\n const nextTitle = flow.title ?? metadata.title;\n const nextDescription = flow.description ?? metadata.description;\n\n if (nextTitle === flow.title && nextDescription === flow.description) {\n return flow;\n }\n\n changed = true;\n return {\n ...flow,\n title: nextTitle,\n description: nextDescription,\n };\n });\n\n if (changed) {\n syncFlowOptions();\n }\n}\n\nfunction getSpecMetadata(spec: FlaierSpec) {\n const rootElement = spec.elements[spec.root];\n const rootProps = isObject(rootElement?.props) ? rootElement.props : {};\n const title = toOptionalString(rootProps.title);\n const description = toOptionalString(rootProps.description);\n const fallbackId = toOptionalString(spec.root) ?? \"flow\";\n\n return {\n id: slugifyId(title ?? fallbackId),\n title,\n description,\n };\n}\n\nfunction applyThemeModeOverride(spec: FlaierSpec): FlaierSpec {\n const override = props.themeMode;\n if (!override) {\n return spec;\n }\n\n const rootElement = spec.elements[spec.root];\n if (!rootElement || rootElement.type !== \"FlowTimeline\" || !isObject(rootElement.props)) {\n return spec;\n }\n\n if (rootElement.props.themeMode === override) {\n return spec;\n }\n\n return {\n ...spec,\n elements: {\n ...spec.elements,\n [spec.root]: {\n ...rootElement,\n props: {\n ...rootElement.props,\n themeMode: override,\n },\n },\n },\n };\n}\n\nfunction slugifyId(value: string) {\n const slug = value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n return slug || \"flow\";\n}\n\nfunction resolveRelativeSource(value: string, baseUrl?: string) {\n if (!baseUrl) return value;\n\n try {\n return new URL(value, baseUrl).toString();\n } catch {\n return value;\n }\n}\n\nfunction createFetchCandidates(source: string) {\n const trimmed = source.trim();\n if (!trimmed) return [];\n\n const hasJsonSuffix = /\\.json(?:[?#].*)?$/i.test(trimmed);\n const candidates: string[] = [trimmed];\n\n if (!hasJsonSuffix && !isLikelyFlowSpecEndpoint(trimmed)) {\n candidates.push(appendManifestJsonPath(trimmed));\n }\n\n return Array.from(new Set(candidates));\n}\n\nfunction isLikelyFlowSpecEndpoint(value: string) {\n return /\\/api\\/flows\\/spec\\/[^/?#]+(?:[?#].*)?$/i.test(value);\n}\n\nfunction appendManifestJsonPath(value: string) {\n const hashSplit = value.split(\"#\", 2);\n const pathAndQuery = hashSplit[0] ?? \"\";\n const hash = hashSplit[1] ?? \"\";\n\n const querySplit = pathAndQuery.split(\"?\", 2);\n const path = querySplit[0] ?? \"\";\n const query = querySplit[1] ?? \"\";\n\n const normalizedPath = path.endsWith(\"/\") ? path : `${path}/`;\n const manifestPath = `${normalizedPath}manifest.json`;\n const withQuery = query ? `${manifestPath}?${query}` : manifestPath;\n\n return hash ? `${withQuery}#${hash}` : withQuery;\n}\n\nasync function fetchJsonSource(source: string) {\n const candidates = createFetchCandidates(source);\n\n if (candidates.length === 0) {\n throw new Error(\"Flow source path cannot be empty.\");\n }\n\n let lastError: Error | null = null;\n\n for (const candidate of candidates) {\n try {\n const response = await fetch(candidate);\n if (!response.ok) {\n lastError = new Error(\n `Failed to fetch \"${candidate}\" (${response.status} ${response.statusText})`,\n );\n continue;\n }\n\n const payload = (await response.json()) as unknown;\n\n return {\n payload,\n resolvedUrl: resolveRelativeSource(\n candidate,\n typeof window !== \"undefined\" ? window.location.href : undefined,\n ),\n };\n } catch (error) {\n lastError =\n error instanceof Error ? error : new Error(`Failed to load source \"${candidate}\".`);\n }\n }\n\n throw lastError ?? new Error(`Failed to load source \"${source}\".`);\n}\n\nfunction cloneSpec(spec: FlaierSpec): FlaierSpec {\n return JSON.parse(JSON.stringify(spec)) as FlaierSpec;\n}\n\nfunction isFlaierManifest(value: unknown): value is FlaierManifest {\n if (!isObject(value)) return false;\n return Array.isArray(value.flows);\n}\n\nfunction isFlaierSpec(value: unknown): value is FlaierSpec {\n if (!isObject(value)) return false;\n if (typeof value.root !== \"string\") return false;\n if (!isObject(value.elements)) return false;\n return true;\n}\n\nfunction toOptionalString(value: unknown) {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\nfunction toStringArray(value: unknown) {\n if (!Array.isArray(value)) return undefined;\n\n const result = value.filter(\n (entry): entry is string => typeof entry === \"string\" && entry.length > 0,\n );\n return result.length > 0 ? result : undefined;\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction handleStateChange(changes: Array<{ path: string; value: unknown }>) {\n emit(\"state-change\", changes);\n}\n</script>\n\n<template>\n <div class=\"flaier relative h-full w-full min-h-[320px]\">\n <div\n v-if=\"loading\"\n class=\"flex h-full w-full items-center justify-center text-sm text-muted-foreground\"\n >\n Loading flow spec...\n </div>\n\n <div\n v-else-if=\"loadError\"\n class=\"flex h-full w-full items-center justify-center px-6 text-center text-sm text-red-300\"\n >\n {{ loadError }}\n </div>\n\n <StateProvider\n v-else-if=\"resolvedSpec\"\n :key=\"providerKey\"\n :initial-state=\"initialState\"\n :on-state-change=\"handleStateChange\"\n >\n <ActionProvider>\n <VisibilityProvider>\n <Renderer :spec=\"resolvedSpec\" :registry=\"rendererRegistry\" />\n </VisibilityProvider>\n </ActionProvider>\n </StateProvider>\n </div>\n</template>\n","import { onUnmounted, ref, watch } from \"vue\";\n\nexport function useFlaierFullscreen() {\n const fullscreen = ref(false);\n let previousBodyOverflow = \"\";\n\n function closeFullscreen() {\n fullscreen.value = false;\n }\n\n function toggleFullscreen() {\n fullscreen.value = !fullscreen.value;\n }\n\n function handleEscape(event: KeyboardEvent) {\n if (event.key !== \"Escape\") return;\n closeFullscreen();\n }\n\n watch(fullscreen, (active) => {\n if (typeof document === \"undefined\") return;\n\n if (active) {\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n document.addEventListener(\"keydown\", handleEscape);\n return;\n }\n\n document.body.style.overflow = previousBodyOverflow;\n document.removeEventListener(\"keydown\", handleEscape);\n });\n\n onUnmounted(() => {\n if (typeof document === \"undefined\") return;\n\n document.body.style.overflow = previousBodyOverflow;\n document.removeEventListener(\"keydown\", handleEscape);\n });\n\n return {\n fullscreen,\n closeFullscreen,\n toggleFullscreen,\n };\n}\n","<script setup lang=\"ts\">\nimport { watch } from \"vue\";\nimport { computed } from \"vue\";\nimport Flaier from \"./Flaier.vue\";\nimport { useFlaierFullscreen } from \"../composables/useFlaierFullscreen\";\nimport type { FlaierPanelProps } from \"../types\";\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(defineProps<FlaierPanelProps>(), {\n autoPlay: false,\n interval: 3000,\n height: \"min(72vh, 760px)\",\n minHeight: 420,\n zIndex: 1400,\n fullscreenEnabled: true,\n});\n\nconst { fullscreen, closeFullscreen, toggleFullscreen } = useFlaierFullscreen();\n\nconst fullscreenActive = computed(() => props.fullscreenEnabled && fullscreen.value);\n\nconst containerStyle = computed<Record<string, string>>(() => {\n const minHeight = Number.isFinite(props.minHeight)\n ? Math.max(280, Math.floor(props.minHeight))\n : 420;\n\n return {\n \"--fn-panel-height\":\n typeof props.height === \"number\"\n ? `${Math.max(280, Math.floor(props.height))}px`\n : props.height,\n \"--fn-panel-min-height\": `${minHeight}px`,\n \"--fn-panel-z-index\": String(props.zIndex),\n };\n});\n\nwatch(\n () => props.fullscreenEnabled,\n (enabled) => {\n if (!enabled && fullscreen.value) {\n closeFullscreen();\n }\n },\n);\n</script>\n\n<template>\n <Teleport to=\"body\" :disabled=\"!fullscreenActive\">\n <div\n class=\"fn-panel\"\n :class=\"{ 'fn-panel--fullscreen': fullscreenActive }\"\n :style=\"containerStyle\"\n v-bind=\"$attrs\"\n >\n <button\n v-if=\"fullscreenActive\"\n type=\"button\"\n class=\"fn-panel__backdrop\"\n aria-label=\"Exit fullscreen\"\n @click=\"closeFullscreen\"\n />\n\n <div class=\"fn-panel__surface\">\n <Flaier\n class=\"fn-panel__viewer\"\n :src=\"src\"\n :auto-play=\"autoPlay\"\n :interval=\"interval\"\n :theme-mode=\"themeMode\"\n :nodes=\"nodes\"\n />\n\n <button\n v-if=\"fullscreenEnabled\"\n type=\"button\"\n class=\"fn-panel__toggle\"\n :aria-label=\"fullscreenActive ? 'Exit fullscreen' : 'Enter fullscreen'\"\n :title=\"fullscreenActive ? 'Exit fullscreen' : 'Enter fullscreen'\"\n @click=\"toggleFullscreen\"\n >\n <svg\n v-if=\"!fullscreenActive\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.8\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"15 3 21 3 21 9\" />\n <polyline points=\"9 21 3 21 3 15\" />\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n\n <svg\n v-else\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.8\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"14 10 21 3\" />\n <polyline points=\"10 14 3 21\" />\n <polyline points=\"3 9 3 3 9 3\" />\n <polyline points=\"15 21 21 21 21 15\" />\n </svg>\n </button>\n </div>\n </div>\n </Teleport>\n</template>\n\n<style scoped>\n.fn-panel {\n --fn-panel-height: min(72vh, 760px);\n --fn-panel-min-height: 420px;\n --fn-panel-z-index: 1400;\n --fn-panel-toggle-border: rgba(148, 163, 184, 0.5);\n --fn-panel-toggle-bg: rgba(15, 23, 42, 0.82);\n --fn-panel-toggle-color: rgba(226, 232, 240, 0.95);\n --fn-panel-toggle-shadow: 0 10px 26px rgba(15, 23, 42, 0.24);\n --fn-panel-toggle-hover-border: rgba(125, 211, 252, 0.7);\n --fn-panel-toggle-hover-bg: rgba(15, 23, 42, 0.96);\n --fn-panel-backdrop-bg: rgba(2, 6, 23, 0.72);\n position: relative;\n width: 100%;\n}\n\n.fn-panel__surface {\n position: relative;\n width: 100%;\n height: var(--fn-panel-height);\n min-height: var(--fn-panel-min-height);\n overflow: hidden;\n isolation: isolate;\n}\n\n.fn-panel__viewer {\n width: 100%;\n height: 100%;\n}\n\n.fn-panel__toggle {\n position: absolute;\n left: 0.95rem;\n bottom: 0.95rem;\n width: 2.3rem;\n height: 2.3rem;\n border: 1px solid var(--fn-panel-toggle-border);\n border-radius: 0.65rem;\n background: var(--fn-panel-toggle-bg);\n color: var(--fn-panel-toggle-color);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n z-index: 40;\n box-shadow: var(--fn-panel-toggle-shadow);\n transition:\n transform 0.18s ease,\n background-color 0.2s ease,\n border-color 0.2s ease;\n}\n\n.fn-panel__toggle:hover {\n transform: translateY(-1px);\n border-color: var(--fn-panel-toggle-hover-border);\n background: var(--fn-panel-toggle-hover-bg);\n}\n\n.fn-panel__toggle svg {\n width: 1rem;\n height: 1rem;\n}\n\n.fn-panel--fullscreen {\n position: fixed;\n inset: 0;\n z-index: var(--fn-panel-z-index);\n display: grid;\n place-items: center;\n padding: 1rem;\n}\n\n.fn-panel__backdrop {\n position: absolute;\n inset: 0;\n border: none;\n background: var(--fn-panel-backdrop-bg);\n cursor: default;\n}\n\n.fn-panel--fullscreen .fn-panel__surface {\n width: min(1480px, 100%);\n height: min(94vh, 1020px);\n max-height: 100%;\n z-index: 1;\n}\n\n@media (max-width: 900px) {\n .fn-panel--fullscreen {\n padding: 0.55rem;\n }\n\n .fn-panel--fullscreen .fn-panel__surface {\n width: 100%;\n height: 100%;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { watch } from \"vue\";\nimport { computed } from \"vue\";\nimport Flaier from \"./Flaier.vue\";\nimport { useFlaierFullscreen } from \"../composables/useFlaierFullscreen\";\nimport type { FlaierPanelProps } from \"../types\";\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(defineProps<FlaierPanelProps>(), {\n autoPlay: false,\n interval: 3000,\n height: \"min(72vh, 760px)\",\n minHeight: 420,\n zIndex: 1400,\n fullscreenEnabled: true,\n});\n\nconst { fullscreen, closeFullscreen, toggleFullscreen } = useFlaierFullscreen();\n\nconst fullscreenActive = computed(() => props.fullscreenEnabled && fullscreen.value);\n\nconst containerStyle = computed<Record<string, string>>(() => {\n const minHeight = Number.isFinite(props.minHeight)\n ? Math.max(280, Math.floor(props.minHeight))\n : 420;\n\n return {\n \"--fn-panel-height\":\n typeof props.height === \"number\"\n ? `${Math.max(280, Math.floor(props.height))}px`\n : props.height,\n \"--fn-panel-min-height\": `${minHeight}px`,\n \"--fn-panel-z-index\": String(props.zIndex),\n };\n});\n\nwatch(\n () => props.fullscreenEnabled,\n (enabled) => {\n if (!enabled && fullscreen.value) {\n closeFullscreen();\n }\n },\n);\n</script>\n\n<template>\n <Teleport to=\"body\" :disabled=\"!fullscreenActive\">\n <div\n class=\"fn-panel\"\n :class=\"{ 'fn-panel--fullscreen': fullscreenActive }\"\n :style=\"containerStyle\"\n v-bind=\"$attrs\"\n >\n <button\n v-if=\"fullscreenActive\"\n type=\"button\"\n class=\"fn-panel__backdrop\"\n aria-label=\"Exit fullscreen\"\n @click=\"closeFullscreen\"\n />\n\n <div class=\"fn-panel__surface\">\n <Flaier\n class=\"fn-panel__viewer\"\n :src=\"src\"\n :auto-play=\"autoPlay\"\n :interval=\"interval\"\n :theme-mode=\"themeMode\"\n :nodes=\"nodes\"\n />\n\n <button\n v-if=\"fullscreenEnabled\"\n type=\"button\"\n class=\"fn-panel__toggle\"\n :aria-label=\"fullscreenActive ? 'Exit fullscreen' : 'Enter fullscreen'\"\n :title=\"fullscreenActive ? 'Exit fullscreen' : 'Enter fullscreen'\"\n @click=\"toggleFullscreen\"\n >\n <svg\n v-if=\"!fullscreenActive\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.8\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"15 3 21 3 21 9\" />\n <polyline points=\"9 21 3 21 3 15\" />\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n\n <svg\n v-else\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.8\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"14 10 21 3\" />\n <polyline points=\"10 14 3 21\" />\n <polyline points=\"3 9 3 3 9 3\" />\n <polyline points=\"15 21 21 21 21 15\" />\n </svg>\n </button>\n </div>\n </div>\n </Teleport>\n</template>\n\n<style scoped>\n.fn-panel {\n --fn-panel-height: min(72vh, 760px);\n --fn-panel-min-height: 420px;\n --fn-panel-z-index: 1400;\n --fn-panel-toggle-border: rgba(148, 163, 184, 0.5);\n --fn-panel-toggle-bg: rgba(15, 23, 42, 0.82);\n --fn-panel-toggle-color: rgba(226, 232, 240, 0.95);\n --fn-panel-toggle-shadow: 0 10px 26px rgba(15, 23, 42, 0.24);\n --fn-panel-toggle-hover-border: rgba(125, 211, 252, 0.7);\n --fn-panel-toggle-hover-bg: rgba(15, 23, 42, 0.96);\n --fn-panel-backdrop-bg: rgba(2, 6, 23, 0.72);\n position: relative;\n width: 100%;\n}\n\n.fn-panel__surface {\n position: relative;\n width: 100%;\n height: var(--fn-panel-height);\n min-height: var(--fn-panel-min-height);\n overflow: hidden;\n isolation: isolate;\n}\n\n.fn-panel__viewer {\n width: 100%;\n height: 100%;\n}\n\n.fn-panel__toggle {\n position: absolute;\n left: 0.95rem;\n bottom: 0.95rem;\n width: 2.3rem;\n height: 2.3rem;\n border: 1px solid var(--fn-panel-toggle-border);\n border-radius: 0.65rem;\n background: var(--fn-panel-toggle-bg);\n color: var(--fn-panel-toggle-color);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n z-index: 40;\n box-shadow: var(--fn-panel-toggle-shadow);\n transition:\n transform 0.18s ease,\n background-color 0.2s ease,\n border-color 0.2s ease;\n}\n\n.fn-panel__toggle:hover {\n transform: translateY(-1px);\n border-color: var(--fn-panel-toggle-hover-border);\n background: var(--fn-panel-toggle-hover-bg);\n}\n\n.fn-panel__toggle svg {\n width: 1rem;\n height: 1rem;\n}\n\n.fn-panel--fullscreen {\n position: fixed;\n inset: 0;\n z-index: var(--fn-panel-z-index);\n display: grid;\n place-items: center;\n padding: 1rem;\n}\n\n.fn-panel__backdrop {\n position: absolute;\n inset: 0;\n border: none;\n background: var(--fn-panel-backdrop-bg);\n cursor: default;\n}\n\n.fn-panel--fullscreen .fn-panel__surface {\n width: min(1480px, 100%);\n height: min(94vh, 1020px);\n max-height: 100%;\n z-index: 1;\n}\n\n@media (max-width: 900px) {\n .fn-panel--fullscreen {\n padding: 0.55rem;\n }\n\n .fn-panel--fullscreen .fn-panel__surface {\n width: 100%;\n height: 100%;\n }\n}\n</style>\n","import { computed, watch, onUnmounted, ref } from \"vue\";\nimport type { Ref } from \"vue\";\n\ninterface TimelineOptions {\n totalSteps: Ref<number>;\n interval?: number;\n}\n\n/**\n * Timeline playback controls.\n * Manages currentStep, playing state, and auto-advance logic.\n */\nexport function useTimeline(options: TimelineOptions) {\n const { totalSteps, interval = 3000 } = options;\n\n const currentStep = ref(0);\n const playing = ref(false);\n\n let timer: ReturnType<typeof setInterval> | null = null;\n\n function clearTimer() {\n if (timer !== null) {\n clearInterval(timer);\n timer = null;\n }\n }\n\n watch(playing, (isPlaying) => {\n clearTimer();\n if (isPlaying) {\n timer = setInterval(() => {\n if (currentStep.value < totalSteps.value - 1) {\n currentStep.value++;\n } else {\n playing.value = false;\n }\n }, interval);\n }\n });\n\n onUnmounted(clearTimer);\n\n const progress = computed(() =>\n totalSteps.value > 1 ? currentStep.value / (totalSteps.value - 1) : 0,\n );\n\n return {\n currentStep,\n playing,\n totalSteps,\n progress,\n\n next() {\n if (currentStep.value < totalSteps.value - 1) {\n currentStep.value++;\n }\n },\n prev() {\n if (currentStep.value > 0) {\n currentStep.value--;\n }\n },\n goTo(step: number) {\n currentStep.value = Math.max(0, Math.min(step, totalSteps.value - 1));\n },\n togglePlay() {\n playing.value = !playing.value;\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["FlowTimelineRenderer","$attrs"],"sources":["../src/context.ts","../src/custom-nodes.ts","../src/catalog.ts","../src/code-node-sizing.ts","../src/composables/useDiagramExport.ts","../src/composables/useFlaierRuntime.ts","../src/twoslash.ts","../src/components/controls/TimelineControls.vue","../src/components/controls/TimelineControls.vue","../src/components/edges/ArchitectureSmoothEdge.vue","../src/components/edges/ArchitectureSmoothEdge.vue","../src/components/nodes/NodeSourceAnchor.vue","../src/components/nodes/NodeSourceAnchor.vue","../src/components/nodes/ArchitectureNode.vue","../src/components/nodes/ArchitectureNode.vue","../src/composables/useShiki.ts","../src/components/nodes/CodeNode.vue","../src/components/nodes/CodeNode.vue","../src/components/nodes/DecisionNode.vue","../src/components/nodes/DecisionNode.vue","../src/components/nodes/DescriptionNode.vue","../src/components/nodes/DescriptionNode.vue","../src/components/nodes/ErrorNode.vue","../src/components/nodes/ErrorNode.vue","../src/components/nodes/LinkNode.vue","../src/components/nodes/LinkNode.vue","../src/components/nodes/PayloadNode.vue","../src/components/nodes/PayloadNode.vue","../src/components/nodes/TriggerNode.vue","../src/components/nodes/TriggerNode.vue","../src/components/renderer/FlowTimelineRenderer.vue","../src/components/renderer/FlowTimelineRenderer.vue","../src/registry.ts","../src/components/Flaier.vue","../src/components/Flaier.vue","../src/composables/useFlaierFullscreen.ts","../src/components/FlaierPanel.vue","../src/components/FlaierPanel.vue","../src/composables/useTimeline.ts"],"sourcesContent":["import type { InjectionKey, Ref } from \"vue\";\nimport type { FlaierCustomNodeDefinitions, FlaierFlowOption, FlaierSpec } from \"./types\";\n\nexport interface FlaierRuntimeContext {\n spec: Ref<FlaierSpec | null>;\n interval: Ref<number>;\n nodes: Ref<FlaierCustomNodeDefinitions>;\n flowOptions: Ref<FlaierFlowOption[]>;\n activeFlowId: Ref<string | null>;\n viewportResetToken: Ref<number>;\n setActiveFlow: (flowId: string) => void;\n}\n\nexport const flaierRuntimeKey: InjectionKey<FlaierRuntimeContext> = Symbol(\"flaier-runtime\");\n","import { defineComponent, markRaw, type Component } from \"vue\";\nimport type { FlaierCustomNodeDefinition, FlaierCustomNodeDefinitions } from \"./types\";\n\nconst RESERVED_FLAIER_NODE_NAMES = new Set([\n \"FlowTimeline\",\n \"ArchitectureNode\",\n \"TriggerNode\",\n \"CodeNode\",\n \"DecisionNode\",\n \"PayloadNode\",\n \"ErrorNode\",\n \"DescriptionNode\",\n \"LinkNode\",\n]);\n\nconst FlaierNullNode = defineComponent({\n name: \"FlaierNullNode\",\n setup() {\n return () => null;\n },\n});\n\nfunction normalizeFlaierCustomNodeDefinition(\n definition: FlaierCustomNodeDefinition,\n): FlaierCustomNodeDefinition {\n return {\n ...definition,\n component: markRaw(definition.component) as Component,\n };\n}\n\nexport function normalizeFlaierCustomNodes(\n nodes?: FlaierCustomNodeDefinitions,\n): FlaierCustomNodeDefinitions {\n if (!nodes) {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(nodes)\n .filter(([name]) => {\n if (!RESERVED_FLAIER_NODE_NAMES.has(name)) {\n return true;\n }\n\n console.warn(`[flaier] Ignoring custom node \"${name}\" because the name is reserved.`);\n return false;\n })\n .map(([name, definition]) => [name, normalizeFlaierCustomNodeDefinition(definition)]),\n );\n}\n\nexport function mergeFlaierCustomNodes(\n ...sources: Array<FlaierCustomNodeDefinitions | undefined>\n): FlaierCustomNodeDefinitions {\n return sources.reduce<FlaierCustomNodeDefinitions>((result, source) => {\n if (!source) {\n return result;\n }\n\n return {\n ...result,\n ...normalizeFlaierCustomNodes(source),\n };\n }, {});\n}\n\nexport function createFlaierCustomCatalogComponents(nodes?: FlaierCustomNodeDefinitions) {\n const normalizedNodes = normalizeFlaierCustomNodes(nodes);\n\n if (Object.keys(normalizedNodes).length === 0) {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(normalizedNodes).map(([name, definition]) => [\n name,\n {\n props: definition.props,\n description: definition.description,\n },\n ]),\n );\n}\n\nexport function createFlaierCustomRegistryComponents(nodes?: FlaierCustomNodeDefinitions) {\n const normalizedNodes = normalizeFlaierCustomNodes(nodes);\n\n if (Object.keys(normalizedNodes).length === 0) {\n return {};\n }\n\n return Object.fromEntries(\n Object.keys(normalizedNodes).map((name) => [name, FlaierNullNode]),\n ) as Record<string, Component>;\n}\n","import { defineCatalog } from \"@json-render/core\";\nimport { schema } from \"@json-render/vue\";\nimport { z } from \"zod\";\nimport { createFlaierCustomCatalogComponents } from \"./custom-nodes\";\nimport type { FlaierCatalogOptions } from \"./types\";\n\nexport const magicMoveStepSchema = z.object({\n code: z.string(),\n title: z.string().optional(),\n comment: z.string().optional(),\n story: z.string().optional(),\n speaker: z.string().optional(),\n});\n\nexport const twoslashHtmlSchema = z\n .object({\n dark: z.string().optional(),\n light: z.string().optional(),\n })\n .optional();\n\nexport const edgeTransitionKindSchema = z.enum([\n \"default\",\n \"success\",\n \"error\",\n \"warning\",\n \"retry\",\n \"async\",\n]);\n\nexport const edgeTransitionSchema = z.object({\n to: z.string(),\n label: z.string().optional(),\n description: z.string().optional(),\n kind: edgeTransitionKindSchema.optional(),\n protocol: z.string().optional(),\n transport: z.enum([\"sync\", \"async\"]).optional(),\n auth: z.string().optional(),\n contract: z.string().optional(),\n criticality: z.enum([\"low\", \"medium\", \"high\"]).optional(),\n});\n\nexport const sourceAnchorSchema = z.union([\n z.string(),\n z.object({\n path: z.string(),\n line: z.number().int().positive().optional(),\n column: z.number().int().positive().optional(),\n label: z.string().optional(),\n href: z.string().optional(),\n }),\n]);\n\nexport const architectureZoneSchema = z.object({\n id: z.string(),\n label: z.string(),\n description: z.string().optional(),\n color: z.string().optional(),\n padding: z.number().positive().optional(),\n});\n\nexport const architectureInterfaceSchema = z.object({\n name: z.string(),\n protocol: z.string().optional(),\n direction: z.enum([\"inbound\", \"outbound\", \"bidirectional\"]).optional(),\n contract: z.string().optional(),\n auth: z.string().optional(),\n notes: z.string().optional(),\n});\n\nexport const architectureDataAssetSchema = z.object({\n name: z.string(),\n kind: z.string().optional(),\n classification: z.enum([\"public\", \"internal\", \"confidential\", \"restricted\"]).optional(),\n retention: z.string().optional(),\n notes: z.string().optional(),\n});\n\nexport const architectureSecuritySchema = z.object({\n auth: z.string().optional(),\n encryption: z.string().optional(),\n pii: z.boolean().optional(),\n threatModel: z.string().optional(),\n});\n\nexport const architectureOperationsSchema = z.object({\n owner: z.string().optional(),\n slo: z.string().optional(),\n alert: z.string().optional(),\n runbook: z.string().optional(),\n});\n\nexport const architectureLinkSchema = z.object({\n label: z.string(),\n href: z.string(),\n});\n\nexport const flaierCatalogComponents = {\n components: {\n FlowTimeline: {\n props: z.object({\n title: z.string(),\n description: z.string().optional(),\n mode: z.enum([\"narrative\", \"architecture\"]).default(\"narrative\"),\n zones: z.array(architectureZoneSchema).optional(),\n direction: z.enum([\"horizontal\", \"vertical\"]).default(\"horizontal\"),\n minHeight: z.number().int().positive().optional(),\n layoutEngine: z.enum([\"dagre\", \"manual\"]).default(\"dagre\"),\n layoutRankSep: z.number().positive().optional(),\n layoutNodeSep: z.number().positive().optional(),\n layoutEdgeSep: z.number().positive().optional(),\n themeMode: z.enum([\"local\", \"document\"]).optional(),\n showHeaderOverlay: z.boolean().optional(),\n showExportControls: z.boolean().optional(),\n showThemeToggle: z.boolean().optional(),\n showArchitectureInspector: z.boolean().optional(),\n defaultArchitectureInspectorOpen: z.boolean().optional(),\n showArchitectureInspectorToggleText: z.boolean().optional(),\n }),\n description: \"Root timeline container that orchestrates a pipeline flow graph\",\n slots: [\"default\"],\n },\n ArchitectureNode: {\n props: z.object({\n label: z.string(),\n kind: z\n .enum([\"service\", \"database\", \"queue\", \"cache\", \"gateway\", \"external\", \"compute\"])\n .default(\"service\"),\n technology: z.string().optional(),\n runtime: z.string().optional(),\n owner: z.string().optional(),\n tier: z\n .enum([\"edge\", \"application\", \"integration\", \"data\", \"platform\", \"external\"])\n .optional(),\n status: z.enum([\"planned\", \"active\", \"degraded\", \"retired\"]).optional(),\n zone: z.string().optional(),\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n responsibilities: z.array(z.string()).optional(),\n capabilities: z.array(z.string()).optional(),\n interfaces: z.array(architectureInterfaceSchema).optional(),\n data: z.array(architectureDataAssetSchema).optional(),\n security: architectureSecuritySchema.optional(),\n operations: architectureOperationsSchema.optional(),\n links: z.array(architectureLinkSchema).optional(),\n sourceAnchor: sourceAnchorSchema.optional(),\n transitions: z.array(edgeTransitionSchema).optional(),\n }),\n description: \"Architecture/infrastructure component node for system diagrams\",\n },\n TriggerNode: {\n props: z.object({\n label: z.string(),\n description: z.string().optional(),\n color: z.string().default(\"#22c55e\"),\n sourceAnchor: sourceAnchorSchema.optional(),\n transitions: z.array(edgeTransitionSchema).optional(),\n }),\n description: \"Entry point node representing a trigger (cron, webhook, event)\",\n },\n CodeNode: {\n props: z.object({\n label: z.string(),\n file: z.string().optional(),\n sourceAnchor: sourceAnchorSchema.optional(),\n language: z.string().default(\"typescript\"),\n code: z.string(),\n comment: z.string().optional(),\n story: z.string().optional(),\n wrapLongLines: z.boolean().default(false),\n magicMoveSteps: z.array(magicMoveStepSchema).optional(),\n twoslash: z.boolean().optional(),\n twoslashHtml: twoslashHtmlSchema,\n transitions: z.array(edgeTransitionSchema).optional(),\n }),\n description:\n \"Code block with syntax highlighting, step-by-step magic-move transitions, optional twoslash callouts, and narration/story beats\",\n },\n DecisionNode: {\n props: z.object({\n label: z.string(),\n condition: z.string().optional(),\n description: z.string().optional(),\n sourceAnchor: sourceAnchorSchema.optional(),\n transitions: z.array(edgeTransitionSchema).optional(),\n }),\n description: \"Branch decision node that explains routing criteria before fan-out paths\",\n },\n PayloadNode: {\n props: z.object({\n label: z.string(),\n payload: z.string().optional(),\n before: z.string().optional(),\n after: z.string().optional(),\n format: z.enum([\"json\", \"yaml\", \"text\"]).default(\"json\"),\n description: z.string().optional(),\n sourceAnchor: sourceAnchorSchema.optional(),\n transitions: z.array(edgeTransitionSchema).optional(),\n }),\n description: \"Data-focused node for payload snapshots and before/after transformations\",\n },\n ErrorNode: {\n props: z.object({\n label: z.string(),\n message: z.string(),\n code: z.string().optional(),\n cause: z.string().optional(),\n mitigation: z.string().optional(),\n sourceAnchor: sourceAnchorSchema.optional(),\n transitions: z.array(edgeTransitionSchema).optional(),\n }),\n description: \"Failure node that captures error detail, cause, and recovery guidance\",\n },\n DescriptionNode: {\n props: z.object({\n label: z.string(),\n body: z.string(),\n sourceAnchor: sourceAnchorSchema.optional(),\n transitions: z.array(edgeTransitionSchema).optional(),\n }),\n description: \"Prose/text explanation node for documenting a pipeline step\",\n },\n LinkNode: {\n props: z.object({\n label: z.string(),\n href: z.string(),\n description: z.string().optional(),\n sourceAnchor: sourceAnchorSchema.optional(),\n transitions: z.array(edgeTransitionSchema).optional(),\n }),\n description: \"Clickable reference link to a file or URL\",\n },\n },\n};\n\nexport const catalog = defineCatalog(schema, {\n components: flaierCatalogComponents.components,\n actions: {},\n});\n\nexport function createFlaierCatalog<TNodes extends NonNullable<FlaierCatalogOptions[\"nodes\"]>>(\n options?: FlaierCatalogOptions<TNodes>,\n) {\n return defineCatalog(schema, {\n components: {\n ...flaierCatalogComponents.components,\n ...createFlaierCustomCatalogComponents(options?.nodes),\n },\n actions: {},\n });\n}\n","const CODE_NODE_MIN_WIDTH = 520;\nconst CODE_NODE_MAX_WIDTH = 2200;\nconst CODE_NODE_CHARACTER_WIDTH = 8.5;\nconst CODE_NODE_CHROME_WIDTH = 88;\n\nexport const CODE_NODE_MAX_INLINE_CHARS = Math.floor(\n (CODE_NODE_MAX_WIDTH - CODE_NODE_CHROME_WIDTH) / CODE_NODE_CHARACTER_WIDTH,\n);\n\nexport function estimateCodeNodeWidth(maxLineLength: number) {\n const safeLineLength = Number.isFinite(maxLineLength)\n ? Math.max(0, Math.floor(maxLineLength))\n : 0;\n\n const estimatedWidth = CODE_NODE_CHROME_WIDTH + safeLineLength * CODE_NODE_CHARACTER_WIDTH;\n\n return Math.min(CODE_NODE_MAX_WIDTH, Math.max(CODE_NODE_MIN_WIDTH, Math.ceil(estimatedWidth)));\n}\n\nexport function estimateCodeNodeCharsPerLine(nodeWidth: number) {\n const safeWidth = Number.isFinite(nodeWidth)\n ? Math.max(CODE_NODE_MIN_WIDTH, Math.floor(nodeWidth))\n : CODE_NODE_MIN_WIDTH;\n\n return Math.max(44, Math.floor((safeWidth - CODE_NODE_CHROME_WIDTH) / CODE_NODE_CHARACTER_WIDTH));\n}\n","export interface DiagramBounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport type DiagramExportFormat = \"png\" | \"pdf\";\n\nexport interface ExportFlowDiagramOptions {\n flowElement: HTMLElement;\n theme: \"dark\" | \"light\";\n bounds: DiagramBounds;\n fileNameBase: string;\n format: DiagramExportFormat;\n}\n\nconst EXPORT_PADDING_PX = 72;\nconst MAX_EXPORT_SIDE_PX = 6000;\nconst MAX_EXPORT_AREA_PX = 26_000_000;\n\nexport async function exportFlowDiagram(options: ExportFlowDiagramOptions) {\n if (typeof document === \"undefined\" || typeof window === \"undefined\") {\n throw new Error(\"Diagram export is only available in the browser.\");\n }\n\n const normalizedBounds = normalizeBounds(options.bounds);\n if (!normalizedBounds) {\n throw new Error(\"Diagram has no measurable bounds to export.\");\n }\n\n const capture = createCaptureStage({\n flowElement: options.flowElement,\n theme: options.theme,\n bounds: normalizedBounds,\n });\n\n let pngDataUrl = \"\";\n\n try {\n const { toPng } = await import(\"html-to-image\");\n\n await settleCaptureStage();\n\n pngDataUrl = await toPng(capture.stage, {\n width: capture.width,\n height: capture.height,\n pixelRatio: resolveExportPixelRatio(capture.width, capture.height),\n backgroundColor: capture.backgroundColor,\n cacheBust: true,\n });\n } finally {\n capture.destroy();\n }\n\n const safeBaseName = sanitizeFileName(options.fileNameBase || \"flow-diagram\");\n\n if (options.format === \"png\") {\n downloadDataUrl(pngDataUrl, `${safeBaseName}.png`);\n return;\n }\n\n const pdfBlob = await renderPdfBlob(pngDataUrl, capture.width, capture.height);\n downloadBlob(pdfBlob, `${safeBaseName}.pdf`);\n}\n\nfunction createCaptureStage({\n flowElement,\n theme,\n bounds,\n}: {\n flowElement: HTMLElement;\n theme: \"dark\" | \"light\";\n bounds: Required<DiagramBounds>;\n}) {\n const width = Math.ceil(bounds.width + EXPORT_PADDING_PX * 2);\n const height = Math.ceil(bounds.height + EXPORT_PADDING_PX * 2);\n const sourceRoot = flowElement.closest(\".flaier\") as HTMLElement | null;\n const sourceStyles = getComputedStyle(sourceRoot ?? flowElement);\n const wrapper = document.createElement(\"div\");\n wrapper.style.position = \"fixed\";\n wrapper.style.left = \"-100000px\";\n wrapper.style.top = \"0\";\n wrapper.style.width = \"0\";\n wrapper.style.height = \"0\";\n wrapper.style.overflow = \"hidden\";\n wrapper.style.pointerEvents = \"none\";\n\n const stage = document.createElement(\"div\");\n stage.className = \"flaier\";\n stage.dataset.theme = theme;\n stage.style.position = \"relative\";\n stage.style.width = `${width}px`;\n stage.style.height = `${height}px`;\n stage.style.overflow = \"hidden\";\n stage.style.pointerEvents = \"none\";\n\n for (let index = 0; index < sourceStyles.length; index += 1) {\n const key = sourceStyles.item(index);\n if (!key.startsWith(\"--\")) continue;\n\n const value = sourceStyles.getPropertyValue(key);\n if (!value) continue;\n stage.style.setProperty(key, value);\n }\n\n const backgroundColor = sourceStyles.getPropertyValue(\"--color-background\").trim() || \"#0b1120\";\n stage.style.background = backgroundColor;\n\n const flowClone = flowElement.cloneNode(true) as HTMLElement;\n flowClone.style.width = `${width}px`;\n flowClone.style.height = `${height}px`;\n flowClone.style.margin = \"0\";\n\n inlineSvgPresentationStyles(flowElement, flowClone);\n\n const transformPane = (flowClone.querySelector(\".vue-flow__transformationpane\") ??\n flowClone.querySelector(\".vue-flow__viewport\")) as HTMLElement | null;\n const exportTransform = `translate(${Math.round(EXPORT_PADDING_PX - bounds.x)}px, ${Math.round(EXPORT_PADDING_PX - bounds.y)}px) scale(1)`;\n\n if (transformPane) {\n transformPane.style.transformOrigin = \"0 0\";\n transformPane.style.transform = exportTransform;\n transformPane.style.opacity = \"1\";\n }\n\n const zoneOverlays = flowClone.querySelectorAll<HTMLElement>('[data-zone-overlay=\"true\"]');\n for (const overlay of zoneOverlays) {\n overlay.style.transformOrigin = \"0 0\";\n overlay.style.transform = exportTransform;\n }\n\n stage.appendChild(flowClone);\n wrapper.appendChild(stage);\n document.body.appendChild(wrapper);\n\n return {\n stage,\n width,\n height,\n backgroundColor,\n destroy() {\n wrapper.remove();\n },\n };\n}\n\nfunction normalizeBounds(bounds: DiagramBounds): Required<DiagramBounds> | null {\n if (!Number.isFinite(bounds.x) || !Number.isFinite(bounds.y)) {\n return null;\n }\n\n if (!Number.isFinite(bounds.width) || !Number.isFinite(bounds.height)) {\n return null;\n }\n\n const width = Math.max(1, Math.floor(bounds.width));\n const height = Math.max(1, Math.floor(bounds.height));\n\n return {\n x: Math.floor(bounds.x),\n y: Math.floor(bounds.y),\n width,\n height,\n };\n}\n\nfunction resolveExportPixelRatio(width: number, height: number) {\n let ratio = Math.max(1, Math.min(2, window.devicePixelRatio || 1));\n\n if (width * ratio > MAX_EXPORT_SIDE_PX) {\n ratio = MAX_EXPORT_SIDE_PX / width;\n }\n\n if (height * ratio > MAX_EXPORT_SIDE_PX) {\n ratio = Math.min(ratio, MAX_EXPORT_SIDE_PX / height);\n }\n\n const areaAtRatio = width * height * ratio * ratio;\n if (areaAtRatio > MAX_EXPORT_AREA_PX) {\n ratio = Math.min(ratio, Math.sqrt(MAX_EXPORT_AREA_PX / (width * height)));\n }\n\n return Math.max(0.45, ratio);\n}\n\nfunction inlineSvgPresentationStyles(sourceRoot: HTMLElement, clonedRoot: HTMLElement) {\n copyComputedSvgStyles(sourceRoot, clonedRoot, \".vue-flow__edge-path\", [\n \"fill\",\n \"stroke\",\n \"stroke-width\",\n \"stroke-linecap\",\n \"stroke-linejoin\",\n \"vector-effect\",\n \"filter\",\n \"opacity\",\n ]);\n}\n\nfunction copyComputedSvgStyles(\n sourceRoot: HTMLElement,\n clonedRoot: HTMLElement,\n selector: string,\n properties: string[],\n) {\n const sourceElements = sourceRoot.querySelectorAll<SVGElement>(selector);\n const clonedElements = clonedRoot.querySelectorAll<SVGElement>(selector);\n const total = Math.min(sourceElements.length, clonedElements.length);\n\n for (let index = 0; index < total; index += 1) {\n const sourceElement = sourceElements[index];\n const clonedElement = clonedElements[index];\n if (!sourceElement || !clonedElement) continue;\n\n const computedStyle = getComputedStyle(sourceElement);\n\n for (const property of properties) {\n const value = computedStyle.getPropertyValue(property);\n if (!value) continue;\n clonedElement.style.setProperty(property, value);\n }\n }\n}\n\nasync function settleCaptureStage() {\n if (typeof document !== \"undefined\" && \"fonts\" in document) {\n try {\n await document.fonts.ready;\n } catch {\n // Ignore font readiness failures and continue with the best available render.\n }\n }\n\n await waitForAnimationFrame();\n await waitForAnimationFrame();\n}\n\nfunction waitForAnimationFrame() {\n return new Promise<void>((resolve) => {\n window.requestAnimationFrame(() => resolve());\n });\n}\n\nasync function renderPdfBlob(pngDataUrl: string, widthPx: number, heightPx: number) {\n const jspdfModule = await import(\"jspdf\");\n const jsPDF = (jspdfModule.jsPDF ??\n (typeof jspdfModule.default === \"function\" ? jspdfModule.default : null) ??\n (jspdfModule.default as { jsPDF?: unknown } | undefined)?.jsPDF ??\n null) as\n | (new (options: { unit: string; format: [number, number]; compress: boolean }) => {\n addImage: (...args: unknown[]) => void;\n output: (type: \"blob\") => Blob;\n })\n | null;\n\n if (!jsPDF) {\n throw new Error(\"Could not load PDF runtime. Please try PNG export.\");\n }\n\n const pointPerPixel = 72 / 96;\n const pageWidth = Math.max(72, Math.round(widthPx * pointPerPixel));\n const pageHeight = Math.max(72, Math.round(heightPx * pointPerPixel));\n\n const pdf = new jsPDF({\n unit: \"pt\",\n format: [pageWidth, pageHeight],\n compress: true,\n });\n\n pdf.addImage(pngDataUrl, \"PNG\", 0, 0, pageWidth, pageHeight, undefined, \"FAST\");\n return pdf.output(\"blob\");\n}\n\nfunction sanitizeFileName(value: string) {\n const cleaned = value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n return cleaned || \"flow-diagram\";\n}\n\nfunction downloadDataUrl(dataUrl: string, fileName: string) {\n triggerDownload(dataUrl, fileName);\n}\n\nfunction downloadBlob(blob: Blob, fileName: string) {\n const url = URL.createObjectURL(blob);\n\n try {\n triggerDownload(url, fileName);\n } finally {\n setTimeout(() => {\n URL.revokeObjectURL(url);\n }, 30_000);\n }\n}\n\nfunction triggerDownload(href: string, fileName: string) {\n const anchor = document.createElement(\"a\");\n anchor.href = href;\n anchor.download = fileName;\n anchor.rel = \"noopener\";\n anchor.style.display = \"none\";\n\n document.body.appendChild(anchor);\n\n try {\n anchor.click();\n } finally {\n anchor.remove();\n }\n}\n","import { inject } from \"vue\";\nimport { flaierRuntimeKey } from \"../context\";\n\nexport function useFlaierRuntime() {\n const context = inject(flaierRuntimeKey);\n\n if (!context) {\n throw new Error(\"[flaier] Runtime context not found. Wrap components with <Flaier>.\");\n }\n\n return context;\n}\n","export type SupportedTwoslashLanguage = \"ts\" | \"tsx\";\n\nexport interface TwoslashHtml {\n dark?: string;\n light?: string;\n}\n\nconst TWOSLASH_HINT_PATTERN = /(?:\\^\\?|\\^\\||@errors\\b|@log\\b|@warn\\b|@annotate\\b|@include\\b)/m;\nconst TWOSLASH_LANGUAGE_ALIASES: Record<string, SupportedTwoslashLanguage> = {\n ts: \"ts\",\n typescript: \"ts\",\n tsx: \"tsx\",\n};\n\nexport function hasTwoslashHints(code: string) {\n return TWOSLASH_HINT_PATTERN.test(code);\n}\n\nexport function normalizeTwoslashLanguage(language?: string): SupportedTwoslashLanguage | null {\n const normalized = (language ?? \"typescript\").trim().toLowerCase();\n return TWOSLASH_LANGUAGE_ALIASES[normalized] ?? null;\n}\n\nexport function normalizeTwoslashHtml(value: unknown): TwoslashHtml | undefined {\n if (!value || typeof value !== \"object\") {\n return undefined;\n }\n\n const record = value as Record<string, unknown>;\n const dark = typeof record.dark === \"string\" && record.dark.length > 0 ? record.dark : undefined;\n const light =\n typeof record.light === \"string\" && record.light.length > 0 ? record.light : undefined;\n\n if (!dark && !light) {\n return undefined;\n }\n\n return { dark, light };\n}\n\nexport function hasTwoslashHtml(value: TwoslashHtml | undefined) {\n return Boolean(value?.dark || value?.light);\n}\n\nexport function resolveTwoslashHtmlForTheme(\n value: TwoslashHtml | undefined,\n theme: \"dark\" | \"light\",\n) {\n if (!value) {\n return \"\";\n }\n\n return theme === \"light\" ? (value.light ?? value.dark ?? \"\") : (value.dark ?? value.light ?? \"\");\n}\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\n\ninterface ChoiceOption {\n id: string;\n label: string;\n description?: string;\n kind?: \"default\" | \"success\" | \"error\" | \"warning\" | \"retry\" | \"async\";\n}\n\nconst props = defineProps<{\n currentStep: number;\n totalSteps: number;\n playing: boolean;\n label?: string;\n description?: string;\n sourceAnchorLabel?: string;\n sourceAnchorHref?: string;\n choices?: ChoiceOption[];\n selectedChoiceId?: string;\n}>();\n\nconst emit = defineEmits<{\n next: [];\n prev: [];\n togglePlay: [];\n goTo: [step: number];\n chooseChoice: [choiceId: string];\n}>();\n\nconst MAX_VISIBLE_DOTS = 11;\n\nconst dotWindow = computed(() => {\n if (props.totalSteps <= MAX_VISIBLE_DOTS) {\n return { start: 0, end: Math.max(0, props.totalSteps - 1) };\n }\n\n const halfWindow = Math.floor(MAX_VISIBLE_DOTS / 2);\n let start = Math.max(0, props.currentStep - halfWindow);\n let end = Math.min(props.totalSteps - 1, start + MAX_VISIBLE_DOTS - 1);\n\n if (end - start + 1 < MAX_VISIBLE_DOTS) {\n start = Math.max(0, end - MAX_VISIBLE_DOTS + 1);\n }\n\n return { start, end };\n});\n\nconst visibleStepIndexes = computed(() => {\n const indexes: number[] = [];\n for (let i = dotWindow.value.start; i <= dotWindow.value.end; i += 1) {\n indexes.push(i);\n }\n return indexes;\n});\n\nconst hasLeadingSteps = computed(() => dotWindow.value.start > 0);\nconst hasTrailingSteps = computed(() => dotWindow.value.end < props.totalSteps - 1);\nconst hasChoices = computed(() => (props.choices?.length ?? 0) > 0);\n\nfunction choiceKindClass(kind?: ChoiceOption[\"kind\"]) {\n switch (kind) {\n case \"success\":\n return \"border-emerald-500/40 bg-emerald-500/10 text-emerald-500\";\n case \"error\":\n return \"border-red-500/45 bg-red-500/10 text-red-500\";\n case \"warning\":\n return \"border-amber-500/45 bg-amber-500/10 text-amber-500\";\n case \"retry\":\n return \"border-sky-500/45 bg-sky-500/10 text-sky-500\";\n case \"async\":\n return \"border-violet-500/45 bg-violet-500/10 text-violet-500\";\n default:\n return \"border-border/65 bg-background/70 text-muted-foreground\";\n }\n}\n</script>\n\n<template>\n <div\n class=\"w-full rounded-2xl bg-card/80 backdrop-blur-xl border border-border/60 shadow-2xl px-2.5 py-2\"\n >\n <div class=\"flex items-center gap-2\">\n <button\n class=\"w-8 h-8 rounded-xl flex items-center justify-center text-muted-foreground hover:text-foreground hover:bg-muted/60 disabled:opacity-20 disabled:pointer-events-none transition-colors\"\n :disabled=\"props.currentStep <= 0\"\n @click=\"emit('prev')\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n </button>\n\n <button\n class=\"w-8 h-8 rounded-xl flex items-center justify-center bg-foreground text-background hover:bg-foreground/85 transition-colors\"\n @click=\"emit('togglePlay')\"\n >\n <svg v-if=\"!props.playing\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <polygon points=\"6 3 20 12 6 21 6 3\" />\n </svg>\n <svg v-else width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <rect x=\"5\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\" />\n <rect x=\"15\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\" />\n </svg>\n </button>\n\n <button\n class=\"w-8 h-8 rounded-xl flex items-center justify-center text-muted-foreground hover:text-foreground hover:bg-muted/60 disabled:opacity-20 disabled:pointer-events-none transition-colors\"\n :disabled=\"props.currentStep >= props.totalSteps - 1\"\n @click=\"emit('next')\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n </button>\n\n <div class=\"w-px h-5 bg-border/60\" />\n\n <div class=\"flex min-w-0 flex-1 items-center gap-2.5 px-1.5\">\n <div class=\"h-1 flex-1 overflow-hidden rounded-full bg-muted/70\">\n <div\n class=\"h-full bg-foreground transition-[width] duration-500 ease-out\"\n :style=\"{\n width: `${props.totalSteps > 1 ? (props.currentStep / (props.totalSteps - 1)) * 100 : 100}%`,\n }\"\n />\n </div>\n\n <div class=\"flex items-center gap-1\">\n <span v-if=\"hasLeadingSteps\" class=\"text-[10px] text-muted-foreground/60\">...</span>\n\n <button\n v-for=\"step in visibleStepIndexes\"\n :key=\"step\"\n class=\"h-1.5 rounded-full transition-all duration-300\"\n :class=\"\n step === props.currentStep\n ? 'bg-foreground w-4'\n : step < props.currentStep\n ? 'bg-muted-foreground/50 w-1.5'\n : 'bg-muted-foreground/20 w-1.5'\n \"\n @click=\"emit('goTo', step)\"\n />\n\n <span v-if=\"hasTrailingSteps\" class=\"text-[10px] text-muted-foreground/60\">...</span>\n </div>\n\n <span class=\"shrink-0 text-[11px] text-muted-foreground font-mono tabular-nums\">\n {{ props.currentStep + 1 }}<span class=\"text-muted-foreground/40\">/</span\n >{{ props.totalSteps }}\n </span>\n </div>\n </div>\n\n <div\n v-if=\"props.label || props.description || props.sourceAnchorLabel\"\n class=\"mt-2 border-t border-border/60 pt-2 px-1.5\"\n >\n <p\n v-if=\"props.label\"\n class=\"text-[11px] font-medium text-foreground leading-snug break-words\"\n >\n {{ props.label }}\n </p>\n\n <a\n v-if=\"props.sourceAnchorLabel && props.sourceAnchorHref\"\n :href=\"props.sourceAnchorHref\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"mt-1 inline-flex max-w-full items-center gap-1 rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground transition-colors hover:border-primary/45 hover:text-foreground\"\n >\n <span class=\"truncate\">{{ props.sourceAnchorLabel }}</span>\n </a>\n\n <p\n v-else-if=\"props.sourceAnchorLabel\"\n class=\"mt-1 inline-flex max-w-full items-center rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground\"\n >\n <span class=\"truncate\">{{ props.sourceAnchorLabel }}</span>\n </p>\n\n <p\n v-if=\"props.description\"\n class=\"mt-1 max-h-[120px] overflow-auto pr-1 text-[11px] text-muted-foreground leading-relaxed whitespace-pre-wrap break-words\"\n >\n {{ props.description }}\n </p>\n </div>\n\n <div v-if=\"hasChoices\" class=\"mt-2 border-t border-border/60 pt-2 px-1.5\">\n <p class=\"text-[10px] uppercase tracking-wider text-muted-foreground\">\n Choose Next Path (1-9)\n </p>\n\n <div class=\"mt-1.5 flex flex-wrap gap-1.5\">\n <button\n v-for=\"(choice, index) in props.choices\"\n :key=\"choice.id\"\n class=\"rounded-lg border px-2 py-1 text-[11px] transition-colors text-left\"\n :class=\"\n choice.id === props.selectedChoiceId\n ? 'border-foreground/70 bg-foreground/10 text-foreground'\n : 'border-border/60 text-muted-foreground hover:text-foreground hover:bg-muted/60'\n \"\n @click=\"emit('chooseChoice', choice.id)\"\n >\n <span class=\"flex items-center gap-1.5\">\n <span\n v-if=\"index < 9\"\n class=\"inline-flex h-4 min-w-4 items-center justify-center rounded border border-border/70 bg-background/65 px-1 text-[10px] font-medium tabular-nums\"\n >\n {{ index + 1 }}\n </span>\n <span>{{ choice.label }}</span>\n <span\n v-if=\"choice.kind\"\n class=\"rounded border px-1 py-0.5 text-[9px] uppercase tracking-wider\"\n :class=\"choiceKindClass(choice.kind)\"\n >\n {{ choice.kind }}\n </span>\n </span>\n </button>\n </div>\n\n <p\n v-if=\"props.selectedChoiceId\"\n class=\"mt-1.5 text-[10px] text-muted-foreground leading-relaxed whitespace-pre-wrap break-words\"\n >\n {{ props.choices?.find((choice) => choice.id === props.selectedChoiceId)?.description }}\n </p>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\n\ninterface ChoiceOption {\n id: string;\n label: string;\n description?: string;\n kind?: \"default\" | \"success\" | \"error\" | \"warning\" | \"retry\" | \"async\";\n}\n\nconst props = defineProps<{\n currentStep: number;\n totalSteps: number;\n playing: boolean;\n label?: string;\n description?: string;\n sourceAnchorLabel?: string;\n sourceAnchorHref?: string;\n choices?: ChoiceOption[];\n selectedChoiceId?: string;\n}>();\n\nconst emit = defineEmits<{\n next: [];\n prev: [];\n togglePlay: [];\n goTo: [step: number];\n chooseChoice: [choiceId: string];\n}>();\n\nconst MAX_VISIBLE_DOTS = 11;\n\nconst dotWindow = computed(() => {\n if (props.totalSteps <= MAX_VISIBLE_DOTS) {\n return { start: 0, end: Math.max(0, props.totalSteps - 1) };\n }\n\n const halfWindow = Math.floor(MAX_VISIBLE_DOTS / 2);\n let start = Math.max(0, props.currentStep - halfWindow);\n let end = Math.min(props.totalSteps - 1, start + MAX_VISIBLE_DOTS - 1);\n\n if (end - start + 1 < MAX_VISIBLE_DOTS) {\n start = Math.max(0, end - MAX_VISIBLE_DOTS + 1);\n }\n\n return { start, end };\n});\n\nconst visibleStepIndexes = computed(() => {\n const indexes: number[] = [];\n for (let i = dotWindow.value.start; i <= dotWindow.value.end; i += 1) {\n indexes.push(i);\n }\n return indexes;\n});\n\nconst hasLeadingSteps = computed(() => dotWindow.value.start > 0);\nconst hasTrailingSteps = computed(() => dotWindow.value.end < props.totalSteps - 1);\nconst hasChoices = computed(() => (props.choices?.length ?? 0) > 0);\n\nfunction choiceKindClass(kind?: ChoiceOption[\"kind\"]) {\n switch (kind) {\n case \"success\":\n return \"border-emerald-500/40 bg-emerald-500/10 text-emerald-500\";\n case \"error\":\n return \"border-red-500/45 bg-red-500/10 text-red-500\";\n case \"warning\":\n return \"border-amber-500/45 bg-amber-500/10 text-amber-500\";\n case \"retry\":\n return \"border-sky-500/45 bg-sky-500/10 text-sky-500\";\n case \"async\":\n return \"border-violet-500/45 bg-violet-500/10 text-violet-500\";\n default:\n return \"border-border/65 bg-background/70 text-muted-foreground\";\n }\n}\n</script>\n\n<template>\n <div\n class=\"w-full rounded-2xl bg-card/80 backdrop-blur-xl border border-border/60 shadow-2xl px-2.5 py-2\"\n >\n <div class=\"flex items-center gap-2\">\n <button\n class=\"w-8 h-8 rounded-xl flex items-center justify-center text-muted-foreground hover:text-foreground hover:bg-muted/60 disabled:opacity-20 disabled:pointer-events-none transition-colors\"\n :disabled=\"props.currentStep <= 0\"\n @click=\"emit('prev')\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n </button>\n\n <button\n class=\"w-8 h-8 rounded-xl flex items-center justify-center bg-foreground text-background hover:bg-foreground/85 transition-colors\"\n @click=\"emit('togglePlay')\"\n >\n <svg v-if=\"!props.playing\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <polygon points=\"6 3 20 12 6 21 6 3\" />\n </svg>\n <svg v-else width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <rect x=\"5\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\" />\n <rect x=\"15\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\" />\n </svg>\n </button>\n\n <button\n class=\"w-8 h-8 rounded-xl flex items-center justify-center text-muted-foreground hover:text-foreground hover:bg-muted/60 disabled:opacity-20 disabled:pointer-events-none transition-colors\"\n :disabled=\"props.currentStep >= props.totalSteps - 1\"\n @click=\"emit('next')\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n </button>\n\n <div class=\"w-px h-5 bg-border/60\" />\n\n <div class=\"flex min-w-0 flex-1 items-center gap-2.5 px-1.5\">\n <div class=\"h-1 flex-1 overflow-hidden rounded-full bg-muted/70\">\n <div\n class=\"h-full bg-foreground transition-[width] duration-500 ease-out\"\n :style=\"{\n width: `${props.totalSteps > 1 ? (props.currentStep / (props.totalSteps - 1)) * 100 : 100}%`,\n }\"\n />\n </div>\n\n <div class=\"flex items-center gap-1\">\n <span v-if=\"hasLeadingSteps\" class=\"text-[10px] text-muted-foreground/60\">...</span>\n\n <button\n v-for=\"step in visibleStepIndexes\"\n :key=\"step\"\n class=\"h-1.5 rounded-full transition-all duration-300\"\n :class=\"\n step === props.currentStep\n ? 'bg-foreground w-4'\n : step < props.currentStep\n ? 'bg-muted-foreground/50 w-1.5'\n : 'bg-muted-foreground/20 w-1.5'\n \"\n @click=\"emit('goTo', step)\"\n />\n\n <span v-if=\"hasTrailingSteps\" class=\"text-[10px] text-muted-foreground/60\">...</span>\n </div>\n\n <span class=\"shrink-0 text-[11px] text-muted-foreground font-mono tabular-nums\">\n {{ props.currentStep + 1 }}<span class=\"text-muted-foreground/40\">/</span\n >{{ props.totalSteps }}\n </span>\n </div>\n </div>\n\n <div\n v-if=\"props.label || props.description || props.sourceAnchorLabel\"\n class=\"mt-2 border-t border-border/60 pt-2 px-1.5\"\n >\n <p\n v-if=\"props.label\"\n class=\"text-[11px] font-medium text-foreground leading-snug break-words\"\n >\n {{ props.label }}\n </p>\n\n <a\n v-if=\"props.sourceAnchorLabel && props.sourceAnchorHref\"\n :href=\"props.sourceAnchorHref\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"mt-1 inline-flex max-w-full items-center gap-1 rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground transition-colors hover:border-primary/45 hover:text-foreground\"\n >\n <span class=\"truncate\">{{ props.sourceAnchorLabel }}</span>\n </a>\n\n <p\n v-else-if=\"props.sourceAnchorLabel\"\n class=\"mt-1 inline-flex max-w-full items-center rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground\"\n >\n <span class=\"truncate\">{{ props.sourceAnchorLabel }}</span>\n </p>\n\n <p\n v-if=\"props.description\"\n class=\"mt-1 max-h-[120px] overflow-auto pr-1 text-[11px] text-muted-foreground leading-relaxed whitespace-pre-wrap break-words\"\n >\n {{ props.description }}\n </p>\n </div>\n\n <div v-if=\"hasChoices\" class=\"mt-2 border-t border-border/60 pt-2 px-1.5\">\n <p class=\"text-[10px] uppercase tracking-wider text-muted-foreground\">\n Choose Next Path (1-9)\n </p>\n\n <div class=\"mt-1.5 flex flex-wrap gap-1.5\">\n <button\n v-for=\"(choice, index) in props.choices\"\n :key=\"choice.id\"\n class=\"rounded-lg border px-2 py-1 text-[11px] transition-colors text-left\"\n :class=\"\n choice.id === props.selectedChoiceId\n ? 'border-foreground/70 bg-foreground/10 text-foreground'\n : 'border-border/60 text-muted-foreground hover:text-foreground hover:bg-muted/60'\n \"\n @click=\"emit('chooseChoice', choice.id)\"\n >\n <span class=\"flex items-center gap-1.5\">\n <span\n v-if=\"index < 9\"\n class=\"inline-flex h-4 min-w-4 items-center justify-center rounded border border-border/70 bg-background/65 px-1 text-[10px] font-medium tabular-nums\"\n >\n {{ index + 1 }}\n </span>\n <span>{{ choice.label }}</span>\n <span\n v-if=\"choice.kind\"\n class=\"rounded border px-1 py-0.5 text-[9px] uppercase tracking-wider\"\n :class=\"choiceKindClass(choice.kind)\"\n >\n {{ choice.kind }}\n </span>\n </span>\n </button>\n </div>\n\n <p\n v-if=\"props.selectedChoiceId\"\n class=\"mt-1.5 text-[10px] text-muted-foreground leading-relaxed whitespace-pre-wrap break-words\"\n >\n {{ props.choices?.find((choice) => choice.id === props.selectedChoiceId)?.description }}\n </p>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { BaseEdge, EdgeLabelRenderer, getSmoothStepPath, type EdgeProps } from \"@vue-flow/core\";\nimport { computed } from \"vue\";\n\nconst props = withDefaults(defineProps<EdgeProps>(), {\n interactionWidth: 28,\n});\n\nconst pathDefinition = computed(() => {\n return getSmoothStepPath({\n sourceX: props.sourceX,\n sourceY: props.sourceY,\n sourcePosition: props.sourcePosition,\n targetX: props.targetX,\n targetY: props.targetY,\n targetPosition: props.targetPosition,\n offset: 42,\n borderRadius: 14,\n });\n});\n\nconst edgePath = computed(() => pathDefinition.value[0]);\nconst labelX = computed(() => pathDefinition.value[1]);\nconst labelY = computed(() => pathDefinition.value[2]);\nconst labelText = computed(() => (typeof props.label === \"string\" ? props.label : \"\"));\nconst labelPositionStyle = computed(() => ({\n transform: `translate(-50%, -50%) translate(${labelX.value}px, ${labelY.value}px)`,\n}));\n</script>\n\n<template>\n <BaseEdge\n :id=\"id\"\n :path=\"edgePath\"\n :marker-start=\"markerStart\"\n :marker-end=\"markerEnd\"\n :interaction-width=\"interactionWidth\"\n />\n\n <EdgeLabelRenderer>\n <div v-if=\"labelText\" class=\"fn-edge-html-label nodrag nopan\" :style=\"labelPositionStyle\">\n {{ labelText }}\n </div>\n </EdgeLabelRenderer>\n</template>\n","<script setup lang=\"ts\">\nimport { BaseEdge, EdgeLabelRenderer, getSmoothStepPath, type EdgeProps } from \"@vue-flow/core\";\nimport { computed } from \"vue\";\n\nconst props = withDefaults(defineProps<EdgeProps>(), {\n interactionWidth: 28,\n});\n\nconst pathDefinition = computed(() => {\n return getSmoothStepPath({\n sourceX: props.sourceX,\n sourceY: props.sourceY,\n sourcePosition: props.sourcePosition,\n targetX: props.targetX,\n targetY: props.targetY,\n targetPosition: props.targetPosition,\n offset: 42,\n borderRadius: 14,\n });\n});\n\nconst edgePath = computed(() => pathDefinition.value[0]);\nconst labelX = computed(() => pathDefinition.value[1]);\nconst labelY = computed(() => pathDefinition.value[2]);\nconst labelText = computed(() => (typeof props.label === \"string\" ? props.label : \"\"));\nconst labelPositionStyle = computed(() => ({\n transform: `translate(-50%, -50%) translate(${labelX.value}px, ${labelY.value}px)`,\n}));\n</script>\n\n<template>\n <BaseEdge\n :id=\"id\"\n :path=\"edgePath\"\n :marker-start=\"markerStart\"\n :marker-end=\"markerEnd\"\n :interaction-width=\"interactionWidth\"\n />\n\n <EdgeLabelRenderer>\n <div v-if=\"labelText\" class=\"fn-edge-html-label nodrag nopan\" :style=\"labelPositionStyle\">\n {{ labelText }}\n </div>\n </EdgeLabelRenderer>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\n\nconst props = defineProps<{\n label: string;\n href?: string;\n}>();\n\nconst opensNewTab = computed(() => {\n return typeof props.href === \"string\" && /^https?:\\/\\//i.test(props.href);\n});\n</script>\n\n<template>\n <a\n v-if=\"href\"\n :href=\"href\"\n :target=\"opensNewTab ? '_blank' : undefined\"\n :rel=\"opensNewTab ? 'noopener noreferrer' : undefined\"\n class=\"nowheel nopan nodrag inline-flex min-w-0 max-w-full items-center gap-1 rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground transition-colors hover:border-primary/40 hover:text-foreground\"\n :draggable=\"false\"\n @click.stop\n @pointerdown.stop\n @mousedown.stop\n @touchstart.stop\n >\n <svg\n class=\"h-3 w-3 shrink-0\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M14 3h7v7\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M21 14v7h-7\" />\n <path d=\"M3 10v11h11\" />\n </svg>\n <span class=\"truncate\" :title=\"label\">{{ label }}</span>\n </a>\n\n <span\n v-else\n class=\"nowheel nopan nodrag inline-flex min-w-0 max-w-full items-center gap-1 rounded-md border border-border/65 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground\"\n :title=\"label\"\n @click.stop\n @pointerdown.stop\n @mousedown.stop\n @touchstart.stop\n >\n <svg\n class=\"h-3 w-3 shrink-0\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M3 10v11h11\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M14 3h7v7\" />\n </svg>\n <span class=\"truncate\">{{ label }}</span>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\n\nconst props = defineProps<{\n label: string;\n href?: string;\n}>();\n\nconst opensNewTab = computed(() => {\n return typeof props.href === \"string\" && /^https?:\\/\\//i.test(props.href);\n});\n</script>\n\n<template>\n <a\n v-if=\"href\"\n :href=\"href\"\n :target=\"opensNewTab ? '_blank' : undefined\"\n :rel=\"opensNewTab ? 'noopener noreferrer' : undefined\"\n class=\"nowheel nopan nodrag inline-flex min-w-0 max-w-full items-center gap-1 rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground transition-colors hover:border-primary/40 hover:text-foreground\"\n :draggable=\"false\"\n @click.stop\n @pointerdown.stop\n @mousedown.stop\n @touchstart.stop\n >\n <svg\n class=\"h-3 w-3 shrink-0\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M14 3h7v7\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M21 14v7h-7\" />\n <path d=\"M3 10v11h11\" />\n </svg>\n <span class=\"truncate\" :title=\"label\">{{ label }}</span>\n </a>\n\n <span\n v-else\n class=\"nowheel nopan nodrag inline-flex min-w-0 max-w-full items-center gap-1 rounded-md border border-border/65 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground\"\n :title=\"label\"\n @click.stop\n @pointerdown.stop\n @mousedown.stop\n @touchstart.stop\n >\n <svg\n class=\"h-3 w-3 shrink-0\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M3 10v11h11\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M14 3h7v7\" />\n </svg>\n <span class=\"truncate\">{{ label }}</span>\n </span>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ntype ArchitectureKind =\n | \"service\"\n | \"database\"\n | \"queue\"\n | \"cache\"\n | \"gateway\"\n | \"external\"\n | \"compute\";\ntype ArchitectureTier = \"edge\" | \"application\" | \"integration\" | \"data\" | \"platform\" | \"external\";\ntype ArchitectureStatus = \"planned\" | \"active\" | \"degraded\" | \"retired\";\n\nconst props = withDefaults(\n defineProps<{\n label: string;\n kind?: ArchitectureKind;\n technology?: string;\n runtime?: string;\n owner?: string;\n tier?: ArchitectureTier;\n status?: ArchitectureStatus;\n tags?: string[];\n capabilities?: string[];\n description?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n }>(),\n {\n kind: \"service\",\n },\n);\n\nconst kindMeta = computed(() => {\n switch (props.kind) {\n case \"database\":\n return {\n tag: \"Database\",\n short: \"DB\",\n cardClass: \"border-emerald-500/40\",\n iconClass: \"border-emerald-500/45 bg-emerald-500/12 text-emerald-500\",\n tagClass: \"border-emerald-500/35 bg-emerald-500/12 text-emerald-500\",\n };\n case \"queue\":\n return {\n tag: \"Queue\",\n short: \"Q\",\n cardClass: \"border-amber-500/45\",\n iconClass: \"border-amber-500/45 bg-amber-500/12 text-amber-500\",\n tagClass: \"border-amber-500/35 bg-amber-500/12 text-amber-500\",\n };\n case \"cache\":\n return {\n tag: \"Cache\",\n short: \"C\",\n cardClass: \"border-cyan-500/45\",\n iconClass: \"border-cyan-500/45 bg-cyan-500/12 text-cyan-500\",\n tagClass: \"border-cyan-500/35 bg-cyan-500/12 text-cyan-500\",\n };\n case \"gateway\":\n return {\n tag: \"Gateway\",\n short: \"GW\",\n cardClass: \"border-indigo-500/45\",\n iconClass: \"border-indigo-500/45 bg-indigo-500/12 text-indigo-400\",\n tagClass: \"border-indigo-500/35 bg-indigo-500/12 text-indigo-400\",\n };\n case \"external\":\n return {\n tag: \"External\",\n short: \"EXT\",\n cardClass: \"border-slate-500/45\",\n iconClass: \"border-slate-500/45 bg-slate-500/12 text-slate-300\",\n tagClass: \"border-slate-500/35 bg-slate-500/12 text-slate-300\",\n };\n case \"compute\":\n return {\n tag: \"Compute\",\n short: \"CPU\",\n cardClass: \"border-rose-500/45\",\n iconClass: \"border-rose-500/45 bg-rose-500/12 text-rose-400\",\n tagClass: \"border-rose-500/35 bg-rose-500/12 text-rose-400\",\n };\n case \"service\":\n default:\n return {\n tag: \"Service\",\n short: \"API\",\n cardClass: \"border-sky-500/45\",\n iconClass: \"border-sky-500/45 bg-sky-500/12 text-sky-400\",\n tagClass: \"border-sky-500/35 bg-sky-500/12 text-sky-400\",\n };\n }\n});\n\nconst statusMeta = computed(() => {\n switch (props.status) {\n case \"planned\":\n return {\n label: \"Planned\",\n className: \"border-blue-400/35 bg-blue-400/12 text-blue-200\",\n };\n case \"degraded\":\n return {\n label: \"Degraded\",\n className: \"border-amber-400/35 bg-amber-400/12 text-amber-200\",\n };\n case \"retired\":\n return {\n label: \"Retired\",\n className: \"border-slate-400/35 bg-slate-400/12 text-slate-300\",\n };\n case \"active\":\n default:\n return {\n label: \"Active\",\n className: \"border-emerald-400/35 bg-emerald-400/12 text-emerald-200\",\n };\n }\n});\n\nconst tierLabel = computed(() => {\n if (!props.tier) {\n return undefined;\n }\n\n return props.tier.charAt(0).toUpperCase() + props.tier.slice(1);\n});\n\nconst compactCapabilities = computed(() => (props.capabilities ?? []).slice(0, 2));\nconst compactTags = computed(() => (props.tags ?? []).slice(0, 3));\n</script>\n\n<template>\n <div\n class=\"fn-node w-[270px] rounded-xl border bg-card/95 px-4 py-3 shadow-sm\"\n :class=\"kindMeta.cardClass\"\n :data-active=\"active\"\n data-node-type=\"architecture\"\n :data-node-kind=\"kind\"\n :data-node-status=\"status\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n\n <div class=\"flex items-start gap-2.5\">\n <div\n class=\"inline-flex h-8 min-w-8 items-center justify-center rounded-md border px-1 text-[10px] font-semibold uppercase tracking-wide\"\n :class=\"kindMeta.iconClass\"\n >\n {{ kindMeta.short }}\n </div>\n\n <div class=\"min-w-0 flex-1\">\n <p\n class=\"inline-flex items-center rounded-full border px-1.5 py-0.5 text-[9px] font-medium uppercase tracking-wider\"\n :class=\"kindMeta.tagClass\"\n >\n {{ kindMeta.tag }}\n </p>\n\n <p class=\"mt-1 text-sm font-semibold text-foreground leading-snug break-words\">\n {{ label }}\n </p>\n\n <p v-if=\"technology\" class=\"mt-0.5 text-[11px] font-mono text-muted-foreground break-words\">\n {{ technology }}\n </p>\n\n <div class=\"mt-1 flex flex-wrap items-center gap-1\">\n <span\n class=\"inline-flex items-center rounded border px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wider\"\n :class=\"statusMeta.className\"\n >\n {{ statusMeta.label }}\n </span>\n\n <span\n v-if=\"tierLabel\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[9px] font-medium uppercase tracking-wider text-muted-foreground\"\n >\n {{ tierLabel }}\n </span>\n </div>\n\n <p v-if=\"owner\" class=\"mt-1 text-[10px] text-muted-foreground break-words\">\n Owner: {{ owner }}\n </p>\n\n <p v-if=\"runtime\" class=\"text-[10px] font-mono text-muted-foreground break-words\">\n Runtime: {{ runtime }}\n </p>\n </div>\n </div>\n\n <div v-if=\"compactCapabilities.length > 0\" class=\"mt-2 flex flex-wrap gap-1\">\n <span\n v-for=\"capability in compactCapabilities\"\n :key=\"capability\"\n class=\"inline-flex items-center rounded border border-primary/30 bg-primary/10 px-1.5 py-0.5 text-[9px] font-medium text-primary\"\n >\n {{ capability }}\n </span>\n </div>\n\n <div v-if=\"compactTags.length > 0\" class=\"mt-1 flex flex-wrap gap-1\">\n <span\n v-for=\"tag in compactTags\"\n :key=\"tag\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/20 px-1.5 py-0.5 text-[9px] font-medium text-muted-foreground\"\n >\n #{{ tag }}\n </span>\n </div>\n\n <p\n v-if=\"description\"\n class=\"mt-2 text-[11px] text-muted-foreground leading-relaxed break-words\"\n >\n {{ description }}\n </p>\n\n <div v-if=\"sourceAnchor?.label\" class=\"mt-2 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ntype ArchitectureKind =\n | \"service\"\n | \"database\"\n | \"queue\"\n | \"cache\"\n | \"gateway\"\n | \"external\"\n | \"compute\";\ntype ArchitectureTier = \"edge\" | \"application\" | \"integration\" | \"data\" | \"platform\" | \"external\";\ntype ArchitectureStatus = \"planned\" | \"active\" | \"degraded\" | \"retired\";\n\nconst props = withDefaults(\n defineProps<{\n label: string;\n kind?: ArchitectureKind;\n technology?: string;\n runtime?: string;\n owner?: string;\n tier?: ArchitectureTier;\n status?: ArchitectureStatus;\n tags?: string[];\n capabilities?: string[];\n description?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n }>(),\n {\n kind: \"service\",\n },\n);\n\nconst kindMeta = computed(() => {\n switch (props.kind) {\n case \"database\":\n return {\n tag: \"Database\",\n short: \"DB\",\n cardClass: \"border-emerald-500/40\",\n iconClass: \"border-emerald-500/45 bg-emerald-500/12 text-emerald-500\",\n tagClass: \"border-emerald-500/35 bg-emerald-500/12 text-emerald-500\",\n };\n case \"queue\":\n return {\n tag: \"Queue\",\n short: \"Q\",\n cardClass: \"border-amber-500/45\",\n iconClass: \"border-amber-500/45 bg-amber-500/12 text-amber-500\",\n tagClass: \"border-amber-500/35 bg-amber-500/12 text-amber-500\",\n };\n case \"cache\":\n return {\n tag: \"Cache\",\n short: \"C\",\n cardClass: \"border-cyan-500/45\",\n iconClass: \"border-cyan-500/45 bg-cyan-500/12 text-cyan-500\",\n tagClass: \"border-cyan-500/35 bg-cyan-500/12 text-cyan-500\",\n };\n case \"gateway\":\n return {\n tag: \"Gateway\",\n short: \"GW\",\n cardClass: \"border-indigo-500/45\",\n iconClass: \"border-indigo-500/45 bg-indigo-500/12 text-indigo-400\",\n tagClass: \"border-indigo-500/35 bg-indigo-500/12 text-indigo-400\",\n };\n case \"external\":\n return {\n tag: \"External\",\n short: \"EXT\",\n cardClass: \"border-slate-500/45\",\n iconClass: \"border-slate-500/45 bg-slate-500/12 text-slate-300\",\n tagClass: \"border-slate-500/35 bg-slate-500/12 text-slate-300\",\n };\n case \"compute\":\n return {\n tag: \"Compute\",\n short: \"CPU\",\n cardClass: \"border-rose-500/45\",\n iconClass: \"border-rose-500/45 bg-rose-500/12 text-rose-400\",\n tagClass: \"border-rose-500/35 bg-rose-500/12 text-rose-400\",\n };\n case \"service\":\n default:\n return {\n tag: \"Service\",\n short: \"API\",\n cardClass: \"border-sky-500/45\",\n iconClass: \"border-sky-500/45 bg-sky-500/12 text-sky-400\",\n tagClass: \"border-sky-500/35 bg-sky-500/12 text-sky-400\",\n };\n }\n});\n\nconst statusMeta = computed(() => {\n switch (props.status) {\n case \"planned\":\n return {\n label: \"Planned\",\n className: \"border-blue-400/35 bg-blue-400/12 text-blue-200\",\n };\n case \"degraded\":\n return {\n label: \"Degraded\",\n className: \"border-amber-400/35 bg-amber-400/12 text-amber-200\",\n };\n case \"retired\":\n return {\n label: \"Retired\",\n className: \"border-slate-400/35 bg-slate-400/12 text-slate-300\",\n };\n case \"active\":\n default:\n return {\n label: \"Active\",\n className: \"border-emerald-400/35 bg-emerald-400/12 text-emerald-200\",\n };\n }\n});\n\nconst tierLabel = computed(() => {\n if (!props.tier) {\n return undefined;\n }\n\n return props.tier.charAt(0).toUpperCase() + props.tier.slice(1);\n});\n\nconst compactCapabilities = computed(() => (props.capabilities ?? []).slice(0, 2));\nconst compactTags = computed(() => (props.tags ?? []).slice(0, 3));\n</script>\n\n<template>\n <div\n class=\"fn-node w-[270px] rounded-xl border bg-card/95 px-4 py-3 shadow-sm\"\n :class=\"kindMeta.cardClass\"\n :data-active=\"active\"\n data-node-type=\"architecture\"\n :data-node-kind=\"kind\"\n :data-node-status=\"status\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n\n <div class=\"flex items-start gap-2.5\">\n <div\n class=\"inline-flex h-8 min-w-8 items-center justify-center rounded-md border px-1 text-[10px] font-semibold uppercase tracking-wide\"\n :class=\"kindMeta.iconClass\"\n >\n {{ kindMeta.short }}\n </div>\n\n <div class=\"min-w-0 flex-1\">\n <p\n class=\"inline-flex items-center rounded-full border px-1.5 py-0.5 text-[9px] font-medium uppercase tracking-wider\"\n :class=\"kindMeta.tagClass\"\n >\n {{ kindMeta.tag }}\n </p>\n\n <p class=\"mt-1 text-sm font-semibold text-foreground leading-snug break-words\">\n {{ label }}\n </p>\n\n <p v-if=\"technology\" class=\"mt-0.5 text-[11px] font-mono text-muted-foreground break-words\">\n {{ technology }}\n </p>\n\n <div class=\"mt-1 flex flex-wrap items-center gap-1\">\n <span\n class=\"inline-flex items-center rounded border px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wider\"\n :class=\"statusMeta.className\"\n >\n {{ statusMeta.label }}\n </span>\n\n <span\n v-if=\"tierLabel\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[9px] font-medium uppercase tracking-wider text-muted-foreground\"\n >\n {{ tierLabel }}\n </span>\n </div>\n\n <p v-if=\"owner\" class=\"mt-1 text-[10px] text-muted-foreground break-words\">\n Owner: {{ owner }}\n </p>\n\n <p v-if=\"runtime\" class=\"text-[10px] font-mono text-muted-foreground break-words\">\n Runtime: {{ runtime }}\n </p>\n </div>\n </div>\n\n <div v-if=\"compactCapabilities.length > 0\" class=\"mt-2 flex flex-wrap gap-1\">\n <span\n v-for=\"capability in compactCapabilities\"\n :key=\"capability\"\n class=\"inline-flex items-center rounded border border-primary/30 bg-primary/10 px-1.5 py-0.5 text-[9px] font-medium text-primary\"\n >\n {{ capability }}\n </span>\n </div>\n\n <div v-if=\"compactTags.length > 0\" class=\"mt-1 flex flex-wrap gap-1\">\n <span\n v-for=\"tag in compactTags\"\n :key=\"tag\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/20 px-1.5 py-0.5 text-[9px] font-medium text-muted-foreground\"\n >\n #{{ tag }}\n </span>\n </div>\n\n <p\n v-if=\"description\"\n class=\"mt-2 text-[11px] text-muted-foreground leading-relaxed break-words\"\n >\n {{ description }}\n </p>\n\n <div v-if=\"sourceAnchor?.label\" class=\"mt-2 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","import { shallowRef, type ShallowRef } from \"vue\";\nimport type { HighlighterCore } from \"shiki\";\n\nlet highlighterPromise: Promise<HighlighterCore> | null = null;\nconst highlighterRef: ShallowRef<HighlighterCore | null> = shallowRef(null);\n\n/**\n * Shared singleton Shiki highlighter.\n * Lazily created on first call; the same instance is reused across all components.\n */\nexport function useShiki(\n langs: string[] = [\n \"typescript\",\n \"tsx\",\n \"javascript\",\n \"jsx\",\n \"python\",\n \"json\",\n \"bash\",\n \"yaml\",\n \"go\",\n \"rust\",\n ],\n theme = \"github-dark\",\n) {\n if (!highlighterPromise) {\n highlighterPromise = import(\"shiki\").then(async ({ createHighlighter }) => {\n const themes = Array.from(new Set([\"github-dark\", \"github-light\", theme]));\n const hl = await createHighlighter({ themes, langs });\n highlighterRef.value = hl;\n return hl;\n });\n }\n\n return {\n highlighter: highlighterRef,\n ready: highlighterPromise,\n };\n}\n","<script setup lang=\"ts\">\nimport { computed, onUnmounted, ref, watch } from \"vue\";\nimport { Handle, Position } from \"@vue-flow/core\";\nimport { ShikiMagicMove, ShikiMagicMovePrecompiled } from \"shiki-magic-move/vue\";\nimport { codeToKeyedTokens, type KeyedTokensInfo } from \"shiki-magic-move/core\";\nimport \"shiki-magic-move/dist/style.css\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\nimport {\n CODE_NODE_MAX_INLINE_CHARS,\n estimateCodeNodeCharsPerLine,\n estimateCodeNodeWidth,\n} from \"../../code-node-sizing\";\nimport { useShiki } from \"../../composables/useShiki\";\nimport {\n hasTwoslashHints,\n hasTwoslashHtml,\n normalizeTwoslashLanguage,\n resolveTwoslashHtmlForTheme,\n} from \"../../twoslash\";\nimport type { MagicMoveStep, TwoslashHtml } from \"../../types\";\n\nconst TWOSLASH_SWAP_DELAY_MS = 560;\nconst FALLBACK_SHIKI_LANGUAGE = \"text\";\n\nconst props = withDefaults(\n defineProps<{\n label: string;\n file?: string;\n language?: string;\n code: string;\n comment?: string;\n story?: string;\n wrapLongLines?: boolean;\n magicMoveSteps?: MagicMoveStep[];\n twoslash?: boolean;\n twoslashHtml?: TwoslashHtml;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n uiTheme?: \"dark\" | \"light\";\n active?: boolean;\n stepIndex?: number;\n }>(),\n {\n language: \"typescript\",\n wrapLongLines: false,\n uiTheme: \"dark\",\n stepIndex: 0,\n },\n);\n\nconst { highlighter } = useShiki();\nconst isClient = typeof window !== \"undefined\";\n\nconst activeStep = computed(() => {\n if (!props.magicMoveSteps?.length) return undefined;\n const idx = Math.min(props.stepIndex, props.magicMoveSteps.length - 1);\n return props.magicMoveSteps[idx];\n});\n\nconst displayCode = computed(() => {\n return activeStep.value?.code ?? props.code;\n});\n\nconst displayTitle = computed(() => activeStep.value?.title);\n\nconst displaySpeaker = computed(() => activeStep.value?.speaker);\n\nconst displayNarrative = computed(() => {\n return activeStep.value?.story ?? activeStep.value?.comment ?? props.story ?? props.comment;\n});\n\nconst codeSequence = computed(() => {\n if (props.magicMoveSteps?.length) {\n return props.magicMoveSteps.map((step) => step.code);\n }\n\n return [props.code];\n});\n\nconst requestedLanguage = computed(() => {\n return (props.language ?? \"typescript\").trim().toLowerCase();\n});\n\nconst renderLanguage = computed(() => {\n const language = requestedLanguage.value || \"typescript\";\n const hl = highlighter.value;\n\n if (!hl) {\n return language;\n }\n\n const loadedLanguages = hl.getLoadedLanguages();\n if (loadedLanguages.includes(language)) {\n return language;\n }\n\n try {\n const resolvedAlias = hl.resolveLangAlias(language);\n if (loadedLanguages.includes(resolvedAlias)) {\n return resolvedAlias;\n }\n } catch {}\n\n return FALLBACK_SHIKI_LANGUAGE;\n});\n\nconst codeVariants = computed(() => {\n const variants = [props.code, ...codeSequence.value];\n return variants.filter((value): value is string => typeof value === \"string\" && value.length > 0);\n});\n\nconst hasMagicMoveSteps = computed(() => {\n return (props.magicMoveSteps?.length ?? 0) > 0;\n});\n\nconst autoTwoslashEnabled = computed(() => {\n return codeVariants.value.some((code) => hasTwoslashHints(code));\n});\n\nconst twoslashRequested = computed(() => {\n return props.twoslash ?? autoTwoslashEnabled.value;\n});\n\nconst twoslashLanguage = computed(() => {\n return normalizeTwoslashLanguage(props.language);\n});\n\nconst resolvedTwoslashHtml = computed(() => {\n return resolveTwoslashHtmlForTheme(props.twoslashHtml, props.uiTheme);\n});\n\nconst displaySourceAnchor = computed(() => {\n if (props.sourceAnchor?.label) {\n return props.sourceAnchor;\n }\n\n if (props.file) {\n return { label: props.file };\n }\n\n return undefined;\n});\n\nconst canRenderTwoslash = computed(() => {\n return (\n twoslashRequested.value &&\n Boolean(twoslashLanguage.value) &&\n hasTwoslashHtml(props.twoslashHtml)\n );\n});\n\nfunction getMaxLineLength(code: string) {\n return code.split(\"\\n\").reduce((max, line) => Math.max(max, line.length), 0);\n}\n\nconst maxLineLength = computed(() => {\n return codeVariants.value.reduce((max, code) => {\n return Math.max(max, getMaxLineLength(code));\n }, 0);\n});\n\nconst nodeWidth = computed(() => {\n return estimateCodeNodeWidth(maxLineLength.value);\n});\n\nconst codeCharsPerLine = computed(() => {\n return estimateCodeNodeCharsPerLine(nodeWidth.value);\n});\n\nconst shouldWrapLongLines = computed(() => {\n return props.wrapLongLines || maxLineLength.value > CODE_NODE_MAX_INLINE_CHARS;\n});\n\nconst shikiTheme = computed(() => {\n return props.uiTheme === \"light\" ? \"github-light\" : \"github-dark\";\n});\n\nconst twoslashShown = ref(false);\n\nconst showTwoslashPane = computed(() => {\n return twoslashShown.value && resolvedTwoslashHtml.value.length > 0;\n});\n\nlet finalSwapTimer: ReturnType<typeof setTimeout> | null = null;\n\nfunction getLastMagicMoveStepIndex() {\n return Math.max(0, (props.magicMoveSteps?.length ?? 1) - 1);\n}\n\nfunction clearFinalSwapTimer() {\n if (!finalSwapTimer) return;\n clearTimeout(finalSwapTimer);\n finalSwapTimer = null;\n}\n\nfunction scheduleFinalSwap() {\n if (!isClient) return;\n\n clearFinalSwapTimer();\n finalSwapTimer = setTimeout(() => {\n if (!canRenderTwoslash.value || !hasMagicMoveSteps.value) return;\n if (props.stepIndex >= getLastMagicMoveStepIndex()) {\n twoslashShown.value = true;\n }\n }, TWOSLASH_SWAP_DELAY_MS);\n}\n\nfunction handleMagicMoveEnd() {\n if (!canRenderTwoslash.value || !hasMagicMoveSteps.value) return;\n if (props.stepIndex < getLastMagicMoveStepIndex()) return;\n\n clearFinalSwapTimer();\n twoslashShown.value = true;\n}\n\nwatch(\n [canRenderTwoslash, hasMagicMoveSteps],\n ([enabled, hasSteps]) => {\n if (!enabled) {\n clearFinalSwapTimer();\n twoslashShown.value = false;\n return;\n }\n\n if (!hasSteps) {\n twoslashShown.value = true;\n return;\n }\n\n if (props.stepIndex < getLastMagicMoveStepIndex()) {\n twoslashShown.value = false;\n }\n },\n { immediate: true },\n);\n\nwatch(\n () => props.stepIndex,\n (stepIndex, previousStepIndex) => {\n if (!canRenderTwoslash.value || !hasMagicMoveSteps.value) return;\n\n const lastStepIndex = getLastMagicMoveStepIndex();\n\n if (stepIndex < lastStepIndex) {\n clearFinalSwapTimer();\n twoslashShown.value = false;\n return;\n }\n\n if (previousStepIndex === undefined || previousStepIndex < lastStepIndex) {\n scheduleFinalSwap();\n }\n },\n { immediate: true },\n);\n\nonUnmounted(() => {\n clearFinalSwapTimer();\n});\n\nconst precompiledSteps = computed<KeyedTokensInfo[] | null>(() => {\n const hl = highlighter.value;\n if (!hl) return null;\n\n try {\n return codeSequence.value.map((code) =>\n codeToKeyedTokens(\n hl as never,\n code,\n {\n lang: renderLanguage.value,\n theme: shikiTheme.value,\n } as never,\n false,\n ),\n );\n } catch {\n return null;\n }\n});\n\nconst precompiledStepIndex = computed(() => {\n const steps = precompiledSteps.value;\n if (!steps?.length) return 0;\n return Math.max(0, Math.min(props.stepIndex, steps.length - 1));\n});\n\nfunction estimateWrappedLines(text: string, charsPerLine = 44) {\n return text\n .split(\"\\n\")\n .reduce((total, line) => total + Math.max(1, Math.ceil(line.length / charsPerLine)), 0);\n}\n\nconst codeViewportHeight = computed(() => {\n const maxLines = codeVariants.value.reduce((max, code) => {\n const lines = shouldWrapLongLines.value\n ? estimateWrappedLines(code, codeCharsPerLine.value)\n : code.split(\"\\n\").length;\n\n return Math.max(max, lines);\n }, 1);\n\n if (shouldWrapLongLines.value) {\n return Math.min(400, Math.max(190, 72 + maxLines * 16));\n }\n\n return Math.min(340, Math.max(160, 84 + maxLines * 17));\n});\n\nconst narrativeVariants = computed(() => {\n const variants = [\n props.story,\n props.comment,\n ...(props.magicMoveSteps?.flatMap((step) => [step.story, step.comment]) ?? []),\n ];\n\n return variants.filter((value): value is string => typeof value === \"string\" && value.length > 0);\n});\n\nconst hasNarrative = computed(() => narrativeVariants.value.length > 0);\n\nconst hasNarrativeMeta = computed(() => {\n return Boolean(\n props.magicMoveSteps?.some((step) => step.title || step.speaker) ||\n displayTitle.value ||\n displaySpeaker.value,\n );\n});\n\nconst narrativeViewportHeight = computed(() => {\n if (!hasNarrative.value) return 0;\n\n const maxLines = narrativeVariants.value.reduce((max, text) => {\n return Math.max(max, estimateWrappedLines(text));\n }, 1);\n\n const baseHeight = hasNarrativeMeta.value ? 56 : 34;\n\n return Math.min(220, Math.max(88, baseHeight + maxLines * 18));\n});\n\nconst magicMoveOptions = {\n duration: 480,\n easing: \"cubic-bezier(0.22, 1, 0.36, 1)\",\n stagger: 0,\n delayMove: 0.18,\n delayEnter: 0.42,\n delayLeave: 0.06,\n animateContainer: false,\n containerStyle: false,\n splitTokens: true,\n enhanceMatching: true,\n lineNumbers: false,\n} as const;\n</script>\n\n<template>\n <div\n class=\"fn-node rounded-lg border border-border bg-card overflow-hidden\"\n :style=\"{ width: `${nodeWidth}px` }\"\n :data-active=\"active\"\n data-node-type=\"code\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n\n <!-- Header -->\n <div class=\"flex items-center justify-between gap-2 px-3 py-2 border-b border-border/50\">\n <span class=\"min-w-0 flex-1 truncate text-sm font-medium text-foreground\">{{ label }}</span>\n <NodeSourceAnchor\n v-if=\"displaySourceAnchor\"\n :label=\"displaySourceAnchor.label\"\n :href=\"displaySourceAnchor.href\"\n />\n </div>\n\n <!-- Code -->\n <div\n class=\"fn-code-stage nowheel nopan px-3 py-2.5 overflow-y-auto transition-[height] duration-300 ease-out\"\n :class=\"shouldWrapLongLines ? 'overflow-x-hidden' : 'overflow-x-auto'\"\n :style=\"{ height: `${codeViewportHeight}px` }\"\n :data-wrap=\"shouldWrapLongLines\"\n >\n <div v-if=\"showTwoslashPane\" class=\"fn-twoslash\" v-html=\"resolvedTwoslashHtml\" />\n <ShikiMagicMovePrecompiled\n v-else-if=\"!shouldWrapLongLines && precompiledSteps && precompiledSteps.length > 0\"\n :steps=\"precompiledSteps\"\n :step=\"precompiledStepIndex\"\n :options=\"magicMoveOptions\"\n @end=\"handleMagicMoveEnd\"\n />\n <ShikiMagicMove\n v-else-if=\"highlighter\"\n :highlighter=\"highlighter\"\n :code=\"displayCode\"\n :lang=\"renderLanguage\"\n :theme=\"shikiTheme\"\n :options=\"magicMoveOptions\"\n class=\"!bg-transparent\"\n @end=\"handleMagicMoveEnd\"\n />\n <pre\n v-else\n class=\"fn-static-code text-xs text-muted-foreground font-mono\"\n :class=\"shouldWrapLongLines ? 'whitespace-pre-wrap break-words' : 'whitespace-pre'\"\n ><code>{{ displayCode }}</code></pre>\n </div>\n\n <!-- Story -->\n <div\n v-if=\"hasNarrative\"\n class=\"nowheel nopan px-3 py-2 border-t border-border/50 overflow-y-auto overflow-x-hidden transition-[height] duration-300 ease-out\"\n :style=\"{ height: `${narrativeViewportHeight}px` }\"\n >\n <div class=\"min-h-full\">\n <div class=\"mb-1 flex items-center justify-between gap-2\">\n <p v-if=\"displayTitle\" class=\"text-[11px] font-medium text-foreground leading-snug\">\n {{ displayTitle }}\n </p>\n <span\n v-if=\"displaySpeaker\"\n class=\"text-[10px] uppercase tracking-wider text-muted-foreground border border-border/60 rounded-full px-2 py-0.5\"\n >\n {{ displaySpeaker }}\n </span>\n </div>\n\n <p class=\"text-[11px] text-muted-foreground leading-relaxed\">{{ displayNarrative }}</p>\n </div>\n </div>\n\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n\n<style scoped>\n.fn-code-stage[data-wrap=\"false\"] :deep(.shiki-magic-move-container),\n.fn-code-stage[data-wrap=\"false\"] :deep(.fn-static-code),\n.fn-code-stage[data-wrap=\"false\"] :deep(.fn-twoslash),\n.fn-code-stage[data-wrap=\"false\"] :deep(.fn-twoslash .twoslash),\n.fn-code-stage[data-wrap=\"false\"] :deep(.fn-twoslash pre.shiki) {\n display: inline-block;\n width: max-content;\n min-width: max-content;\n}\n\n.fn-code-stage[data-wrap=\"true\"] :deep(.shiki-magic-move-container),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-static-code),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-static-code code),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-twoslash),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-twoslash .twoslash),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-twoslash pre.shiki),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-twoslash pre.shiki > code) {\n display: block;\n width: 100%;\n min-width: 0 !important;\n white-space: pre-wrap !important;\n overflow-wrap: anywhere;\n word-break: break-word;\n}\n\n.fn-twoslash :deep(pre.shiki) {\n margin: 0 !important;\n padding: 0 !important;\n background: transparent !important;\n}\n\n.fn-twoslash :deep(pre.shiki code) {\n font-size: 12px;\n line-height: 1.65;\n}\n\n.fn-twoslash :deep(.twoslash-popup-container) {\n max-width: min(520px, calc(100vw - 5rem));\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onUnmounted, ref, watch } from \"vue\";\nimport { Handle, Position } from \"@vue-flow/core\";\nimport { ShikiMagicMove, ShikiMagicMovePrecompiled } from \"shiki-magic-move/vue\";\nimport { codeToKeyedTokens, type KeyedTokensInfo } from \"shiki-magic-move/core\";\nimport \"shiki-magic-move/dist/style.css\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\nimport {\n CODE_NODE_MAX_INLINE_CHARS,\n estimateCodeNodeCharsPerLine,\n estimateCodeNodeWidth,\n} from \"../../code-node-sizing\";\nimport { useShiki } from \"../../composables/useShiki\";\nimport {\n hasTwoslashHints,\n hasTwoslashHtml,\n normalizeTwoslashLanguage,\n resolveTwoslashHtmlForTheme,\n} from \"../../twoslash\";\nimport type { MagicMoveStep, TwoslashHtml } from \"../../types\";\n\nconst TWOSLASH_SWAP_DELAY_MS = 560;\nconst FALLBACK_SHIKI_LANGUAGE = \"text\";\n\nconst props = withDefaults(\n defineProps<{\n label: string;\n file?: string;\n language?: string;\n code: string;\n comment?: string;\n story?: string;\n wrapLongLines?: boolean;\n magicMoveSteps?: MagicMoveStep[];\n twoslash?: boolean;\n twoslashHtml?: TwoslashHtml;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n uiTheme?: \"dark\" | \"light\";\n active?: boolean;\n stepIndex?: number;\n }>(),\n {\n language: \"typescript\",\n wrapLongLines: false,\n uiTheme: \"dark\",\n stepIndex: 0,\n },\n);\n\nconst { highlighter } = useShiki();\nconst isClient = typeof window !== \"undefined\";\n\nconst activeStep = computed(() => {\n if (!props.magicMoveSteps?.length) return undefined;\n const idx = Math.min(props.stepIndex, props.magicMoveSteps.length - 1);\n return props.magicMoveSteps[idx];\n});\n\nconst displayCode = computed(() => {\n return activeStep.value?.code ?? props.code;\n});\n\nconst displayTitle = computed(() => activeStep.value?.title);\n\nconst displaySpeaker = computed(() => activeStep.value?.speaker);\n\nconst displayNarrative = computed(() => {\n return activeStep.value?.story ?? activeStep.value?.comment ?? props.story ?? props.comment;\n});\n\nconst codeSequence = computed(() => {\n if (props.magicMoveSteps?.length) {\n return props.magicMoveSteps.map((step) => step.code);\n }\n\n return [props.code];\n});\n\nconst requestedLanguage = computed(() => {\n return (props.language ?? \"typescript\").trim().toLowerCase();\n});\n\nconst renderLanguage = computed(() => {\n const language = requestedLanguage.value || \"typescript\";\n const hl = highlighter.value;\n\n if (!hl) {\n return language;\n }\n\n const loadedLanguages = hl.getLoadedLanguages();\n if (loadedLanguages.includes(language)) {\n return language;\n }\n\n try {\n const resolvedAlias = hl.resolveLangAlias(language);\n if (loadedLanguages.includes(resolvedAlias)) {\n return resolvedAlias;\n }\n } catch {}\n\n return FALLBACK_SHIKI_LANGUAGE;\n});\n\nconst codeVariants = computed(() => {\n const variants = [props.code, ...codeSequence.value];\n return variants.filter((value): value is string => typeof value === \"string\" && value.length > 0);\n});\n\nconst hasMagicMoveSteps = computed(() => {\n return (props.magicMoveSteps?.length ?? 0) > 0;\n});\n\nconst autoTwoslashEnabled = computed(() => {\n return codeVariants.value.some((code) => hasTwoslashHints(code));\n});\n\nconst twoslashRequested = computed(() => {\n return props.twoslash ?? autoTwoslashEnabled.value;\n});\n\nconst twoslashLanguage = computed(() => {\n return normalizeTwoslashLanguage(props.language);\n});\n\nconst resolvedTwoslashHtml = computed(() => {\n return resolveTwoslashHtmlForTheme(props.twoslashHtml, props.uiTheme);\n});\n\nconst displaySourceAnchor = computed(() => {\n if (props.sourceAnchor?.label) {\n return props.sourceAnchor;\n }\n\n if (props.file) {\n return { label: props.file };\n }\n\n return undefined;\n});\n\nconst canRenderTwoslash = computed(() => {\n return (\n twoslashRequested.value &&\n Boolean(twoslashLanguage.value) &&\n hasTwoslashHtml(props.twoslashHtml)\n );\n});\n\nfunction getMaxLineLength(code: string) {\n return code.split(\"\\n\").reduce((max, line) => Math.max(max, line.length), 0);\n}\n\nconst maxLineLength = computed(() => {\n return codeVariants.value.reduce((max, code) => {\n return Math.max(max, getMaxLineLength(code));\n }, 0);\n});\n\nconst nodeWidth = computed(() => {\n return estimateCodeNodeWidth(maxLineLength.value);\n});\n\nconst codeCharsPerLine = computed(() => {\n return estimateCodeNodeCharsPerLine(nodeWidth.value);\n});\n\nconst shouldWrapLongLines = computed(() => {\n return props.wrapLongLines || maxLineLength.value > CODE_NODE_MAX_INLINE_CHARS;\n});\n\nconst shikiTheme = computed(() => {\n return props.uiTheme === \"light\" ? \"github-light\" : \"github-dark\";\n});\n\nconst twoslashShown = ref(false);\n\nconst showTwoslashPane = computed(() => {\n return twoslashShown.value && resolvedTwoslashHtml.value.length > 0;\n});\n\nlet finalSwapTimer: ReturnType<typeof setTimeout> | null = null;\n\nfunction getLastMagicMoveStepIndex() {\n return Math.max(0, (props.magicMoveSteps?.length ?? 1) - 1);\n}\n\nfunction clearFinalSwapTimer() {\n if (!finalSwapTimer) return;\n clearTimeout(finalSwapTimer);\n finalSwapTimer = null;\n}\n\nfunction scheduleFinalSwap() {\n if (!isClient) return;\n\n clearFinalSwapTimer();\n finalSwapTimer = setTimeout(() => {\n if (!canRenderTwoslash.value || !hasMagicMoveSteps.value) return;\n if (props.stepIndex >= getLastMagicMoveStepIndex()) {\n twoslashShown.value = true;\n }\n }, TWOSLASH_SWAP_DELAY_MS);\n}\n\nfunction handleMagicMoveEnd() {\n if (!canRenderTwoslash.value || !hasMagicMoveSteps.value) return;\n if (props.stepIndex < getLastMagicMoveStepIndex()) return;\n\n clearFinalSwapTimer();\n twoslashShown.value = true;\n}\n\nwatch(\n [canRenderTwoslash, hasMagicMoveSteps],\n ([enabled, hasSteps]) => {\n if (!enabled) {\n clearFinalSwapTimer();\n twoslashShown.value = false;\n return;\n }\n\n if (!hasSteps) {\n twoslashShown.value = true;\n return;\n }\n\n if (props.stepIndex < getLastMagicMoveStepIndex()) {\n twoslashShown.value = false;\n }\n },\n { immediate: true },\n);\n\nwatch(\n () => props.stepIndex,\n (stepIndex, previousStepIndex) => {\n if (!canRenderTwoslash.value || !hasMagicMoveSteps.value) return;\n\n const lastStepIndex = getLastMagicMoveStepIndex();\n\n if (stepIndex < lastStepIndex) {\n clearFinalSwapTimer();\n twoslashShown.value = false;\n return;\n }\n\n if (previousStepIndex === undefined || previousStepIndex < lastStepIndex) {\n scheduleFinalSwap();\n }\n },\n { immediate: true },\n);\n\nonUnmounted(() => {\n clearFinalSwapTimer();\n});\n\nconst precompiledSteps = computed<KeyedTokensInfo[] | null>(() => {\n const hl = highlighter.value;\n if (!hl) return null;\n\n try {\n return codeSequence.value.map((code) =>\n codeToKeyedTokens(\n hl as never,\n code,\n {\n lang: renderLanguage.value,\n theme: shikiTheme.value,\n } as never,\n false,\n ),\n );\n } catch {\n return null;\n }\n});\n\nconst precompiledStepIndex = computed(() => {\n const steps = precompiledSteps.value;\n if (!steps?.length) return 0;\n return Math.max(0, Math.min(props.stepIndex, steps.length - 1));\n});\n\nfunction estimateWrappedLines(text: string, charsPerLine = 44) {\n return text\n .split(\"\\n\")\n .reduce((total, line) => total + Math.max(1, Math.ceil(line.length / charsPerLine)), 0);\n}\n\nconst codeViewportHeight = computed(() => {\n const maxLines = codeVariants.value.reduce((max, code) => {\n const lines = shouldWrapLongLines.value\n ? estimateWrappedLines(code, codeCharsPerLine.value)\n : code.split(\"\\n\").length;\n\n return Math.max(max, lines);\n }, 1);\n\n if (shouldWrapLongLines.value) {\n return Math.min(400, Math.max(190, 72 + maxLines * 16));\n }\n\n return Math.min(340, Math.max(160, 84 + maxLines * 17));\n});\n\nconst narrativeVariants = computed(() => {\n const variants = [\n props.story,\n props.comment,\n ...(props.magicMoveSteps?.flatMap((step) => [step.story, step.comment]) ?? []),\n ];\n\n return variants.filter((value): value is string => typeof value === \"string\" && value.length > 0);\n});\n\nconst hasNarrative = computed(() => narrativeVariants.value.length > 0);\n\nconst hasNarrativeMeta = computed(() => {\n return Boolean(\n props.magicMoveSteps?.some((step) => step.title || step.speaker) ||\n displayTitle.value ||\n displaySpeaker.value,\n );\n});\n\nconst narrativeViewportHeight = computed(() => {\n if (!hasNarrative.value) return 0;\n\n const maxLines = narrativeVariants.value.reduce((max, text) => {\n return Math.max(max, estimateWrappedLines(text));\n }, 1);\n\n const baseHeight = hasNarrativeMeta.value ? 56 : 34;\n\n return Math.min(220, Math.max(88, baseHeight + maxLines * 18));\n});\n\nconst magicMoveOptions = {\n duration: 480,\n easing: \"cubic-bezier(0.22, 1, 0.36, 1)\",\n stagger: 0,\n delayMove: 0.18,\n delayEnter: 0.42,\n delayLeave: 0.06,\n animateContainer: false,\n containerStyle: false,\n splitTokens: true,\n enhanceMatching: true,\n lineNumbers: false,\n} as const;\n</script>\n\n<template>\n <div\n class=\"fn-node rounded-lg border border-border bg-card overflow-hidden\"\n :style=\"{ width: `${nodeWidth}px` }\"\n :data-active=\"active\"\n data-node-type=\"code\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n\n <!-- Header -->\n <div class=\"flex items-center justify-between gap-2 px-3 py-2 border-b border-border/50\">\n <span class=\"min-w-0 flex-1 truncate text-sm font-medium text-foreground\">{{ label }}</span>\n <NodeSourceAnchor\n v-if=\"displaySourceAnchor\"\n :label=\"displaySourceAnchor.label\"\n :href=\"displaySourceAnchor.href\"\n />\n </div>\n\n <!-- Code -->\n <div\n class=\"fn-code-stage nowheel nopan px-3 py-2.5 overflow-y-auto transition-[height] duration-300 ease-out\"\n :class=\"shouldWrapLongLines ? 'overflow-x-hidden' : 'overflow-x-auto'\"\n :style=\"{ height: `${codeViewportHeight}px` }\"\n :data-wrap=\"shouldWrapLongLines\"\n >\n <div v-if=\"showTwoslashPane\" class=\"fn-twoslash\" v-html=\"resolvedTwoslashHtml\" />\n <ShikiMagicMovePrecompiled\n v-else-if=\"!shouldWrapLongLines && precompiledSteps && precompiledSteps.length > 0\"\n :steps=\"precompiledSteps\"\n :step=\"precompiledStepIndex\"\n :options=\"magicMoveOptions\"\n @end=\"handleMagicMoveEnd\"\n />\n <ShikiMagicMove\n v-else-if=\"highlighter\"\n :highlighter=\"highlighter\"\n :code=\"displayCode\"\n :lang=\"renderLanguage\"\n :theme=\"shikiTheme\"\n :options=\"magicMoveOptions\"\n class=\"!bg-transparent\"\n @end=\"handleMagicMoveEnd\"\n />\n <pre\n v-else\n class=\"fn-static-code text-xs text-muted-foreground font-mono\"\n :class=\"shouldWrapLongLines ? 'whitespace-pre-wrap break-words' : 'whitespace-pre'\"\n ><code>{{ displayCode }}</code></pre>\n </div>\n\n <!-- Story -->\n <div\n v-if=\"hasNarrative\"\n class=\"nowheel nopan px-3 py-2 border-t border-border/50 overflow-y-auto overflow-x-hidden transition-[height] duration-300 ease-out\"\n :style=\"{ height: `${narrativeViewportHeight}px` }\"\n >\n <div class=\"min-h-full\">\n <div class=\"mb-1 flex items-center justify-between gap-2\">\n <p v-if=\"displayTitle\" class=\"text-[11px] font-medium text-foreground leading-snug\">\n {{ displayTitle }}\n </p>\n <span\n v-if=\"displaySpeaker\"\n class=\"text-[10px] uppercase tracking-wider text-muted-foreground border border-border/60 rounded-full px-2 py-0.5\"\n >\n {{ displaySpeaker }}\n </span>\n </div>\n\n <p class=\"text-[11px] text-muted-foreground leading-relaxed\">{{ displayNarrative }}</p>\n </div>\n </div>\n\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n\n<style scoped>\n.fn-code-stage[data-wrap=\"false\"] :deep(.shiki-magic-move-container),\n.fn-code-stage[data-wrap=\"false\"] :deep(.fn-static-code),\n.fn-code-stage[data-wrap=\"false\"] :deep(.fn-twoslash),\n.fn-code-stage[data-wrap=\"false\"] :deep(.fn-twoslash .twoslash),\n.fn-code-stage[data-wrap=\"false\"] :deep(.fn-twoslash pre.shiki) {\n display: inline-block;\n width: max-content;\n min-width: max-content;\n}\n\n.fn-code-stage[data-wrap=\"true\"] :deep(.shiki-magic-move-container),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-static-code),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-static-code code),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-twoslash),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-twoslash .twoslash),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-twoslash pre.shiki),\n.fn-code-stage[data-wrap=\"true\"] :deep(.fn-twoslash pre.shiki > code) {\n display: block;\n width: 100%;\n min-width: 0 !important;\n white-space: pre-wrap !important;\n overflow-wrap: anywhere;\n word-break: break-word;\n}\n\n.fn-twoslash :deep(pre.shiki) {\n margin: 0 !important;\n padding: 0 !important;\n background: transparent !important;\n}\n\n.fn-twoslash :deep(pre.shiki code) {\n font-size: 12px;\n line-height: 1.65;\n}\n\n.fn-twoslash :deep(.twoslash-popup-container) {\n max-width: min(520px, calc(100vw - 5rem));\n}\n</style>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ndefineProps<{\n label: string;\n condition?: string;\n description?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n}>();\n</script>\n\n<template>\n <div\n class=\"fn-node w-[250px] rounded-lg border border-primary/35 bg-card px-4 py-3\"\n :data-active=\"active\"\n data-node-type=\"decision\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n <div class=\"mb-1.5 flex items-center gap-2\">\n <span\n class=\"inline-flex h-5 items-center rounded-full border border-primary/35 bg-primary/10 px-2 text-[10px] font-medium uppercase tracking-wider text-primary\"\n >\n Decision\n </span>\n </div>\n <p class=\"text-sm font-medium text-foreground leading-snug\">{{ label }}</p>\n <p\n v-if=\"condition\"\n class=\"mt-1 text-[11px] text-foreground/85 font-mono leading-relaxed break-words\"\n >\n {{ condition }}\n </p>\n <p v-if=\"description\" class=\"mt-1.5 text-[11px] text-muted-foreground leading-relaxed\">\n {{ description }}\n </p>\n <div v-if=\"sourceAnchor?.label\" class=\"mt-1.5 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ndefineProps<{\n label: string;\n condition?: string;\n description?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n}>();\n</script>\n\n<template>\n <div\n class=\"fn-node w-[250px] rounded-lg border border-primary/35 bg-card px-4 py-3\"\n :data-active=\"active\"\n data-node-type=\"decision\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n <div class=\"mb-1.5 flex items-center gap-2\">\n <span\n class=\"inline-flex h-5 items-center rounded-full border border-primary/35 bg-primary/10 px-2 text-[10px] font-medium uppercase tracking-wider text-primary\"\n >\n Decision\n </span>\n </div>\n <p class=\"text-sm font-medium text-foreground leading-snug\">{{ label }}</p>\n <p\n v-if=\"condition\"\n class=\"mt-1 text-[11px] text-foreground/85 font-mono leading-relaxed break-words\"\n >\n {{ condition }}\n </p>\n <p v-if=\"description\" class=\"mt-1.5 text-[11px] text-muted-foreground leading-relaxed\">\n {{ description }}\n </p>\n <div v-if=\"sourceAnchor?.label\" class=\"mt-1.5 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ndefineProps<{\n label: string;\n body: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n}>();\n</script>\n\n<template>\n <div\n class=\"fn-node w-[240px] rounded-lg border border-border bg-card px-4 py-3\"\n :data-active=\"active\"\n data-node-type=\"description\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n <p class=\"text-sm font-medium text-foreground leading-snug mb-1\">{{ label }}</p>\n <div v-if=\"sourceAnchor?.label\" class=\"mb-1.5 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n <p class=\"text-[11px] text-muted-foreground leading-relaxed\">{{ body }}</p>\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ndefineProps<{\n label: string;\n body: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n}>();\n</script>\n\n<template>\n <div\n class=\"fn-node w-[240px] rounded-lg border border-border bg-card px-4 py-3\"\n :data-active=\"active\"\n data-node-type=\"description\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n <p class=\"text-sm font-medium text-foreground leading-snug mb-1\">{{ label }}</p>\n <div v-if=\"sourceAnchor?.label\" class=\"mb-1.5 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n <p class=\"text-[11px] text-muted-foreground leading-relaxed\">{{ body }}</p>\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ndefineProps<{\n label: string;\n message: string;\n code?: string;\n cause?: string;\n mitigation?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n}>();\n</script>\n\n<template>\n <div\n class=\"fn-node w-[280px] rounded-lg border border-red-400/45 bg-card overflow-hidden\"\n :data-active=\"active\"\n data-node-type=\"error\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n\n <div\n class=\"flex items-center justify-between gap-2 border-b border-red-400/35 bg-red-400/10 px-3 py-2\"\n >\n <span class=\"text-sm font-medium text-foreground\">{{ label }}</span>\n <span\n class=\"rounded-full border border-red-400/45 bg-red-400/18 px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-red-200\"\n >\n Error\n </span>\n </div>\n\n <div class=\"space-y-2 px-3 py-2.5\">\n <p class=\"text-[11px] leading-relaxed text-foreground\">{{ message }}</p>\n\n <div\n v-if=\"code\"\n class=\"inline-flex items-center rounded-md border border-red-400/35 bg-red-400/12 px-2 py-0.5 text-[10px] font-mono text-red-100\"\n >\n {{ code }}\n </div>\n\n <p v-if=\"cause\" class=\"text-[11px] leading-relaxed text-muted-foreground\">\n <span class=\"font-medium text-foreground/90\">Cause:</span> {{ cause }}\n </p>\n\n <p v-if=\"mitigation\" class=\"text-[11px] leading-relaxed text-muted-foreground\">\n <span class=\"font-medium text-foreground/90\">Mitigation:</span> {{ mitigation }}\n </p>\n\n <div v-if=\"sourceAnchor?.label\" class=\"max-w-full pt-1\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n </div>\n\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ndefineProps<{\n label: string;\n message: string;\n code?: string;\n cause?: string;\n mitigation?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n}>();\n</script>\n\n<template>\n <div\n class=\"fn-node w-[280px] rounded-lg border border-red-400/45 bg-card overflow-hidden\"\n :data-active=\"active\"\n data-node-type=\"error\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n\n <div\n class=\"flex items-center justify-between gap-2 border-b border-red-400/35 bg-red-400/10 px-3 py-2\"\n >\n <span class=\"text-sm font-medium text-foreground\">{{ label }}</span>\n <span\n class=\"rounded-full border border-red-400/45 bg-red-400/18 px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-red-200\"\n >\n Error\n </span>\n </div>\n\n <div class=\"space-y-2 px-3 py-2.5\">\n <p class=\"text-[11px] leading-relaxed text-foreground\">{{ message }}</p>\n\n <div\n v-if=\"code\"\n class=\"inline-flex items-center rounded-md border border-red-400/35 bg-red-400/12 px-2 py-0.5 text-[10px] font-mono text-red-100\"\n >\n {{ code }}\n </div>\n\n <p v-if=\"cause\" class=\"text-[11px] leading-relaxed text-muted-foreground\">\n <span class=\"font-medium text-foreground/90\">Cause:</span> {{ cause }}\n </p>\n\n <p v-if=\"mitigation\" class=\"text-[11px] leading-relaxed text-muted-foreground\">\n <span class=\"font-medium text-foreground/90\">Mitigation:</span> {{ mitigation }}\n </p>\n\n <div v-if=\"sourceAnchor?.label\" class=\"max-w-full pt-1\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n </div>\n\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ndefineProps<{\n label: string;\n href: string;\n description?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n}>();\n</script>\n\n<template>\n <div\n class=\"fn-node w-[220px] rounded-lg border border-border bg-card px-4 py-3\"\n :data-active=\"active\"\n data-node-type=\"link\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n <a :href=\"href\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"block group\">\n <p\n class=\"text-sm font-medium text-foreground group-hover:text-primary transition-colors leading-snug\"\n >\n {{ label }}\n </p>\n <p v-if=\"description\" class=\"text-[11px] text-muted-foreground mt-1 leading-relaxed\">\n {{ description }}\n </p>\n </a>\n <div v-if=\"sourceAnchor?.label\" class=\"mt-1.5 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\ndefineProps<{\n label: string;\n href: string;\n description?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n}>();\n</script>\n\n<template>\n <div\n class=\"fn-node w-[220px] rounded-lg border border-border bg-card px-4 py-3\"\n :data-active=\"active\"\n data-node-type=\"link\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n <a :href=\"href\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"block group\">\n <p\n class=\"text-sm font-medium text-foreground group-hover:text-primary transition-colors leading-snug\"\n >\n {{ label }}\n </p>\n <p v-if=\"description\" class=\"text-[11px] text-muted-foreground mt-1 leading-relaxed\">\n {{ description }}\n </p>\n </a>\n <div v-if=\"sourceAnchor?.label\" class=\"mt-1.5 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\nconst props = withDefaults(\n defineProps<{\n label: string;\n payload?: string;\n before?: string;\n after?: string;\n format?: \"json\" | \"yaml\" | \"text\";\n description?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n }>(),\n {\n format: \"json\",\n },\n);\n\nconst hasBefore = computed(() => Boolean(props.before));\nconst hasAfter = computed(() => Boolean(props.after));\nconst hasDiff = computed(() => hasBefore.value || hasAfter.value);\nconst singlePayload = computed(() => {\n if (hasDiff.value) return \"\";\n return props.payload ?? \"\";\n});\n</script>\n\n<template>\n <div\n class=\"fn-node w-[300px] rounded-lg border border-border bg-card overflow-hidden\"\n :data-active=\"active\"\n data-node-type=\"payload\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n\n <div class=\"flex items-center justify-between gap-2 border-b border-border/50 px-3 py-2\">\n <span class=\"text-sm font-medium text-foreground\">{{ label }}</span>\n <span\n class=\"rounded-full border border-border/60 bg-muted/45 px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-muted-foreground\"\n >\n {{ format }}\n </span>\n </div>\n\n <div class=\"px-3 py-2.5\">\n <div v-if=\"sourceAnchor?.label\" class=\"mb-2 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n\n <p v-if=\"description\" class=\"mb-2 text-[11px] text-muted-foreground leading-relaxed\">\n {{ description }}\n </p>\n\n <div v-if=\"hasDiff\" class=\"space-y-2\">\n <div v-if=\"hasBefore\" class=\"rounded-md border border-border/65 bg-muted/30 p-2\">\n <p class=\"mb-1 text-[10px] font-medium uppercase tracking-wider text-muted-foreground\">\n Before\n </p>\n <pre\n class=\"nowheel nopan max-h-[132px] overflow-auto text-[11px] leading-relaxed text-foreground whitespace-pre\"\n ><code>{{ before }}</code></pre>\n </div>\n\n <div v-if=\"hasAfter\" class=\"rounded-md border border-primary/30 bg-primary/8 p-2\">\n <p class=\"mb-1 text-[10px] font-medium uppercase tracking-wider text-primary\">After</p>\n <pre\n class=\"nowheel nopan max-h-[132px] overflow-auto text-[11px] leading-relaxed text-foreground whitespace-pre\"\n ><code>{{ after }}</code></pre>\n </div>\n </div>\n\n <div v-else class=\"rounded-md border border-border/65 bg-muted/25 p-2\">\n <pre\n class=\"nowheel nopan max-h-[220px] overflow-auto text-[11px] leading-relaxed text-foreground whitespace-pre\"\n ><code>{{ singlePayload }}</code></pre>\n </div>\n </div>\n\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\nconst props = withDefaults(\n defineProps<{\n label: string;\n payload?: string;\n before?: string;\n after?: string;\n format?: \"json\" | \"yaml\" | \"text\";\n description?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n }>(),\n {\n format: \"json\",\n },\n);\n\nconst hasBefore = computed(() => Boolean(props.before));\nconst hasAfter = computed(() => Boolean(props.after));\nconst hasDiff = computed(() => hasBefore.value || hasAfter.value);\nconst singlePayload = computed(() => {\n if (hasDiff.value) return \"\";\n return props.payload ?? \"\";\n});\n</script>\n\n<template>\n <div\n class=\"fn-node w-[300px] rounded-lg border border-border bg-card overflow-hidden\"\n :data-active=\"active\"\n data-node-type=\"payload\"\n >\n <Handle type=\"target\" :position=\"Position.Left\" />\n\n <div class=\"flex items-center justify-between gap-2 border-b border-border/50 px-3 py-2\">\n <span class=\"text-sm font-medium text-foreground\">{{ label }}</span>\n <span\n class=\"rounded-full border border-border/60 bg-muted/45 px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wider text-muted-foreground\"\n >\n {{ format }}\n </span>\n </div>\n\n <div class=\"px-3 py-2.5\">\n <div v-if=\"sourceAnchor?.label\" class=\"mb-2 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n\n <p v-if=\"description\" class=\"mb-2 text-[11px] text-muted-foreground leading-relaxed\">\n {{ description }}\n </p>\n\n <div v-if=\"hasDiff\" class=\"space-y-2\">\n <div v-if=\"hasBefore\" class=\"rounded-md border border-border/65 bg-muted/30 p-2\">\n <p class=\"mb-1 text-[10px] font-medium uppercase tracking-wider text-muted-foreground\">\n Before\n </p>\n <pre\n class=\"nowheel nopan max-h-[132px] overflow-auto text-[11px] leading-relaxed text-foreground whitespace-pre\"\n ><code>{{ before }}</code></pre>\n </div>\n\n <div v-if=\"hasAfter\" class=\"rounded-md border border-primary/30 bg-primary/8 p-2\">\n <p class=\"mb-1 text-[10px] font-medium uppercase tracking-wider text-primary\">After</p>\n <pre\n class=\"nowheel nopan max-h-[132px] overflow-auto text-[11px] leading-relaxed text-foreground whitespace-pre\"\n ><code>{{ after }}</code></pre>\n </div>\n </div>\n\n <div v-else class=\"rounded-md border border-border/65 bg-muted/25 p-2\">\n <pre\n class=\"nowheel nopan max-h-[220px] overflow-auto text-[11px] leading-relaxed text-foreground whitespace-pre\"\n ><code>{{ singlePayload }}</code></pre>\n </div>\n </div>\n\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\nconst props = withDefaults(\n defineProps<{\n label: string;\n description?: string;\n color?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n }>(),\n {\n color: \"#22c55e\",\n },\n);\n</script>\n\n<template>\n <div\n class=\"fn-node w-[220px] rounded-lg border border-border bg-card px-4 py-3\"\n :data-active=\"active\"\n data-node-type=\"trigger\"\n >\n <div class=\"flex items-center gap-2 mb-1.5\">\n <div class=\"w-2 h-2 rounded-full\" :style=\"{ backgroundColor: color }\" />\n <span class=\"text-[10px] font-medium uppercase tracking-wider text-muted-foreground\"\n >Trigger</span\n >\n </div>\n <p class=\"text-sm font-medium text-foreground leading-snug\">{{ label }}</p>\n <div v-if=\"sourceAnchor?.label\" class=\"mt-1.5 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n <p v-if=\"description\" class=\"text-[11px] text-muted-foreground mt-1 leading-relaxed\">\n {{ description }}\n </p>\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { Handle, Position } from \"@vue-flow/core\";\nimport NodeSourceAnchor from \"./NodeSourceAnchor.vue\";\n\nconst props = withDefaults(\n defineProps<{\n label: string;\n description?: string;\n color?: string;\n sourceAnchor?: {\n label: string;\n href?: string;\n };\n active?: boolean;\n }>(),\n {\n color: \"#22c55e\",\n },\n);\n</script>\n\n<template>\n <div\n class=\"fn-node w-[220px] rounded-lg border border-border bg-card px-4 py-3\"\n :data-active=\"active\"\n data-node-type=\"trigger\"\n >\n <div class=\"flex items-center gap-2 mb-1.5\">\n <div class=\"w-2 h-2 rounded-full\" :style=\"{ backgroundColor: color }\" />\n <span class=\"text-[10px] font-medium uppercase tracking-wider text-muted-foreground\"\n >Trigger</span\n >\n </div>\n <p class=\"text-sm font-medium text-foreground leading-snug\">{{ label }}</p>\n <div v-if=\"sourceAnchor?.label\" class=\"mt-1.5 max-w-full\">\n <NodeSourceAnchor :label=\"sourceAnchor.label\" :href=\"sourceAnchor.href\" />\n </div>\n <p v-if=\"description\" class=\"text-[11px] text-muted-foreground mt-1 leading-relaxed\">\n {{ description }}\n </p>\n <Handle type=\"source\" :position=\"Position.Right\" />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport dagre from \"@dagrejs/dagre\";\nimport { useStateStore, useStateValue } from \"@json-render/vue\";\nimport {\n Position,\n VueFlow,\n type NodeProps,\n type NodeTypesObject,\n useNodesInitialized,\n useVueFlow,\n} from \"@vue-flow/core\";\nimport {\n computed,\n defineComponent,\n getCurrentInstance,\n h,\n markRaw,\n nextTick,\n onMounted,\n onUnmounted,\n ref,\n watch,\n} from \"vue\";\n\nimport {\n CODE_NODE_MAX_INLINE_CHARS,\n estimateCodeNodeCharsPerLine,\n estimateCodeNodeWidth,\n} from \"../../code-node-sizing\";\nimport { exportFlowDiagram, type DiagramExportFormat } from \"../../composables/useDiagramExport\";\nimport { useFlaierRuntime } from \"../../composables/useFlaierRuntime\";\nimport {\n hasTwoslashHints,\n hasTwoslashHtml,\n normalizeTwoslashHtml,\n normalizeTwoslashLanguage,\n} from \"../../twoslash\";\nimport type {\n ArchitectureDataAsset,\n ArchitectureInterface,\n ArchitectureLink,\n ArchitectureNodeProps,\n FlaierCustomNodeContext,\n FlaierCustomNodeDefinition,\n FlaierCustomNodeSize,\n FlaierResolvedSourceAnchor,\n ArchitectureOperations,\n ArchitectureSecurity,\n ArchitectureZone,\n EdgeTransitionKind,\n FlowEdge,\n FlowNode,\n FlowNodeData,\n FlowNodeType,\n MagicMoveStep,\n SpecElement,\n TwoslashHtml,\n} from \"../../types\";\nimport TimelineControls from \"../controls/TimelineControls.vue\";\nimport ArchitectureSmoothEdge from \"../edges/ArchitectureSmoothEdge.vue\";\nimport ArchitectureNodeVue from \"../nodes/ArchitectureNode.vue\";\nimport CodeNodeVue from \"../nodes/CodeNode.vue\";\nimport DecisionNodeVue from \"../nodes/DecisionNode.vue\";\nimport DescriptionNodeVue from \"../nodes/DescriptionNode.vue\";\nimport ErrorNodeVue from \"../nodes/ErrorNode.vue\";\nimport LinkNodeVue from \"../nodes/LinkNode.vue\";\nimport PayloadNodeVue from \"../nodes/PayloadNode.vue\";\nimport TriggerNodeVue from \"../nodes/TriggerNode.vue\";\n\nconst props = withDefaults(\n defineProps<{\n title: string;\n description?: string;\n mode?: \"narrative\" | \"architecture\";\n zones?: ArchitectureZone[];\n direction?: \"horizontal\" | \"vertical\";\n minHeight?: number;\n layoutEngine?: \"dagre\" | \"manual\";\n layoutRankSep?: number;\n layoutNodeSep?: number;\n layoutEdgeSep?: number;\n themeMode?: \"local\" | \"document\";\n showHeaderOverlay?: boolean;\n showExportControls?: boolean;\n showThemeToggle?: boolean;\n showArchitectureInspector?: boolean;\n defaultArchitectureInspectorOpen?: boolean;\n showArchitectureInspectorToggleText?: boolean;\n }>(),\n {\n mode: \"narrative\",\n direction: \"horizontal\",\n layoutEngine: \"dagre\",\n themeMode: \"local\",\n showHeaderOverlay: true,\n showExportControls: true,\n showThemeToggle: true,\n showArchitectureInspector: true,\n defaultArchitectureInspectorOpen: true,\n showArchitectureInspectorToggleText: true,\n },\n);\n\nconst TYPE_MAP: Record<string, FlowNodeType> = {\n ArchitectureNode: \"architecture\",\n TriggerNode: \"trigger\",\n CodeNode: \"code\",\n DecisionNode: \"decision\",\n PayloadNode: \"payload\",\n ErrorNode: \"error\",\n DescriptionNode: \"description\",\n LinkNode: \"link\",\n};\n\nfunction toNodeType(elementType: string): FlowNodeType | undefined {\n if (TYPE_MAP[elementType]) {\n return TYPE_MAP[elementType];\n }\n\n return customNodes.value[elementType] ? elementType : undefined;\n}\n\nfunction getCustomNodeDefinition(elementType: string): FlaierCustomNodeDefinition | undefined {\n return customNodes.value[elementType];\n}\n\nconst DEFAULT_LAYOUT_ENGINE = \"dagre\";\nconst DEFAULT_FALLBACK_GAP = 420;\nconst DEFAULT_DAGRE_RANK_SEP_HORIZONTAL = 260;\nconst DEFAULT_DAGRE_NODE_SEP_HORIZONTAL = 120;\nconst DEFAULT_DAGRE_RANK_SEP_VERTICAL = 220;\nconst DEFAULT_DAGRE_NODE_SEP_VERTICAL = 120;\nconst DEFAULT_DAGRE_EDGE_SEP = 30;\nconst OVERVIEW_ENTER_ZOOM = 0.52;\nconst OVERVIEW_EXIT_ZOOM = 0.62;\nconst NARRATIVE_FOCUS_HORIZONTAL_CONTEXT = 420;\nconst NARRATIVE_FOCUS_VERTICAL_CONTEXT = 320;\nconst NARRATIVE_FOCUS_MIN_ZOOM = 0.58;\nconst NARRATIVE_FOCUS_MAX_ZOOM = 1.35;\nconst FLAIER_THEME_STORAGE_KEY = \"flaier-ui-theme\";\nconst ARCHITECTURE_ZONE_MIN_CONTENT_PADDING = 44;\nconst ARCHITECTURE_ZONE_MIN_BOTTOM_PADDING = 88;\nconst ARCHITECTURE_ZONE_LABEL_TOP = 12;\nconst ARCHITECTURE_ZONE_LABEL_HEIGHT = 22;\nconst ARCHITECTURE_ZONE_DESCRIPTION_HEIGHT = 16;\nconst ARCHITECTURE_ZONE_LABEL_TO_DESCRIPTION_GAP = 6;\nconst ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP = 12;\nconst ARCHITECTURE_ZONE_NESTED_LABEL_STEP = 18;\nconst ARCHITECTURE_ZONE_CONTAINED_ZONE_GAP = 46;\nconst EDGE_TRANSITION_KINDS: EdgeTransitionKind[] = [\n \"default\",\n \"success\",\n \"error\",\n \"warning\",\n \"retry\",\n \"async\",\n];\nconst EDGE_TRANSITION_KIND_SET = new Set(EDGE_TRANSITION_KINDS);\nconst EDGE_TRANSITION_TRANSPORT_SET = new Set([\"sync\", \"async\"]);\nconst EDGE_TRANSITION_CRITICALITY_SET = new Set([\"low\", \"medium\", \"high\"]);\nconst ARCHITECTURE_NODE_KINDS: Array<NonNullable<ArchitectureNodeProps[\"kind\"]>> = [\n \"service\",\n \"database\",\n \"queue\",\n \"cache\",\n \"gateway\",\n \"external\",\n \"compute\",\n];\nconst ARCHITECTURE_NODE_KIND_SET = new Set(ARCHITECTURE_NODE_KINDS);\nconst ARCHITECTURE_NODE_STATUS_VALUES: Array<NonNullable<ArchitectureNodeProps[\"status\"]>> = [\n \"planned\",\n \"active\",\n \"degraded\",\n \"retired\",\n];\nconst ARCHITECTURE_NODE_STATUS_SET = new Set(ARCHITECTURE_NODE_STATUS_VALUES);\nconst ARCHITECTURE_NODE_TIER_VALUES: Array<NonNullable<ArchitectureNodeProps[\"tier\"]>> = [\n \"edge\",\n \"application\",\n \"integration\",\n \"data\",\n \"platform\",\n \"external\",\n];\nconst ARCHITECTURE_NODE_TIER_SET = new Set(ARCHITECTURE_NODE_TIER_VALUES);\nconst ARCHITECTURE_INTERFACE_DIRECTION_VALUES: Array<\n NonNullable<ArchitectureInterface[\"direction\"]>\n> = [\"inbound\", \"outbound\", \"bidirectional\"];\nconst ARCHITECTURE_INTERFACE_DIRECTION_SET = new Set(ARCHITECTURE_INTERFACE_DIRECTION_VALUES);\nconst ARCHITECTURE_DATA_CLASSIFICATION_VALUES: Array<\n NonNullable<ArchitectureDataAsset[\"classification\"]>\n> = [\"public\", \"internal\", \"confidential\", \"restricted\"];\nconst ARCHITECTURE_DATA_CLASSIFICATION_SET = new Set(ARCHITECTURE_DATA_CLASSIFICATION_VALUES);\nconst ARCHITECTURE_ZONE_COLOR_PALETTE = [\n \"#38bdf8\",\n \"#22c55e\",\n \"#f59e0b\",\n \"#f97316\",\n \"#a78bfa\",\n \"#14b8a6\",\n \"#fb7185\",\n];\nconst SOURCE_ANCHOR_LINK_PATTERN = /^(https?:\\/\\/|vscode:\\/\\/|idea:\\/\\/)/i;\nconst SOURCE_ANCHOR_TRAILING_LOCATION_PATTERN = /^(.*?):(\\d+)(?::(\\d+))?$/;\n\ninterface NodeSize {\n width: number;\n height: number;\n}\n\ninterface OrderedNodeElement {\n key: string;\n index: number;\n nodeType: FlowNodeType;\n element: SpecElement;\n}\n\ninterface TimelineFrame {\n nodeIndex: number;\n nodeKey: string;\n localStep: number;\n totalLocalSteps: number;\n}\n\ninterface BranchChoice {\n id: string;\n label: string;\n description?: string;\n kind?: EdgeTransitionKind;\n}\n\ninterface ParsedTransition {\n to: string;\n label?: string;\n description?: string;\n kind?: EdgeTransitionKind;\n protocol?: string;\n transport?: \"sync\" | \"async\";\n auth?: string;\n contract?: string;\n criticality?: \"low\" | \"medium\" | \"high\";\n}\n\ninterface ParsedSourceAnchor {\n label: string;\n href?: string;\n}\n\ninterface ParsedAnchorLocation {\n path: string;\n line?: number;\n column?: number;\n}\n\ninterface ResolvedArchitectureZone extends ArchitectureZone {\n padding: number;\n}\n\ninterface ArchitectureZoneOverlay {\n id: string;\n label: string;\n description?: string;\n color: string;\n x: number;\n y: number;\n width: number;\n height: number;\n nodeCount: number;\n nestingDepth: number;\n labelLane: number;\n labelOffsetY: number;\n descriptionOffsetY: number;\n}\n\ninterface ArchitectureOutgoingEdge {\n target: string;\n label?: string;\n protocol?: string;\n transport?: \"sync\" | \"async\";\n auth?: string;\n criticality?: \"low\" | \"medium\" | \"high\";\n}\n\ninterface ArchitectureInspectorArchitectureView {\n type: \"ArchitectureNode\";\n label: string;\n sourceAnchor?: ParsedSourceAnchor;\n kind?: ArchitectureNodeProps[\"kind\"];\n status?: ArchitectureNodeProps[\"status\"];\n tier?: ArchitectureNodeProps[\"tier\"];\n technology?: string;\n runtime?: string;\n owner?: string;\n zoneLabel?: string;\n summary: string;\n tags: string[];\n responsibilities: string[];\n capabilities: string[];\n interfaces: ArchitectureInterface[];\n dataAssets: ArchitectureDataAsset[];\n security?: ArchitectureSecurity;\n operations?: ArchitectureOperations;\n links: ArchitectureLink[];\n outgoing: ArchitectureOutgoingEdge[];\n}\n\ninterface ArchitectureInspectorGenericView {\n type: \"Other\";\n label: string;\n sourceAnchor?: ParsedSourceAnchor;\n summary: string;\n elementType: string;\n}\n\ntype ArchitectureInspectorView =\n | ArchitectureInspectorArchitectureView\n | ArchitectureInspectorGenericView;\n\nconst EMPTY_ARCHITECTURE_INSPECTOR_NODE: ArchitectureInspectorArchitectureView = {\n type: \"ArchitectureNode\",\n label: \"\",\n summary: \"\",\n tags: [],\n responsibilities: [],\n capabilities: [],\n interfaces: [],\n dataAssets: [],\n links: [],\n outgoing: [],\n};\n\nconst runtime = useFlaierRuntime();\nconst spec = computed(() => runtime.spec.value);\nconst customNodes = computed(() => runtime.nodes.value);\nconst availableFlows = computed(() => runtime.flowOptions.value);\nconst activeFlowId = computed(() => runtime.activeFlowId.value);\nconst activeFlow = computed(() => {\n const activeId = activeFlowId.value;\n if (!activeId) return undefined;\n return availableFlows.value.find((flow) => flow.id === activeId);\n});\nconst showFlowSelector = computed(() => availableFlows.value.length > 1);\nconst showHeaderOverlay = computed(() => props.showHeaderOverlay !== false);\nconst overlayTitle = computed(() => activeFlow.value?.title ?? props.title);\nconst overlayDescription = computed(() => activeFlow.value?.description ?? props.description);\nconst headerModeLabel = computed(() => {\n if (showFlowSelector.value) {\n return \"Flow\";\n }\n\n return isArchitectureMode.value ? \"Diagram\" : \"Narrative\";\n});\nconst headerDropdownRef = ref<HTMLDivElement | null>(null);\nconst headerDropdownOpen = ref(false);\nconst exportMenuRef = ref<HTMLDivElement | null>(null);\nconst exportMenuOpen = ref(false);\nconst exportInFlight = ref<DiagramExportFormat | null>(null);\nconst exportError = ref<string | null>(null);\nconst containerRef = ref<HTMLDivElement | null>(null);\nconst sceneRef = ref<HTMLElement | null>(null);\nconst containerReady = ref(false);\nconst containerWidth = ref(0);\nconst containerHeight = ref(0);\nconst uiTheme = ref<\"dark\" | \"light\">(\"dark\");\nlet documentThemeObserver: MutationObserver | null = null;\nlet documentThemeMediaQuery: MediaQueryList | null = null;\nlet handleDocumentThemeMediaQueryChange: ((event: MediaQueryListEvent) => void) | null = null;\nconst isLightTheme = computed(() => uiTheme.value === \"light\");\nconst themeMode = computed(() => (props.themeMode === \"document\" ? \"document\" : \"local\"));\nconst isArchitectureMode = computed(() => props.mode === \"architecture\");\nconst showExportControls = computed(() => props.showExportControls !== false);\nconst showThemeToggle = computed(() => props.showThemeToggle !== false);\nconst showArchitectureInspectorPanel = computed(() => props.showArchitectureInspector !== false);\nconst defaultArchitectureInspectorOpen = computed(\n () => props.defaultArchitectureInspectorOpen !== false,\n);\nconst showArchitectureInspectorToggleText = computed(\n () => props.showArchitectureInspectorToggleText !== false,\n);\nconst showTopRightControls = computed(() => {\n return (\n showExportControls.value ||\n showThemeToggle.value ||\n (showExportControls.value && Boolean(exportError.value))\n );\n});\nconst architectureInspectorOpen = ref(props.defaultArchitectureInspectorOpen !== false);\nconst themeToggleLabel = computed(() => {\n return isLightTheme.value ? \"Switch to dark mode\" : \"Switch to light mode\";\n});\n\nconst architectureInspectorToggleLabel = computed(() => {\n return architectureInspectorOpen.value\n ? \"Hide architecture details sidebar\"\n : \"Show architecture details sidebar\";\n});\n\nconst exportButtonLabel = computed(() => {\n if (exportInFlight.value === \"png\") {\n return \"Exporting PNG...\";\n }\n\n if (exportInFlight.value === \"pdf\") {\n return \"Exporting PDF...\";\n }\n\n return \"Export full diagram\";\n});\n\nfunction toggleTheme() {\n if (themeMode.value === \"document\") {\n applyDocumentTheme(isLightTheme.value ? \"dark\" : \"light\");\n return;\n }\n\n uiTheme.value = isLightTheme.value ? \"dark\" : \"light\";\n}\n\nfunction toggleArchitectureInspector() {\n architectureInspectorOpen.value = !architectureInspectorOpen.value;\n}\n\nfunction normalizeTheme(value: unknown): \"dark\" | \"light\" | null {\n if (value === \"dark\" || value === \"light\") {\n return value;\n }\n\n return null;\n}\n\nfunction readStoredTheme() {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n try {\n return normalizeTheme(window.localStorage.getItem(FLAIER_THEME_STORAGE_KEY));\n } catch {\n return null;\n }\n}\n\nfunction getPreferredSystemTheme(): \"dark\" | \"light\" {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") {\n return \"dark\";\n }\n\n return window.matchMedia(\"(prefers-color-scheme: light)\").matches ? \"light\" : \"dark\";\n}\n\nfunction getDocumentTheme(): \"dark\" | \"light\" | null {\n if (typeof document === \"undefined\") {\n return null;\n }\n\n const root = document.documentElement;\n const dataTheme = root.getAttribute(\"data-theme\")?.trim().toLowerCase();\n\n if (dataTheme === \"dark\" || dataTheme === \"light\") {\n return dataTheme;\n }\n\n if (root.classList.contains(\"dark\")) {\n return \"dark\";\n }\n\n if (root.classList.contains(\"light\")) {\n return \"light\";\n }\n\n const colorScheme = root.style.colorScheme?.trim().toLowerCase();\n if (colorScheme === \"dark\" || colorScheme === \"light\") {\n return colorScheme;\n }\n\n return null;\n}\n\nfunction applyDocumentTheme(theme: \"dark\" | \"light\") {\n if (typeof document === \"undefined\") {\n return;\n }\n\n const root = document.documentElement;\n root.classList.toggle(\"dark\", theme === \"dark\");\n root.style.colorScheme = theme;\n}\n\nfunction persistTheme(theme: \"dark\" | \"light\") {\n if (typeof window === \"undefined\") {\n return;\n }\n\n try {\n window.localStorage.setItem(FLAIER_THEME_STORAGE_KEY, theme);\n } catch {\n // no-op when storage is unavailable\n }\n}\n\nfunction syncDocumentTheme() {\n uiTheme.value = getDocumentTheme() ?? getPreferredSystemTheme();\n}\n\nfunction startDocumentThemeSync() {\n if (typeof document !== \"undefined\" && typeof MutationObserver !== \"undefined\") {\n if (!documentThemeObserver) {\n documentThemeObserver = new MutationObserver(() => {\n syncDocumentTheme();\n });\n\n documentThemeObserver.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\", \"style\", \"data-theme\"],\n });\n }\n }\n\n if (typeof window !== \"undefined\" && typeof window.matchMedia === \"function\") {\n if (!documentThemeMediaQuery) {\n documentThemeMediaQuery = window.matchMedia(\"(prefers-color-scheme: light)\");\n }\n\n if (!handleDocumentThemeMediaQueryChange) {\n handleDocumentThemeMediaQueryChange = () => {\n syncDocumentTheme();\n };\n\n if (typeof documentThemeMediaQuery.addEventListener === \"function\") {\n documentThemeMediaQuery.addEventListener(\"change\", handleDocumentThemeMediaQueryChange);\n } else {\n documentThemeMediaQuery.addListener(handleDocumentThemeMediaQueryChange);\n }\n }\n }\n}\n\nfunction stopDocumentThemeSync() {\n if (documentThemeObserver) {\n documentThemeObserver.disconnect();\n documentThemeObserver = null;\n }\n\n if (documentThemeMediaQuery && handleDocumentThemeMediaQueryChange) {\n if (typeof documentThemeMediaQuery.removeEventListener === \"function\") {\n documentThemeMediaQuery.removeEventListener(\"change\", handleDocumentThemeMediaQueryChange);\n } else {\n documentThemeMediaQuery.removeListener(handleDocumentThemeMediaQueryChange);\n }\n }\n\n handleDocumentThemeMediaQueryChange = null;\n documentThemeMediaQuery = null;\n}\n\nfunction toggleHeaderDropdown() {\n if (!showFlowSelector.value) return;\n closeExportMenu();\n headerDropdownOpen.value = !headerDropdownOpen.value;\n}\n\nfunction closeHeaderDropdown() {\n headerDropdownOpen.value = false;\n}\n\nfunction toggleExportMenu() {\n if (exportInFlight.value) return;\n if (!canExportDiagram.value) return;\n\n closeHeaderDropdown();\n exportMenuOpen.value = !exportMenuOpen.value;\n}\n\nfunction closeExportMenu() {\n exportMenuOpen.value = false;\n}\n\nfunction handleFlowSelect(flowId: string) {\n if (!flowId) return;\n\n runtime.setActiveFlow(flowId);\n headerDropdownOpen.value = false;\n closeExportMenu();\n}\n\nwatch(showFlowSelector, (show) => {\n if (!show) {\n headerDropdownOpen.value = false;\n }\n});\n\nwatch(activeFlowId, () => {\n headerDropdownOpen.value = false;\n closeExportMenu();\n});\n\nwatch(uiTheme, (theme) => {\n if (themeMode.value === \"document\") {\n return;\n }\n\n persistTheme(theme);\n});\n\nwatch(\n themeMode,\n (mode) => {\n if (mode === \"document\") {\n startDocumentThemeSync();\n syncDocumentTheme();\n return;\n }\n\n stopDocumentThemeSync();\n uiTheme.value = readStoredTheme() ?? getPreferredSystemTheme();\n },\n { immediate: true },\n);\n\nconst rootElement = computed(() => {\n const activeSpec = spec.value;\n if (!activeSpec) return undefined;\n return activeSpec.elements[activeSpec.root];\n});\n\nconst orderedNodeElements = computed<OrderedNodeElement[]>(() => {\n const activeSpec = spec.value;\n const root = rootElement.value;\n\n if (!activeSpec || !root?.children?.length) return [];\n\n const result: OrderedNodeElement[] = [];\n const queue = [...root.children];\n const seen = new Set<string>();\n\n while (queue.length > 0) {\n const key = queue.shift();\n if (!key || seen.has(key)) continue;\n\n const element = activeSpec.elements[key];\n if (!element) continue;\n\n const nodeType = toNodeType(element.type);\n if (!nodeType) continue;\n\n seen.add(key);\n result.push({ key, index: result.length, nodeType, element });\n\n for (const childKey of element.children ?? []) {\n if (!seen.has(childKey)) {\n queue.push(childKey);\n }\n }\n }\n\n return result;\n});\n\nconst orderedNodeByKey = computed<Record<string, OrderedNodeElement>>(() => {\n const map: Record<string, OrderedNodeElement> = {};\n\n for (const node of orderedNodeElements.value) {\n map[node.key] = node;\n }\n\n return map;\n});\n\nconst rootLinearNextByKey = computed<Record<string, string>>(() => {\n const root = rootElement.value;\n if (!root?.children?.length) return {};\n const rootChildren = root.children;\n\n const map: Record<string, string> = {};\n\n rootChildren.forEach((key, index) => {\n const nextKey = rootChildren[index + 1];\n if (!nextKey) return;\n\n if (orderedNodeByKey.value[key] && orderedNodeByKey.value[nextKey]) {\n map[key] = nextKey;\n }\n });\n\n return map;\n});\n\nconst transitionMetaBySource = computed<Record<string, Record<string, ParsedTransition>>>(() => {\n const map: Record<string, Record<string, ParsedTransition>> = {};\n\n for (const node of orderedNodeElements.value) {\n const transitions = toTransitions(node.element.props.transitions).filter((transition) =>\n Boolean(orderedNodeByKey.value[transition.to]),\n );\n\n if (transitions.length === 0) continue;\n\n const byTarget: Record<string, ParsedTransition> = {};\n for (const transition of transitions) {\n if (byTarget[transition.to]) continue;\n byTarget[transition.to] = transition;\n }\n\n if (Object.keys(byTarget).length > 0) {\n map[node.key] = byTarget;\n }\n }\n\n return map;\n});\n\nconst outgoingNodeKeys = computed<Record<string, string[]>>(() => {\n const map: Record<string, string[]> = {};\n\n for (const node of orderedNodeElements.value) {\n const transitionTargets = toTransitions(node.element.props.transitions)\n .map((transition) => transition.to)\n .filter((key) => Boolean(orderedNodeByKey.value[key]));\n\n const explicit = (node.element.children ?? []).filter((key) =>\n Boolean(orderedNodeByKey.value[key]),\n );\n\n const combined = mergeOutgoingTargets(transitionTargets, explicit);\n\n if (combined.length > 0) {\n map[node.key] = combined;\n continue;\n }\n\n const fallback = rootLinearNextByKey.value[node.key];\n map[node.key] = fallback ? [fallback] : [];\n }\n\n return map;\n});\n\nconst incomingNodeKeys = computed<Record<string, string[]>>(() => {\n const map: Record<string, string[]> = {};\n\n for (const node of orderedNodeElements.value) {\n map[node.key] = [];\n }\n\n for (const [source, targets] of Object.entries(outgoingNodeKeys.value)) {\n for (const target of targets) {\n if (!map[target]) continue;\n map[target].push(source);\n }\n }\n\n return map;\n});\n\nconst startNodeKey = computed(() => {\n const root = rootElement.value;\n if (!root?.children?.length) return undefined;\n\n return root.children.find((key) => Boolean(orderedNodeByKey.value[key]));\n});\n\nfunction toOptionalString(value: unknown) {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction toStringArray(value: unknown) {\n if (!Array.isArray(value)) {\n return [];\n }\n\n return value\n .map((entry) => toTrimmedNonEmptyString(entry))\n .filter((entry): entry is string => Boolean(entry));\n}\n\nfunction toTrimmedNonEmptyString(value: unknown) {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction toRequiredString(value: unknown) {\n return toOptionalString(value) ?? \"\";\n}\n\nfunction toBoolean(value: unknown, fallback = false) {\n return typeof value === \"boolean\" ? value : fallback;\n}\n\nfunction toOptionalBoolean(value: unknown) {\n return typeof value === \"boolean\" ? value : undefined;\n}\n\nfunction toTwoslashHtml(value: unknown): TwoslashHtml | undefined {\n return normalizeTwoslashHtml(value);\n}\n\nfunction toPayloadFormat(value: unknown): \"json\" | \"yaml\" | \"text\" | undefined {\n if (value === \"json\" || value === \"yaml\" || value === \"text\") {\n return value;\n }\n\n return undefined;\n}\n\nfunction toArchitectureKind(value: unknown): ArchitectureNodeProps[\"kind\"] | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n if (ARCHITECTURE_NODE_KIND_SET.has(value as NonNullable<ArchitectureNodeProps[\"kind\"]>)) {\n return value as ArchitectureNodeProps[\"kind\"];\n }\n\n return undefined;\n}\n\nfunction toArchitectureZoneId(value: unknown) {\n return toTrimmedNonEmptyString(value);\n}\n\nfunction toArchitectureStatus(value: unknown): ArchitectureNodeProps[\"status\"] | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n if (ARCHITECTURE_NODE_STATUS_SET.has(value as NonNullable<ArchitectureNodeProps[\"status\"]>)) {\n return value as ArchitectureNodeProps[\"status\"];\n }\n\n return undefined;\n}\n\nfunction toArchitectureTier(value: unknown): ArchitectureNodeProps[\"tier\"] | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n if (ARCHITECTURE_NODE_TIER_SET.has(value as NonNullable<ArchitectureNodeProps[\"tier\"]>)) {\n return value as ArchitectureNodeProps[\"tier\"];\n }\n\n return undefined;\n}\n\nfunction toArchitectureInterfaces(value: unknown): ArchitectureInterface[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n const result: ArchitectureInterface[] = [];\n\n for (const rawEntry of value) {\n if (!rawEntry || typeof rawEntry !== \"object\") {\n continue;\n }\n\n const entry = rawEntry as Record<string, unknown>;\n const name = toTrimmedNonEmptyString(entry.name);\n if (!name) {\n continue;\n }\n\n const directionRaw = toTrimmedNonEmptyString(entry.direction);\n const direction =\n directionRaw &&\n ARCHITECTURE_INTERFACE_DIRECTION_SET.has(\n directionRaw as NonNullable<ArchitectureInterface[\"direction\"]>,\n )\n ? (directionRaw as ArchitectureInterface[\"direction\"])\n : undefined;\n\n result.push({\n name,\n protocol: toTrimmedNonEmptyString(entry.protocol),\n direction,\n contract: toTrimmedNonEmptyString(entry.contract),\n auth: toTrimmedNonEmptyString(entry.auth),\n notes: toTrimmedNonEmptyString(entry.notes),\n });\n }\n\n return result;\n}\n\nfunction toArchitectureDataAssets(value: unknown): ArchitectureDataAsset[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n const result: ArchitectureDataAsset[] = [];\n\n for (const rawEntry of value) {\n if (!rawEntry || typeof rawEntry !== \"object\") {\n continue;\n }\n\n const entry = rawEntry as Record<string, unknown>;\n const name = toTrimmedNonEmptyString(entry.name);\n if (!name) {\n continue;\n }\n\n const classificationRaw = toTrimmedNonEmptyString(entry.classification);\n const classification =\n classificationRaw &&\n ARCHITECTURE_DATA_CLASSIFICATION_SET.has(\n classificationRaw as NonNullable<ArchitectureDataAsset[\"classification\"]>,\n )\n ? (classificationRaw as ArchitectureDataAsset[\"classification\"])\n : undefined;\n\n result.push({\n name,\n kind: toTrimmedNonEmptyString(entry.kind),\n classification,\n retention: toTrimmedNonEmptyString(entry.retention),\n notes: toTrimmedNonEmptyString(entry.notes),\n });\n }\n\n return result;\n}\n\nfunction toArchitectureSecurity(value: unknown): ArchitectureSecurity | undefined {\n if (!value || typeof value !== \"object\") {\n return undefined;\n }\n\n const record = value as Record<string, unknown>;\n const security = {\n auth: toTrimmedNonEmptyString(record.auth),\n encryption: toTrimmedNonEmptyString(record.encryption),\n pii: toOptionalBoolean(record.pii),\n threatModel: toTrimmedNonEmptyString(record.threatModel),\n } satisfies ArchitectureSecurity;\n\n if (\n !security.auth &&\n !security.encryption &&\n security.pii === undefined &&\n !security.threatModel\n ) {\n return undefined;\n }\n\n return security;\n}\n\nfunction toArchitectureOperations(value: unknown): ArchitectureOperations | undefined {\n if (!value || typeof value !== \"object\") {\n return undefined;\n }\n\n const record = value as Record<string, unknown>;\n const operations = {\n owner: toTrimmedNonEmptyString(record.owner),\n slo: toTrimmedNonEmptyString(record.slo),\n alert: toTrimmedNonEmptyString(record.alert),\n runbook: toTrimmedNonEmptyString(record.runbook),\n } satisfies ArchitectureOperations;\n\n if (!operations.owner && !operations.slo && !operations.alert && !operations.runbook) {\n return undefined;\n }\n\n return operations;\n}\n\nfunction toArchitectureLinks(value: unknown): ArchitectureLink[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n const result: ArchitectureLink[] = [];\n\n for (const rawEntry of value) {\n if (!rawEntry || typeof rawEntry !== \"object\") {\n continue;\n }\n\n const entry = rawEntry as Record<string, unknown>;\n const label = toTrimmedNonEmptyString(entry.label);\n const href = toTrimmedNonEmptyString(entry.href);\n if (!label || !href) {\n continue;\n }\n\n result.push({\n label,\n href,\n });\n }\n\n return result;\n}\n\nfunction toArchitectureZones(value: unknown): ResolvedArchitectureZone[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n const seen = new Set<string>();\n const result: ResolvedArchitectureZone[] = [];\n\n for (const rawEntry of value) {\n if (!rawEntry || typeof rawEntry !== \"object\") {\n continue;\n }\n\n const entry = rawEntry as Record<string, unknown>;\n const id = toTrimmedNonEmptyString(entry.id);\n const label = toTrimmedNonEmptyString(entry.label);\n if (!id || !label || seen.has(id)) {\n continue;\n }\n\n seen.add(id);\n\n const paddingRaw = entry.padding;\n const padding =\n typeof paddingRaw === \"number\" && Number.isFinite(paddingRaw)\n ? Math.max(28, Math.min(180, Math.round(paddingRaw)))\n : 62;\n\n result.push({\n id,\n label,\n description: toTrimmedNonEmptyString(entry.description),\n color: toTrimmedNonEmptyString(entry.color),\n padding,\n });\n }\n\n return result;\n}\n\nfunction humanizeZoneId(value: string) {\n return value\n .replace(/[-_]+/g, \" \")\n .replace(/\\s+/g, \" \")\n .trim()\n .replace(/(^|\\s)\\w/g, (char) => char.toUpperCase());\n}\n\nfunction resolveZoneColor(index: number, explicitColor?: string) {\n return (\n explicitColor ||\n ARCHITECTURE_ZONE_COLOR_PALETTE[index % ARCHITECTURE_ZONE_COLOR_PALETTE.length] ||\n \"#38bdf8\"\n );\n}\n\nfunction toHexChannel(value: string) {\n return Number.parseInt(value, 16);\n}\n\nfunction hexToRgb(value: string) {\n const hex = value.trim().replace(/^#/, \"\");\n if (hex.length === 3) {\n const r = toHexChannel(`${hex[0]}${hex[0]}`);\n const g = toHexChannel(`${hex[1]}${hex[1]}`);\n const b = toHexChannel(`${hex[2]}${hex[2]}`);\n if ([r, g, b].every((channel) => Number.isFinite(channel))) {\n return { r, g, b };\n }\n\n return undefined;\n }\n\n if (hex.length === 6) {\n const r = toHexChannel(hex.slice(0, 2));\n const g = toHexChannel(hex.slice(2, 4));\n const b = toHexChannel(hex.slice(4, 6));\n if ([r, g, b].every((channel) => Number.isFinite(channel))) {\n return { r, g, b };\n }\n }\n\n return undefined;\n}\n\nfunction withAlpha(color: string, alpha: number) {\n const rgb = hexToRgb(color);\n if (!rgb) {\n return color;\n }\n\n return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`;\n}\n\nfunction toPositiveInteger(value: unknown) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n return undefined;\n }\n\n const asInteger = Math.floor(value);\n return asInteger > 0 ? asInteger : undefined;\n}\n\nfunction parseInlineSourceAnchorLocation(value: string): ParsedAnchorLocation | undefined {\n const trimmed = value.trim();\n if (!trimmed) return undefined;\n\n const matched = SOURCE_ANCHOR_TRAILING_LOCATION_PATTERN.exec(trimmed);\n if (!matched) {\n return {\n path: trimmed,\n };\n }\n\n const rawPath = matched[1]?.trim();\n const rawLine = matched[2];\n const rawColumn = matched[3];\n\n if (!rawPath || !rawLine) {\n return {\n path: trimmed,\n };\n }\n\n const line = Number(rawLine);\n const column = rawColumn ? Number(rawColumn) : undefined;\n\n return {\n path: rawPath,\n line: Number.isFinite(line) && line > 0 ? Math.floor(line) : undefined,\n column: Number.isFinite(column) && (column ?? 0) > 0 ? Math.floor(column as number) : undefined,\n };\n}\n\nfunction toVsCodeFileHref(path: string, line?: number, column?: number) {\n const normalizedPath = path.trim().replace(/\\\\/g, \"/\");\n if (!normalizedPath) return undefined;\n\n const encodedPath = encodeURI(normalizedPath);\n const linePart = line ? `:${line}` : \"\";\n const columnPart = line && column ? `:${column}` : \"\";\n\n return `vscode://file/${encodedPath}${linePart}${columnPart}`;\n}\n\nfunction resolveSourceAnchorHref(\n path: string,\n line?: number,\n column?: number,\n explicitHref?: string,\n) {\n if (explicitHref) {\n return explicitHref;\n }\n\n if (SOURCE_ANCHOR_LINK_PATTERN.test(path)) {\n return path;\n }\n\n return toVsCodeFileHref(path, line, column);\n}\n\nfunction toSourceAnchor(value: unknown): ParsedSourceAnchor | undefined {\n const inlineAnchor = toTrimmedNonEmptyString(value);\n if (inlineAnchor) {\n const parsed = parseInlineSourceAnchorLocation(inlineAnchor);\n\n return {\n label: inlineAnchor,\n href: parsed ? resolveSourceAnchorHref(parsed.path, parsed.line, parsed.column) : undefined,\n };\n }\n\n if (!value || typeof value !== \"object\") {\n return undefined;\n }\n\n const record = value as Record<string, unknown>;\n const path = toTrimmedNonEmptyString(record.path);\n if (!path) {\n return undefined;\n }\n\n const line = toPositiveInteger(record.line);\n const column = toPositiveInteger(record.column);\n const explicitLabel = toTrimmedNonEmptyString(record.label);\n const explicitHref = toTrimmedNonEmptyString(record.href);\n\n const location = [path];\n if (line !== undefined) {\n location.push(String(line));\n\n if (column !== undefined) {\n location.push(String(column));\n }\n }\n\n const label = explicitLabel ?? location.join(\":\");\n\n return {\n label,\n href: resolveSourceAnchorHref(path, line, column, explicitHref),\n };\n}\n\nfunction resolveNodeSourceAnchor(nodeProps: Record<string, unknown>) {\n const explicit = toSourceAnchor(nodeProps.sourceAnchor);\n if (explicit) {\n return explicit;\n }\n\n const fileFallback = toTrimmedNonEmptyString(nodeProps.file);\n if (!fileFallback) {\n return undefined;\n }\n\n return {\n label: fileFallback,\n } satisfies ParsedSourceAnchor;\n}\n\nfunction createCustomNodeContext(\n node: OrderedNodeElement,\n): FlaierCustomNodeContext<Record<string, unknown>> {\n return {\n key: node.key,\n elementType: node.element.type,\n props: node.element.props,\n sourceAnchor: resolveNodeSourceAnchor(node.element.props) as\n | FlaierResolvedSourceAnchor\n | undefined,\n };\n}\n\nfunction toCustomNodeSize(value: FlaierCustomNodeSize | undefined): NodeSize | undefined {\n if (!value) {\n return undefined;\n }\n\n const width = Number(value.width);\n const height = Number(value.height);\n\n if (!Number.isFinite(width) || !Number.isFinite(height)) {\n return undefined;\n }\n\n return {\n width: Math.max(120, Math.round(width)),\n height: Math.max(72, Math.round(height)),\n };\n}\n\nfunction getNodeSummary(node: OrderedNodeElement) {\n const customNode = getCustomNodeDefinition(node.element.type);\n if (customNode?.getSummary) {\n return customNode.getSummary(createCustomNodeContext(node)) ?? \"\";\n }\n\n if (node.element.type === \"CodeNode\") {\n return (\n toTrimmedNonEmptyString(node.element.props.story) ??\n toTrimmedNonEmptyString(node.element.props.comment) ??\n \"\"\n );\n }\n\n if (node.element.type === \"DescriptionNode\") {\n return toTrimmedNonEmptyString(node.element.props.body) ?? \"\";\n }\n\n if (node.element.type === \"DecisionNode\") {\n return (\n toTrimmedNonEmptyString(node.element.props.description) ??\n toTrimmedNonEmptyString(node.element.props.condition) ??\n \"\"\n );\n }\n\n if (node.element.type === \"PayloadNode\") {\n return toTrimmedNonEmptyString(node.element.props.description) ?? \"\";\n }\n\n if (node.element.type === \"ErrorNode\") {\n const message = toTrimmedNonEmptyString(node.element.props.message);\n const cause = toTrimmedNonEmptyString(node.element.props.cause);\n const mitigation = toTrimmedNonEmptyString(node.element.props.mitigation);\n\n return [message, cause ? `Cause: ${cause}` : \"\", mitigation ? `Mitigation: ${mitigation}` : \"\"]\n .filter((value): value is string => typeof value === \"string\" && value.length > 0)\n .join(\" \");\n }\n\n if (node.element.type === \"ArchitectureNode\") {\n const technology = toTrimmedNonEmptyString(node.element.props.technology);\n const description = toTrimmedNonEmptyString(node.element.props.description);\n\n return [technology ? `Technology: ${technology}` : \"\", description ?? \"\"]\n .filter((value): value is string => typeof value === \"string\" && value.length > 0)\n .join(\" \");\n }\n\n return toTrimmedNonEmptyString(node.element.props.description) ?? \"\";\n}\n\nfunction createCustomNodeRenderer(\n elementType: string,\n definition: FlaierCustomNodeDefinition,\n displayName: string,\n) {\n return markRaw(\n defineComponent<NodeProps<FlowNodeData>>({\n name: `Flaier${displayName}Node`,\n props: [\n \"id\",\n \"type\",\n \"selected\",\n \"connectable\",\n \"position\",\n \"dimensions\",\n \"label\",\n \"isValidTargetPos\",\n \"isValidSourcePos\",\n \"parent\",\n \"parentNodeId\",\n \"dragging\",\n \"resizing\",\n \"zIndex\",\n \"targetPosition\",\n \"sourcePosition\",\n \"dragHandle\",\n \"data\",\n \"events\",\n ],\n setup(nodeProps) {\n return () =>\n h(definition.component, {\n ...nodeProps.data?.props,\n active: nodeProps.data?.active,\n nodeKey: nodeProps.data?.key,\n elementType: nodeProps.data?.elementType ?? elementType,\n sourceAnchor: nodeProps.data?.sourceAnchor,\n });\n },\n }),\n );\n}\n\nconst customNodeTypes = computed<NodeTypesObject>(() => {\n return Object.fromEntries(\n Object.entries(customNodes.value).map(([elementType, definition]) => {\n const displayName = elementType.replace(/[^a-z0-9]+/gi, \"\") || \"Custom\";\n\n return [elementType, createCustomNodeRenderer(elementType, definition, displayName)];\n }),\n );\n});\n\nfunction codeNodeTwoslashEnabled(element: SpecElement) {\n if (element.type !== \"CodeNode\") return false;\n\n if (!normalizeTwoslashLanguage(toOptionalString(element.props.language))) {\n return false;\n }\n\n if (!hasTwoslashHtml(toTwoslashHtml(element.props.twoslashHtml))) {\n return false;\n }\n\n const requested = toOptionalBoolean(element.props.twoslash);\n if (requested === true) return true;\n if (requested === false) return false;\n\n const variants = [\n toRequiredString(element.props.code),\n ...toMagicMoveSteps(element.props.magicMoveSteps).map((step) => step.code),\n ];\n\n return variants.some((code) => hasTwoslashHints(code));\n}\n\nfunction toPositiveNumber(value: unknown, fallback: number, min = 1) {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return Math.max(min, Math.floor(value));\n }\n\n return fallback;\n}\n\nfunction toMagicMoveSteps(value: unknown): MagicMoveStep[] {\n if (!Array.isArray(value)) return [];\n\n return value\n .filter((item): item is MagicMoveStep => {\n if (!item || typeof item !== \"object\") return false;\n\n const record = item as Record<string, unknown>;\n if (typeof record.code !== \"string\") return false;\n\n const optionalKeys: Array<\"title\" | \"comment\" | \"story\" | \"speaker\"> = [\n \"title\",\n \"comment\",\n \"story\",\n \"speaker\",\n ];\n\n return optionalKeys.every((key) => {\n const current = record[key];\n return current === undefined || typeof current === \"string\";\n });\n })\n .map((item) => ({\n code: item.code,\n title: toOptionalString(item.title),\n comment: toOptionalString(item.comment),\n story: toOptionalString(item.story),\n speaker: toOptionalString(item.speaker),\n }));\n}\n\nfunction toTransitionKind(value: unknown): EdgeTransitionKind | undefined {\n if (typeof value !== \"string\") return undefined;\n return EDGE_TRANSITION_KIND_SET.has(value as EdgeTransitionKind)\n ? (value as EdgeTransitionKind)\n : undefined;\n}\n\nfunction toTransitionTransport(value: unknown): \"sync\" | \"async\" | undefined {\n if (typeof value !== \"string\") return undefined;\n return EDGE_TRANSITION_TRANSPORT_SET.has(value) ? (value as \"sync\" | \"async\") : undefined;\n}\n\nfunction toTransitionCriticality(value: unknown): \"low\" | \"medium\" | \"high\" | undefined {\n if (typeof value !== \"string\") return undefined;\n return EDGE_TRANSITION_CRITICALITY_SET.has(value)\n ? (value as \"low\" | \"medium\" | \"high\")\n : undefined;\n}\n\nfunction toTransitions(value: unknown): ParsedTransition[] {\n if (!Array.isArray(value)) return [];\n\n return value\n .filter((item): item is Record<string, unknown> => {\n if (!item || typeof item !== \"object\") return false;\n if (!toOptionalString(item.to)) return false;\n\n const label = item.label;\n const description = item.description;\n const kind = item.kind;\n const protocol = item.protocol;\n const transport = item.transport;\n const auth = item.auth;\n const contract = item.contract;\n const criticality = item.criticality;\n\n if (label !== undefined && typeof label !== \"string\") return false;\n if (description !== undefined && typeof description !== \"string\") return false;\n if (kind !== undefined && !toTransitionKind(kind)) return false;\n if (protocol !== undefined && typeof protocol !== \"string\") return false;\n if (transport !== undefined && !toTransitionTransport(transport)) return false;\n if (auth !== undefined && typeof auth !== \"string\") return false;\n if (contract !== undefined && typeof contract !== \"string\") return false;\n if (criticality !== undefined && !toTransitionCriticality(criticality)) return false;\n\n return true;\n })\n .map((item) => ({\n to: toRequiredString(item.to),\n label: toOptionalString(item.label),\n description: toOptionalString(item.description),\n kind: toTransitionKind(item.kind),\n protocol: toOptionalString(item.protocol),\n transport: toTransitionTransport(item.transport),\n auth: toOptionalString(item.auth),\n contract: toOptionalString(item.contract),\n criticality: toTransitionCriticality(item.criticality),\n }));\n}\n\nfunction resolveTransitionEdgeLabel(transition?: ParsedTransition) {\n if (!transition) {\n return undefined;\n }\n\n const metadataParts = [transition.protocol, transition.transport, transition.criticality].filter(\n (value): value is string => Boolean(value),\n );\n\n if (transition.label) {\n return metadataParts.length > 0\n ? `${transition.label} (${metadataParts.join(\" | \")})`\n : transition.label;\n }\n\n if (metadataParts.length > 0) {\n return metadataParts.join(\" | \");\n }\n\n return undefined;\n}\n\nfunction mergeOutgoingTargets(primary: string[], secondary: string[]) {\n const merged: string[] = [];\n const seen = new Set<string>();\n\n for (const target of [...primary, ...secondary]) {\n if (!target || seen.has(target)) continue;\n\n seen.add(target);\n merged.push(target);\n }\n\n return merged;\n}\n\nfunction getNodeFrameCount(element: SpecElement) {\n if (element.type !== \"CodeNode\") return 1;\n\n const magicMoveSteps = toMagicMoveSteps(element.props.magicMoveSteps);\n const baseSteps = Math.max(1, magicMoveSteps.length);\n\n if (magicMoveSteps.length > 0 && codeNodeTwoslashEnabled(element)) {\n return baseSteps + 1;\n }\n\n return baseSteps;\n}\n\nfunction getCodeNodeMaxLines(element: SpecElement) {\n const rootCodeLines = toRequiredString(element.props.code).split(\"\\n\").length;\n const stepLines = toMagicMoveSteps(element.props.magicMoveSteps).map(\n (step) => step.code.split(\"\\n\").length,\n );\n\n return Math.max(rootCodeLines, ...stepLines);\n}\n\nfunction getCodeNodeMaxLineLength(element: SpecElement) {\n const variants = [\n toRequiredString(element.props.code),\n ...toMagicMoveSteps(element.props.magicMoveSteps).map((step) => step.code),\n ];\n\n return variants.reduce((max, code) => {\n const lineMax = code\n .split(\"\\n\")\n .reduce((lineLengthMax, line) => Math.max(lineLengthMax, line.length), 0);\n\n return Math.max(max, lineMax);\n }, 0);\n}\n\nfunction estimateWrappedLines(text: string, charsPerLine = 48) {\n return text\n .split(\"\\n\")\n .reduce((total, line) => total + Math.max(1, Math.ceil(line.length / charsPerLine)), 0);\n}\n\nfunction getCodeNodeWrappedLines(element: SpecElement, charsPerLine = 44) {\n const variants = [\n toRequiredString(element.props.code),\n ...toMagicMoveSteps(element.props.magicMoveSteps).map((step) => step.code),\n ];\n\n return variants.reduce((max, code) => {\n return Math.max(max, estimateWrappedLines(code, charsPerLine));\n }, 1);\n}\n\nfunction hasCodeNodeStoryMeta(element: SpecElement) {\n return toMagicMoveSteps(element.props.magicMoveSteps).some((step) => step.title || step.speaker);\n}\n\nfunction getCodeNodeStoryLines(element: SpecElement) {\n const variants = [\n toOptionalString(element.props.story),\n toOptionalString(element.props.comment),\n ...toMagicMoveSteps(element.props.magicMoveSteps).flatMap((step) => [step.story, step.comment]),\n ].filter((value): value is string => typeof value === \"string\" && value.length > 0);\n\n if (variants.length === 0) return 0;\n\n return variants.reduce((max, current) => Math.max(max, estimateWrappedLines(current)), 1);\n}\n\nfunction estimateNodeTextLines(value: unknown, charsPerLine: number) {\n const text = toOptionalString(value);\n if (!text) return 0;\n return estimateWrappedLines(text, charsPerLine);\n}\n\nfunction estimateCodeNodeSize(element: SpecElement): NodeSize {\n const maxLineLength = getCodeNodeMaxLineLength(element);\n const nodeWidth = estimateCodeNodeWidth(maxLineLength);\n const codeCharsPerLine = estimateCodeNodeCharsPerLine(nodeWidth);\n const autoWrapEnabled = maxLineLength > CODE_NODE_MAX_INLINE_CHARS;\n const wrapEnabled = toBoolean(element.props.wrapLongLines) || autoWrapEnabled;\n\n const codeLines = wrapEnabled\n ? getCodeNodeWrappedLines(element, codeCharsPerLine)\n : getCodeNodeMaxLines(element);\n const storyLines = getCodeNodeStoryLines(element);\n const storyHasMeta = hasCodeNodeStoryMeta(element);\n\n const codeViewportHeight = wrapEnabled\n ? Math.min(400, Math.max(190, 72 + codeLines * 16))\n : Math.min(340, Math.max(160, 84 + codeLines * 17));\n\n const storyViewportHeight =\n storyLines > 0 ? Math.min(220, Math.max(88, (storyHasMeta ? 56 : 34) + storyLines * 18)) : 0;\n\n return {\n width: nodeWidth,\n height: Math.min(760, Math.max(230, 42 + codeViewportHeight + storyViewportHeight + 14)),\n };\n}\n\nfunction estimateNodeSize(node: OrderedNodeElement): NodeSize {\n const { element } = node;\n const customNode = getCustomNodeDefinition(element.type);\n\n if (customNode?.estimateSize) {\n const customSize = toCustomNodeSize(customNode.estimateSize(createCustomNodeContext(node)));\n if (customSize) {\n return customSize;\n }\n }\n\n if (customNode) {\n return {\n width: 240,\n height: 120,\n };\n }\n\n if (element.type === \"ArchitectureNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 28));\n const technologyLines = estimateNodeTextLines(element.props.technology, 30);\n const ownerLines = estimateNodeTextLines(element.props.owner, 30);\n const runtimeLines = estimateNodeTextLines(element.props.runtime, 30);\n const descriptionLines = estimateNodeTextLines(element.props.description, 34);\n const capabilityCount = Math.min(4, toStringArray(element.props.capabilities).length);\n const tagCount = Math.min(4, toStringArray(element.props.tags).length);\n const chipRows =\n (capabilityCount > 0 ? Math.ceil(capabilityCount / 2) : 0) + (tagCount > 0 ? 1 : 0);\n const metaRows =\n toArchitectureStatus(element.props.status) || toArchitectureTier(element.props.tier) ? 1 : 0;\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 270,\n height: Math.min(\n 460,\n Math.max(\n 144,\n 58 +\n labelLines * 19 +\n technologyLines * 14 +\n ownerLines * 12 +\n runtimeLines * 12 +\n descriptionLines * 15 +\n metaRows * 16 +\n chipRows * 18 +\n anchorHeight,\n ),\n ),\n };\n }\n\n if (element.type === \"CodeNode\") {\n return estimateCodeNodeSize(element);\n }\n\n if (element.type === \"TriggerNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 24));\n const descriptionLines = estimateNodeTextLines(element.props.description, 30);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 220,\n height: Math.min(\n 300,\n Math.max(100, 46 + labelLines * 18 + descriptionLines * 15 + anchorHeight),\n ),\n };\n }\n\n if (element.type === \"DecisionNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 26));\n const conditionLines = estimateNodeTextLines(element.props.condition, 34);\n const descriptionLines = estimateNodeTextLines(element.props.description, 34);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 250,\n height: Math.min(\n 360,\n Math.max(\n 122,\n 50 + labelLines * 18 + conditionLines * 16 + descriptionLines * 15 + anchorHeight,\n ),\n ),\n };\n }\n\n if (element.type === \"PayloadNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 32));\n const descriptionLines = estimateNodeTextLines(element.props.description, 34);\n const beforeLines = estimateNodeTextLines(element.props.before, 40);\n const afterLines = estimateNodeTextLines(element.props.after, 40);\n const payloadLines = estimateNodeTextLines(element.props.payload, 40);\n const bodyLines = Math.max(payloadLines, beforeLines + afterLines);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 300,\n height: Math.min(\n 540,\n Math.max(160, 60 + labelLines * 18 + descriptionLines * 14 + bodyLines * 10 + anchorHeight),\n ),\n };\n }\n\n if (element.type === \"ErrorNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 30));\n const messageLines = Math.max(1, estimateNodeTextLines(element.props.message, 34));\n const causeLines = estimateNodeTextLines(element.props.cause, 34);\n const mitigationLines = estimateNodeTextLines(element.props.mitigation, 34);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 280,\n height: Math.min(\n 440,\n Math.max(\n 140,\n 58 +\n labelLines * 18 +\n messageLines * 16 +\n causeLines * 15 +\n mitigationLines * 15 +\n anchorHeight,\n ),\n ),\n };\n }\n\n if (element.type === \"DescriptionNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 26));\n const bodyLines = Math.max(1, estimateNodeTextLines(element.props.body, 30));\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 240,\n height: Math.min(360, Math.max(118, 44 + labelLines * 18 + bodyLines * 16 + anchorHeight)),\n };\n }\n\n if (element.type === \"LinkNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 24));\n const descriptionLines = estimateNodeTextLines(element.props.description, 30);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 220,\n height: Math.min(\n 300,\n Math.max(98, 42 + labelLines * 18 + descriptionLines * 15 + anchorHeight),\n ),\n };\n }\n\n return {\n width: 240,\n height: 120,\n };\n}\n\nconst selectedBranchByNode = ref<Record<string, string>>({});\nconst pathFrames = ref<TimelineFrame[]>([]);\n\nfunction createFramesForNode(nodeKey: string): TimelineFrame[] {\n const node = orderedNodeByKey.value[nodeKey];\n if (!node) return [];\n\n const totalLocalSteps = getNodeFrameCount(node.element);\n\n return Array.from({ length: totalLocalSteps }, (_, localStep) => ({\n nodeIndex: node.index,\n nodeKey,\n localStep,\n totalLocalSteps,\n }));\n}\n\nfunction resolveNextNode(nodeKey: string, options: string[]) {\n const selected = selectedBranchByNode.value[nodeKey];\n if (selected && options.includes(selected)) {\n return selected;\n }\n\n return options[0];\n}\n\nfunction buildGuidedPath(startKey: string, maxFrames = 450): TimelineFrame[] {\n const frames: TimelineFrame[] = [];\n const visitedEdges = new Map<string, number>();\n let currentKey: string | undefined = startKey;\n\n while (currentKey && frames.length < maxFrames) {\n const nodeFrames = createFramesForNode(currentKey);\n if (nodeFrames.length === 0) break;\n\n frames.push(...nodeFrames);\n\n const options = outgoingNodeKeys.value[currentKey] ?? [];\n if (options.length === 0) break;\n\n const nextKey = resolveNextNode(currentKey, options);\n if (!nextKey) break;\n\n const edgeKey = `${currentKey}->${nextKey}`;\n const edgeVisits = (visitedEdges.get(edgeKey) ?? 0) + 1;\n visitedEdges.set(edgeKey, edgeVisits);\n if (edgeVisits > 2) break;\n\n currentKey = nextKey;\n }\n\n return frames;\n}\n\nfunction findNearestFrameIndex(frames: TimelineFrame[], nodeKey: string, anchor = 0) {\n let bestIndex = -1;\n let bestDistance = Number.POSITIVE_INFINITY;\n\n for (let index = 0; index < frames.length; index += 1) {\n if (frames[index]?.nodeKey !== nodeKey) continue;\n\n const distance = Math.abs(index - anchor);\n if (distance < bestDistance) {\n bestDistance = distance;\n bestIndex = index;\n }\n }\n\n return bestIndex;\n}\n\nfunction sortOptionsForTraversal(sourceKey: string, options: string[]) {\n const selected = selectedBranchByNode.value[sourceKey];\n\n return [...options].sort((a, b) => {\n const aSelected = a === selected;\n const bSelected = b === selected;\n\n if (aSelected !== bSelected) {\n return aSelected ? -1 : 1;\n }\n\n const aIndex = orderedNodeByKey.value[a]?.index ?? Number.MAX_SAFE_INTEGER;\n const bIndex = orderedNodeByKey.value[b]?.index ?? Number.MAX_SAFE_INTEGER;\n\n return aIndex - bIndex;\n });\n}\n\nfunction findPathKeysToNode(startKey: string, targetKey: string) {\n if (startKey === targetKey) {\n return [startKey];\n }\n\n const queue: Array<{ key: string; path: string[]; depth: number }> = [\n {\n key: startKey,\n path: [startKey],\n depth: 0,\n },\n ];\n\n const visitedDepth = new Map<string, number>([[startKey, 0]]);\n const maxDepth = Math.max(8, orderedNodeElements.value.length + 8);\n const maxIterations = Math.max(\n 80,\n orderedNodeElements.value.length * orderedNodeElements.value.length * 2,\n );\n let guard = 0;\n\n while (queue.length > 0 && guard < maxIterations) {\n guard += 1;\n\n const current = queue.shift();\n if (!current) continue;\n if (current.depth >= maxDepth) continue;\n\n const options = sortOptionsForTraversal(current.key, outgoingNodeKeys.value[current.key] ?? []);\n\n for (const option of options) {\n if (!orderedNodeByKey.value[option]) continue;\n\n const nextDepth = current.depth + 1;\n if (option === targetKey) {\n return [...current.path, option];\n }\n\n const knownDepth = visitedDepth.get(option);\n if (knownDepth !== undefined && knownDepth <= nextDepth) {\n continue;\n }\n\n visitedDepth.set(option, nextDepth);\n queue.push({\n key: option,\n path: [...current.path, option],\n depth: nextDepth,\n });\n }\n }\n\n return null;\n}\n\nfunction applyBranchSelectionsForPath(pathKeys: string[]) {\n if (pathKeys.length < 2) return;\n\n const nextSelected = { ...selectedBranchByNode.value };\n\n for (let index = 0; index < pathKeys.length - 1; index += 1) {\n const source = pathKeys[index];\n const target = pathKeys[index + 1];\n if (!source || !target) continue;\n\n const options = outgoingNodeKeys.value[source] ?? [];\n if (options.length > 1 && options.includes(target)) {\n nextSelected[source] = target;\n }\n }\n\n selectedBranchByNode.value = nextSelected;\n}\n\nconst totalSteps = computed(() => pathFrames.value.length);\nconst maxStepIndex = computed(() => Math.max(0, totalSteps.value - 1));\n\nconst { set } = useStateStore();\nconst currentStepState = useStateValue<number>(\"/currentStep\");\nconst playingState = useStateValue<boolean>(\"/playing\");\n\nfunction clampStep(value: number) {\n if (!Number.isFinite(value)) return 0;\n const step = Math.floor(value);\n return Math.max(0, Math.min(step, maxStepIndex.value));\n}\n\nconst currentStep = computed<number>({\n get() {\n return clampStep(Number(currentStepState.value ?? 0));\n },\n set(value: number) {\n set(\"/currentStep\", clampStep(value));\n },\n});\n\nconst playing = computed<boolean>({\n get() {\n return Boolean(playingState.value ?? false);\n },\n set(value: boolean) {\n set(\"/playing\", value);\n },\n});\n\nwatch(\n [startNodeKey, orderedNodeElements, isArchitectureMode],\n ([start, , architectureMode]) => {\n if (architectureMode) {\n selectedBranchByNode.value = {};\n pathFrames.value = [];\n currentStep.value = 0;\n playing.value = false;\n return;\n }\n\n selectedBranchByNode.value = {};\n\n if (!start) {\n pathFrames.value = [];\n currentStep.value = 0;\n return;\n }\n\n const built = buildGuidedPath(start);\n pathFrames.value = built.length > 0 ? built : createFramesForNode(start);\n currentStep.value = clampStep(Number(currentStepState.value ?? 0));\n },\n { immediate: true },\n);\n\nwatch(totalSteps, () => {\n currentStep.value = clampStep(currentStep.value);\n});\n\nconst intervalMs = computed(() => {\n const value = Number(runtime.interval.value);\n if (!Number.isFinite(value) || value <= 0) return 3000;\n return Math.max(250, Math.floor(value));\n});\n\nlet timer: ReturnType<typeof setInterval> | null = null;\n\nfunction clearTimer() {\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n}\n\nfunction pauseNarrativePlayback() {\n if (!isArchitectureMode.value) {\n playing.value = false;\n }\n}\n\nfunction next(manual = true) {\n if (isArchitectureMode.value) {\n return false;\n }\n\n if (manual) {\n pauseNarrativePlayback();\n }\n\n if (currentStep.value >= totalSteps.value - 1) {\n return false;\n }\n\n currentStep.value += 1;\n return true;\n}\n\nwatch(\n [playing, totalSteps, intervalMs],\n ([isPlaying, steps, interval]) => {\n clearTimer();\n\n if (!isPlaying || steps <= 1) return;\n\n timer = setInterval(() => {\n const advanced = next(false);\n if (!advanced) {\n playing.value = false;\n }\n }, interval);\n },\n { immediate: true },\n);\n\nfunction prev(manual = true) {\n if (isArchitectureMode.value) {\n return;\n }\n\n if (manual) {\n pauseNarrativePlayback();\n }\n\n if (currentStep.value > 0) {\n currentStep.value -= 1;\n }\n}\n\nfunction goTo(step: number, manual = true) {\n if (isArchitectureMode.value) {\n return;\n }\n\n if (manual) {\n pauseNarrativePlayback();\n }\n\n currentStep.value = clampStep(step);\n}\n\nfunction togglePlay() {\n if (isArchitectureMode.value) {\n playing.value = false;\n return;\n }\n\n if (totalSteps.value <= 1) {\n playing.value = false;\n return;\n }\n\n playing.value = !playing.value;\n}\n\nconst activeFrame = computed(() => pathFrames.value[currentStep.value]);\nconst nextPlannedNodeKey = computed(() => pathFrames.value[currentStep.value + 1]?.nodeKey);\n\nfunction jumpToNode(nodeKey: string) {\n if (!orderedNodeByKey.value[nodeKey]) return;\n\n playing.value = false;\n\n const existingIndex = findNearestFrameIndex(pathFrames.value, nodeKey, currentStep.value);\n if (existingIndex >= 0) {\n currentStep.value = existingIndex;\n return;\n }\n\n const start = startNodeKey.value;\n if (!start) {\n const standaloneFrames = createFramesForNode(nodeKey);\n if (standaloneFrames.length === 0) return;\n\n pathFrames.value = standaloneFrames;\n currentStep.value = 0;\n return;\n }\n\n const pathKeys = findPathKeysToNode(start, nodeKey);\n if (pathKeys) {\n applyBranchSelectionsForPath(pathKeys);\n }\n\n const rebuiltFrames = buildGuidedPath(start);\n pathFrames.value = rebuiltFrames.length > 0 ? rebuiltFrames : createFramesForNode(start);\n\n const rebuiltIndex = findNearestFrameIndex(pathFrames.value, nodeKey, currentStep.value);\n if (rebuiltIndex >= 0) {\n currentStep.value = rebuiltIndex;\n return;\n }\n\n const standaloneFrames = createFramesForNode(nodeKey);\n if (standaloneFrames.length === 0) return;\n\n pathFrames.value = standaloneFrames;\n currentStep.value = 0;\n}\n\nconst resolvedLayoutEngine = computed<\"dagre\" | \"manual\">(() => {\n return props.layoutEngine === \"manual\" ? \"manual\" : DEFAULT_LAYOUT_ENGINE;\n});\n\nconst resolvedLayoutRankSep = computed(() => {\n const fallback =\n props.direction === \"vertical\"\n ? DEFAULT_DAGRE_RANK_SEP_VERTICAL\n : DEFAULT_DAGRE_RANK_SEP_HORIZONTAL;\n\n return toPositiveNumber(props.layoutRankSep, fallback, 80);\n});\n\nconst resolvedLayoutNodeSep = computed(() => {\n const fallback =\n props.direction === \"vertical\"\n ? DEFAULT_DAGRE_NODE_SEP_VERTICAL\n : DEFAULT_DAGRE_NODE_SEP_HORIZONTAL;\n\n return toPositiveNumber(props.layoutNodeSep, fallback, 40);\n});\n\nconst resolvedLayoutEdgeSep = computed(() => {\n return toPositiveNumber(props.layoutEdgeSep, DEFAULT_DAGRE_EDGE_SEP, 8);\n});\n\nfunction createFallbackLayoutPositions(\n nodes: OrderedNodeElement[],\n rankGap = DEFAULT_FALLBACK_GAP,\n) {\n const mainGap = Math.max(80, rankGap);\n const positions: Record<string, { x: number; y: number }> = {};\n\n for (const node of nodes) {\n if (props.direction === \"vertical\") {\n positions[node.key] = { x: 0, y: node.index * mainGap };\n continue;\n }\n\n positions[node.key] = { x: node.index * mainGap, y: 0 };\n }\n\n return positions;\n}\n\nfunction normalizePositions(positions: Record<string, { x: number; y: number }>) {\n if (Object.keys(positions).length === 0) {\n return positions;\n }\n\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n\n for (const position of Object.values(positions)) {\n minX = Math.min(minX, position.x);\n minY = Math.min(minY, position.y);\n }\n\n for (const key of Object.keys(positions)) {\n const currentPosition = positions[key];\n if (!currentPosition) continue;\n\n positions[key] = {\n x: currentPosition.x - minX,\n y: currentPosition.y - minY,\n };\n }\n\n return positions;\n}\n\nfunction createManualLayoutPositions(\n orderedNodes: OrderedNodeElement[],\n rankGap: number,\n laneGap: number,\n) {\n if (orderedNodes.length === 0) return {};\n\n const depthByKey: Record<string, number> = {};\n for (const node of orderedNodes) {\n depthByKey[node.key] = Number.NEGATIVE_INFINITY;\n }\n\n const startKey = startNodeKey.value ?? orderedNodes[0]?.key;\n if (!startKey) {\n return createFallbackLayoutPositions(orderedNodes, rankGap);\n }\n\n depthByKey[startKey] = 0;\n\n const queue: string[] = [startKey];\n const maxDepth = Math.max(0, orderedNodes.length - 1);\n let guard = 0;\n const maxIterations = Math.max(24, orderedNodes.length * orderedNodes.length);\n\n while (queue.length > 0 && guard < maxIterations) {\n guard += 1;\n\n const key = queue.shift();\n if (!key) continue;\n\n const baseDepth = depthByKey[key] ?? Number.NEGATIVE_INFINITY;\n if (!Number.isFinite(baseDepth)) continue;\n\n for (const target of outgoingNodeKeys.value[key] ?? []) {\n if (!(target in depthByKey)) continue;\n\n const candidateDepth = Math.min(maxDepth, baseDepth + 1);\n const currentDepth = depthByKey[target] ?? Number.NEGATIVE_INFINITY;\n\n if (candidateDepth > currentDepth) {\n depthByKey[target] = candidateDepth;\n queue.push(target);\n }\n }\n }\n\n let fallbackDepth = 0;\n for (const node of orderedNodes) {\n if (Number.isFinite(depthByKey[node.key])) continue;\n\n depthByKey[node.key] = Math.min(maxDepth, fallbackDepth);\n fallbackDepth += 1;\n }\n\n const layers: Record<number, string[]> = {};\n for (const node of orderedNodes) {\n const depth = depthByKey[node.key] ?? 0;\n if (!layers[depth]) {\n layers[depth] = [];\n }\n\n layers[depth].push(node.key);\n }\n\n const laneByKey: Record<string, number> = {};\n const sortedDepths = Object.keys(layers)\n .map(Number)\n .sort((a, b) => a - b);\n\n for (const depth of sortedDepths) {\n const layerKeys = [...(layers[depth] ?? [])];\n\n layerKeys.sort((a, b) => {\n const aParents = (incomingNodeKeys.value[a] ?? []).filter((parent) => {\n const parentDepth = depthByKey[parent] ?? Number.NEGATIVE_INFINITY;\n return Number.isFinite(parentDepth) && parentDepth < depth;\n });\n const bParents = (incomingNodeKeys.value[b] ?? []).filter((parent) => {\n const parentDepth = depthByKey[parent] ?? Number.NEGATIVE_INFINITY;\n return Number.isFinite(parentDepth) && parentDepth < depth;\n });\n\n const aAnchor =\n aParents.length > 0\n ? aParents.reduce((sum, parent) => sum + (laneByKey[parent] ?? 0), 0) / aParents.length\n : 0;\n const bAnchor =\n bParents.length > 0\n ? bParents.reduce((sum, parent) => sum + (laneByKey[parent] ?? 0), 0) / bParents.length\n : 0;\n\n if (aAnchor === bAnchor) {\n const aIndex = orderedNodeByKey.value[a]?.index ?? 0;\n const bIndex = orderedNodeByKey.value[b]?.index ?? 0;\n return aIndex - bIndex;\n }\n\n return aAnchor - bAnchor;\n });\n\n const count = layerKeys.length;\n layerKeys.forEach((key, index) => {\n laneByKey[key] = (index - (count - 1) / 2) * laneGap;\n });\n }\n\n const positions: Record<string, { x: number; y: number }> = {};\n\n for (const node of orderedNodes) {\n const depth = depthByKey[node.key] ?? 0;\n const lane = laneByKey[node.key] ?? 0;\n\n if (props.direction === \"vertical\") {\n positions[node.key] = {\n x: Math.round(lane),\n y: Math.round(depth * rankGap),\n };\n continue;\n }\n\n positions[node.key] = {\n x: Math.round(depth * rankGap),\n y: Math.round(lane),\n };\n }\n\n return normalizePositions(positions);\n}\n\nconst nodeSizes = computed<Record<string, NodeSize>>(() => {\n const sizes: Record<string, NodeSize> = {};\n\n for (const node of orderedNodeElements.value) {\n sizes[node.key] = estimateNodeSize(node);\n }\n\n return sizes;\n});\n\nconst architectureZoneDefinitions = computed<ResolvedArchitectureZone[]>(() => {\n if (!isArchitectureMode.value) {\n return [];\n }\n\n const rootZones = toArchitectureZones(props.zones ?? rootElement.value?.props.zones);\n const byId = new Map<string, ResolvedArchitectureZone>();\n\n for (const zone of rootZones) {\n byId.set(zone.id, zone);\n }\n\n for (const node of orderedNodeElements.value) {\n const zoneId = toArchitectureZoneId(node.element.props.zone);\n if (!zoneId || byId.has(zoneId)) {\n continue;\n }\n\n byId.set(zoneId, {\n id: zoneId,\n label: humanizeZoneId(zoneId),\n padding: 62,\n });\n }\n\n return Array.from(byId.values());\n});\n\nconst architectureZoneLabelById = computed<Record<string, string>>(() => {\n const map: Record<string, string> = {};\n\n for (const zone of architectureZoneDefinitions.value) {\n map[zone.id] = zone.label;\n }\n\n return map;\n});\n\nconst architectureNodeZoneByKey = computed<Record<string, string>>(() => {\n const map: Record<string, string> = {};\n\n for (const node of orderedNodeElements.value) {\n const zoneId = toArchitectureZoneId(node.element.props.zone);\n if (!zoneId) {\n continue;\n }\n\n map[node.key] = zoneId;\n }\n\n return map;\n});\n\nconst architectureZoneOverlays = computed<ArchitectureZoneOverlay[]>(() => {\n if (!isArchitectureMode.value) {\n return [];\n }\n\n const rawOverlays: Array<{\n id: string;\n label: string;\n description?: string;\n color: string;\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n padding: number;\n nodeCount: number;\n sourceIndex: number;\n }> = [];\n\n architectureZoneDefinitions.value.forEach((zone, index) => {\n const members = orderedNodeElements.value.filter(\n (node) => architectureNodeZoneByKey.value[node.key] === zone.id,\n );\n if (members.length === 0) {\n return;\n }\n\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n\n for (const member of members) {\n const position = layoutPositions.value[member.key];\n if (!position) {\n continue;\n }\n\n const size = nodeSizes.value[member.key] ?? { width: 240, height: 120 };\n\n minX = Math.min(minX, position.x);\n minY = Math.min(minY, position.y);\n maxX = Math.max(maxX, position.x + size.width);\n maxY = Math.max(maxY, position.y + size.height);\n }\n\n if (\n !Number.isFinite(minX) ||\n !Number.isFinite(minY) ||\n !Number.isFinite(maxX) ||\n !Number.isFinite(maxY)\n ) {\n return;\n }\n\n const padding = zone.padding;\n rawOverlays.push({\n id: zone.id,\n label: zone.label,\n description: zone.description,\n color: resolveZoneColor(index, zone.color),\n minX,\n minY,\n maxX,\n maxY,\n padding,\n nodeCount: members.length,\n sourceIndex: index,\n });\n });\n\n const provisionalBounds = rawOverlays.map((overlay) => ({\n id: overlay.id,\n x: overlay.minX - overlay.padding,\n y: overlay.minY - overlay.padding,\n width: overlay.maxX - overlay.minX + overlay.padding * 2,\n height: overlay.maxY - overlay.minY + overlay.padding * 2,\n }));\n\n const nestingDepthById = new Map<string, number>();\n const containsNestedZoneById = new Map<string, boolean>();\n\n for (const current of provisionalBounds) {\n const depth = provisionalBounds.reduce((count, candidate) => {\n if (candidate.id === current.id) {\n return count;\n }\n\n const containsCurrent =\n candidate.x <= current.x + 12 &&\n candidate.y <= current.y + 12 &&\n candidate.x + candidate.width >= current.x + current.width - 12 &&\n candidate.y + candidate.height >= current.y + current.height - 12;\n\n return containsCurrent ? count + 1 : count;\n }, 0);\n\n nestingDepthById.set(current.id, depth);\n containsNestedZoneById.set(\n current.id,\n provisionalBounds.some((candidate) => {\n if (candidate.id === current.id) {\n return false;\n }\n\n return (\n current.x <= candidate.x + 12 &&\n current.y <= candidate.y + 12 &&\n current.x + current.width >= candidate.x + candidate.width - 12 &&\n current.y + current.height >= candidate.y + candidate.height - 12\n );\n }),\n );\n }\n\n const overlappingZoneIds = new Set<string>();\n for (let index = 0; index < provisionalBounds.length; index += 1) {\n const current = provisionalBounds[index];\n if (!current) {\n continue;\n }\n\n for (let compareIndex = index + 1; compareIndex < provisionalBounds.length; compareIndex += 1) {\n const candidate = provisionalBounds[compareIndex];\n if (!candidate) {\n continue;\n }\n\n const overlaps =\n current.x < candidate.x + candidate.width &&\n current.x + current.width > candidate.x &&\n current.y < candidate.y + candidate.height &&\n current.y + current.height > candidate.y;\n\n if (!overlaps) {\n continue;\n }\n\n overlappingZoneIds.add(current.id);\n overlappingZoneIds.add(candidate.id);\n }\n }\n\n const labelLaneById = new Map<string, number>();\n const placedLabelBoxes: Array<{\n id: string;\n lane: number;\n x: number;\n y: number;\n width: number;\n height: number;\n }> = [];\n const sortedForLabelPlacement = rawOverlays\n .map((overlay) => {\n const sidePadding = Math.max(overlay.padding, ARCHITECTURE_ZONE_MIN_CONTENT_PADDING);\n const descriptionReserve = overlay.description\n ? ARCHITECTURE_ZONE_DESCRIPTION_HEIGHT + ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP\n : 0;\n const topPadding =\n sidePadding +\n ARCHITECTURE_ZONE_LABEL_HEIGHT +\n ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP +\n descriptionReserve;\n const width = Math.min(\n Math.max(132, overlay.label.length * 7 + String(overlay.nodeCount).length * 14 + 86),\n Math.max(148, overlay.maxX - overlay.minX + sidePadding * 2 - 28),\n );\n\n return {\n id: overlay.id,\n x: overlay.minX - sidePadding + 16,\n y: overlay.minY - topPadding + ARCHITECTURE_ZONE_LABEL_TOP,\n width,\n };\n })\n .sort((a, b) => {\n if (a.y !== b.y) {\n return a.y - b.y;\n }\n\n return a.x - b.x;\n });\n\n for (const labelCandidate of sortedForLabelPlacement) {\n let lane = 0;\n\n while (\n placedLabelBoxes.some((placed) => {\n if (placed.lane !== lane) {\n return false;\n }\n\n const currentY = labelCandidate.y + lane * ARCHITECTURE_ZONE_NESTED_LABEL_STEP;\n return (\n labelCandidate.x < placed.x + placed.width &&\n labelCandidate.x + labelCandidate.width > placed.x &&\n currentY < placed.y + placed.height &&\n currentY + ARCHITECTURE_ZONE_LABEL_HEIGHT > placed.y\n );\n })\n ) {\n lane += 1;\n }\n\n labelLaneById.set(labelCandidate.id, lane);\n placedLabelBoxes.push({\n id: labelCandidate.id,\n lane,\n x: labelCandidate.x,\n y: labelCandidate.y + lane * ARCHITECTURE_ZONE_NESTED_LABEL_STEP,\n width: labelCandidate.width,\n height: ARCHITECTURE_ZONE_LABEL_HEIGHT,\n });\n }\n\n const maxLabelLane = placedLabelBoxes.reduce((max, placed) => Math.max(max, placed.lane), 0);\n\n return rawOverlays\n .map((overlay) => {\n const nestingDepth = nestingDepthById.get(overlay.id) ?? 0;\n const nestedZoneGap = containsNestedZoneById.get(overlay.id)\n ? ARCHITECTURE_ZONE_CONTAINED_ZONE_GAP\n : 0;\n const baseSidePadding = Math.max(overlay.padding, ARCHITECTURE_ZONE_MIN_CONTENT_PADDING);\n const sidePadding = baseSidePadding + nestedZoneGap;\n const bottomPadding =\n Math.max(baseSidePadding, ARCHITECTURE_ZONE_MIN_BOTTOM_PADDING) + nestedZoneGap;\n const labelLane = labelLaneById.get(overlay.id) ?? 0;\n const labelOffsetY =\n ARCHITECTURE_ZONE_LABEL_TOP + labelLane * ARCHITECTURE_ZONE_NESTED_LABEL_STEP;\n const showDescription = Boolean(overlay.description) && !overlappingZoneIds.has(overlay.id);\n const descriptionOffsetY =\n labelOffsetY + ARCHITECTURE_ZONE_LABEL_HEIGHT + ARCHITECTURE_ZONE_LABEL_TO_DESCRIPTION_GAP;\n const descriptionReserve = showDescription\n ? ARCHITECTURE_ZONE_DESCRIPTION_HEIGHT + ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP\n : 0;\n const topPadding =\n sidePadding +\n ARCHITECTURE_ZONE_LABEL_HEIGHT +\n ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP +\n descriptionReserve +\n maxLabelLane * ARCHITECTURE_ZONE_NESTED_LABEL_STEP;\n\n return {\n id: overlay.id,\n label: overlay.label,\n description: showDescription ? overlay.description : undefined,\n color: overlay.color,\n x: Math.round(overlay.minX - sidePadding),\n y: Math.round(overlay.minY - topPadding),\n width: Math.max(120, Math.round(overlay.maxX - overlay.minX + sidePadding * 2)),\n height: Math.max(100, Math.round(overlay.maxY - overlay.minY + topPadding + bottomPadding)),\n nodeCount: overlay.nodeCount,\n nestingDepth,\n labelLane,\n labelOffsetY,\n descriptionOffsetY,\n sourceIndex: overlay.sourceIndex,\n };\n })\n .sort((a, b) => {\n const areaDiff = b.width * b.height - a.width * a.height;\n if (areaDiff !== 0) {\n return areaDiff;\n }\n\n return a.sourceIndex - b.sourceIndex;\n })\n .map(({ sourceIndex: _sourceIndex, ...overlay }) => overlay);\n});\n\nfunction architectureZoneCardStyle(zone: ArchitectureZoneOverlay) {\n return {\n left: `${zone.x}px`,\n top: `${zone.y}px`,\n width: `${zone.width}px`,\n height: `${zone.height}px`,\n borderColor: withAlpha(zone.color, 0.38),\n background: `linear-gradient(180deg, ${withAlpha(zone.color, 0.1)} 0%, ${withAlpha(zone.color, 0.045)} 62%, ${withAlpha(zone.color, 0.03)} 100%)`,\n boxShadow: `inset 0 0 0 1px ${withAlpha(zone.color, 0.1)}`,\n };\n}\n\nfunction architectureZoneLabelStyle(zone: ArchitectureZoneOverlay) {\n return {\n top: `${zone.labelOffsetY}px`,\n borderColor: withAlpha(zone.color, 0.55),\n background: withAlpha(zone.color, 0.18),\n color: zone.color,\n };\n}\n\nfunction architectureZoneDescriptionStyle(zone: ArchitectureZoneOverlay) {\n return {\n top: `${zone.descriptionOffsetY}px`,\n };\n}\n\nconst layoutPositions = computed<Record<string, { x: number; y: number }>>(() => {\n const orderedNodes = orderedNodeElements.value;\n if (orderedNodes.length === 0) return {};\n\n const rankGap = resolvedLayoutRankSep.value;\n const nodeGap = resolvedLayoutNodeSep.value;\n const edgeGap = resolvedLayoutEdgeSep.value;\n const fallback = createFallbackLayoutPositions(orderedNodes, rankGap);\n\n if (resolvedLayoutEngine.value === \"manual\") {\n return createManualLayoutPositions(orderedNodes, rankGap, nodeGap);\n }\n\n const graph = new dagre.graphlib.Graph();\n graph.setDefaultEdgeLabel(() => ({}));\n graph.setGraph({\n rankdir: props.direction === \"vertical\" ? \"TB\" : \"LR\",\n ranker: \"network-simplex\",\n acyclicer: \"greedy\",\n align: \"UL\",\n marginx: 36,\n marginy: 36,\n ranksep: rankGap,\n nodesep: nodeGap,\n edgesep: edgeGap,\n });\n\n for (const node of orderedNodes) {\n const size = nodeSizes.value[node.key] ?? { width: 240, height: 120 };\n\n graph.setNode(node.key, {\n width: size.width,\n height: size.height,\n });\n }\n\n for (const node of orderedNodes) {\n const targets = outgoingNodeKeys.value[node.key] ?? [];\n const preferredTarget = resolveNextNode(node.key, targets);\n\n for (const target of targets) {\n if (!orderedNodeByKey.value[target]) continue;\n\n graph.setEdge(node.key, target, {\n minlen: 1,\n weight: target === preferredTarget ? 3 : 1,\n });\n }\n }\n\n try {\n dagre.layout(graph);\n } catch {\n return fallback;\n }\n\n const positions: Record<string, { x: number; y: number }> = {};\n\n for (const node of orderedNodes) {\n const layoutNode = graph.node(node.key);\n if (!layoutNode || typeof layoutNode.x !== \"number\" || typeof layoutNode.y !== \"number\") {\n continue;\n }\n\n const size = nodeSizes.value[node.key] ?? { width: 240, height: 120 };\n\n positions[node.key] = {\n x: Math.round(layoutNode.x - size.width / 2),\n y: Math.round(layoutNode.y - size.height / 2),\n };\n }\n\n if (Object.keys(positions).length === 0) {\n return fallback;\n }\n\n return normalizePositions(positions);\n});\n\nconst nodes = computed<FlowNode[]>(() => {\n const fallbackPositions = createFallbackLayoutPositions(\n orderedNodeElements.value,\n resolvedLayoutRankSep.value,\n );\n\n return orderedNodeElements.value.map(({ key, nodeType, element, index }) => ({\n id: key,\n type: nodeType,\n targetPosition: Position.Left,\n sourcePosition: Position.Right,\n position:\n layoutPositions.value[key] ??\n fallbackPositions[key] ??\n (props.direction === \"vertical\"\n ? { x: 0, y: index * DEFAULT_FALLBACK_GAP }\n : { x: index * DEFAULT_FALLBACK_GAP, y: 0 }),\n data: {\n key,\n type: nodeType,\n elementType: element.type,\n props: element.props,\n active: isActive(key),\n sourceAnchor: resolveNodeSourceAnchor(element.props),\n index,\n },\n }));\n});\n\nconst edges = computed<FlowEdge[]>(() => {\n const result: FlowEdge[] = [];\n\n for (const node of orderedNodeElements.value) {\n const targets = outgoingNodeKeys.value[node.key] ?? [];\n\n for (const target of targets) {\n if (!orderedNodeByKey.value[target]) continue;\n\n const isActiveEdge =\n !isArchitectureMode.value &&\n activeFrame.value?.nodeKey === node.key &&\n nextPlannedNodeKey.value === target;\n const transition = transitionMetaBySource.value[node.key]?.[target];\n const edgeClasses = [\n isActiveEdge ? \"active-edge\" : null,\n transition?.kind ? `edge-kind-${transition.kind}` : null,\n ].filter((value): value is string => Boolean(value));\n\n const edgeLabel = resolveTransitionEdgeLabel(transition);\n const hasLabel = Boolean(edgeLabel);\n\n result.push({\n id: `e-${node.key}-${target}`,\n source: node.key,\n target,\n type: isArchitectureMode.value ? \"architecture\" : \"smoothstep\",\n animated: !isArchitectureMode.value,\n class: edgeClasses.length > 0 ? edgeClasses.join(\" \") : undefined,\n label: edgeLabel,\n labelShowBg: hasLabel && !isArchitectureMode.value,\n labelBgPadding: hasLabel && !isArchitectureMode.value ? [6, 3] : undefined,\n labelBgBorderRadius: hasLabel && !isArchitectureMode.value ? 6 : undefined,\n labelBgStyle:\n hasLabel && !isArchitectureMode.value\n ? { fill: \"var(--color-card)\", fillOpacity: 0.985, stroke: \"var(--color-border)\" }\n : undefined,\n labelStyle:\n hasLabel && !isArchitectureMode.value\n ? {\n fill: \"var(--color-foreground)\",\n fontSize: \"10px\",\n fontWeight: 600,\n }\n : undefined,\n });\n }\n }\n\n return result;\n});\n\nconst diagramBounds = computed(() => {\n if (nodes.value.length === 0) {\n return null;\n }\n\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n\n for (const node of nodes.value) {\n const size = nodeSizes.value[node.id] ?? { width: 240, height: 120 };\n minX = Math.min(minX, node.position.x);\n minY = Math.min(minY, node.position.y);\n maxX = Math.max(maxX, node.position.x + size.width);\n maxY = Math.max(maxY, node.position.y + size.height);\n }\n\n for (const zone of architectureZoneOverlays.value) {\n minX = Math.min(minX, zone.x);\n minY = Math.min(minY, zone.y);\n maxX = Math.max(maxX, zone.x + zone.width);\n maxY = Math.max(maxY, zone.y + zone.height);\n }\n\n if (\n !Number.isFinite(minX) ||\n !Number.isFinite(minY) ||\n !Number.isFinite(maxX) ||\n !Number.isFinite(maxY)\n ) {\n return null;\n }\n\n return {\n x: Math.floor(minX),\n y: Math.floor(minY),\n width: Math.max(1, Math.ceil(maxX - minX)),\n height: Math.max(1, Math.ceil(maxY - minY)),\n };\n});\n\nfunction createExportFileBaseName() {\n const rawName = activeFlow.value?.id ?? overlayTitle.value ?? props.title ?? \"flow-diagram\";\n\n const slug = rawName\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n return slug || \"flow-diagram\";\n}\n\nasync function exportDiagram(format: DiagramExportFormat) {\n if (exportInFlight.value) return;\n if (!canExportDiagram.value) return;\n\n const flowElement = sceneRef.value;\n const bounds = diagramBounds.value;\n\n if (!flowElement || !bounds) {\n exportError.value = \"Diagram is still initializing. Try again in a moment.\";\n return;\n }\n\n exportError.value = null;\n exportMenuOpen.value = false;\n exportInFlight.value = format;\n\n try {\n await exportFlowDiagram({\n flowElement,\n theme: uiTheme.value,\n bounds,\n fileNameBase: createExportFileBaseName(),\n format,\n });\n } catch (error) {\n exportError.value =\n error instanceof Error ? error.message : `Failed to export ${format.toUpperCase()} diagram.`;\n } finally {\n exportInFlight.value = null;\n }\n}\n\nfunction isActive(nodeKey: string) {\n if (isArchitectureMode.value) {\n return true;\n }\n\n return activeFrame.value?.nodeKey === nodeKey;\n}\n\nfunction codeStepIndex(nodeKey: string) {\n if (activeFrame.value?.nodeKey !== nodeKey) {\n return 0;\n }\n\n return activeFrame.value.localStep;\n}\n\nconst activeNode = computed(() => {\n const key = activeFrame.value?.nodeKey;\n if (!key) return undefined;\n return orderedNodeByKey.value[key];\n});\n\nconst activeLocalStep = computed(() => activeFrame.value?.localStep ?? 0);\n\nconst activeLabel = computed(() => {\n const node = activeNode.value;\n if (!node) return \"\";\n\n const base = toOptionalString(node.element.props.label) ?? \"\";\n\n if (node.element.type !== \"CodeNode\") {\n return base;\n }\n\n const steps = toMagicMoveSteps(node.element.props.magicMoveSteps);\n if (steps.length === 0) return base;\n\n const title = steps[Math.min(activeLocalStep.value, steps.length - 1)]?.title;\n return title ? `${base} - ${title}` : base;\n});\n\nconst activeDescription = computed(() => {\n const node = activeNode.value;\n if (!node) return \"\";\n\n if (node.element.type === \"CodeNode\") {\n const steps = toMagicMoveSteps(node.element.props.magicMoveSteps);\n const defaultStory =\n toOptionalString(node.element.props.story) ?? toOptionalString(node.element.props.comment);\n\n if (steps.length > 0) {\n const beat = steps[Math.min(activeLocalStep.value, steps.length - 1)];\n\n return beat?.story ?? beat?.comment ?? defaultStory ?? \"\";\n }\n\n return defaultStory ?? \"\";\n }\n\n return getNodeSummary(node);\n});\n\nconst activeSourceAnchor = computed(() => {\n const node = activeNode.value;\n if (!node) return undefined;\n\n return resolveNodeSourceAnchor(node.element.props);\n});\n\nconst architectureSelectedNodeKey = ref<string | null>(null);\n\nconst architectureSelectedNode = computed(() => {\n if (!isArchitectureMode.value) {\n return undefined;\n }\n\n const selected = architectureSelectedNodeKey.value;\n if (selected && orderedNodeByKey.value[selected]) {\n return orderedNodeByKey.value[selected];\n }\n\n return orderedNodeElements.value[0];\n});\n\nwatch(\n [isArchitectureMode, orderedNodeElements],\n ([architectureMode, ordered]) => {\n if (!architectureMode) {\n architectureSelectedNodeKey.value = null;\n return;\n }\n\n const selected = architectureSelectedNodeKey.value;\n if (selected && ordered.some((node) => node.key === selected)) {\n return;\n }\n\n architectureSelectedNodeKey.value = ordered[0]?.key ?? null;\n },\n { immediate: true },\n);\n\nconst architectureInspector = computed<ArchitectureInspectorView | null>(() => {\n const node = architectureSelectedNode.value;\n if (!node) {\n return null;\n }\n\n const label = toTrimmedNonEmptyString(node.element.props.label) ?? node.key;\n const sourceAnchor = resolveNodeSourceAnchor(node.element.props);\n\n if (node.element.type !== \"ArchitectureNode\") {\n return {\n type: \"Other\",\n label,\n summary: getNodeSummary(node),\n sourceAnchor,\n elementType: node.element.type,\n };\n }\n\n const zoneId = toArchitectureZoneId(node.element.props.zone);\n const zoneLabel = zoneId\n ? (architectureZoneLabelById.value[zoneId] ?? humanizeZoneId(zoneId))\n : undefined;\n const interfaces = toArchitectureInterfaces(node.element.props.interfaces);\n const dataAssets = toArchitectureDataAssets(node.element.props.data);\n const security = toArchitectureSecurity(node.element.props.security);\n const operations = toArchitectureOperations(node.element.props.operations);\n const links = toArchitectureLinks(node.element.props.links);\n const outgoing: ArchitectureOutgoingEdge[] = [];\n\n for (const targetKey of outgoingNodeKeys.value[node.key] ?? []) {\n const targetNode = orderedNodeByKey.value[targetKey];\n if (!targetNode) {\n continue;\n }\n\n const transition = transitionMetaBySource.value[node.key]?.[targetKey];\n\n outgoing.push({\n target: toTrimmedNonEmptyString(targetNode.element.props.label) ?? targetKey,\n label: transition?.label,\n protocol: transition?.protocol,\n transport: transition?.transport,\n auth: transition?.auth,\n criticality: transition?.criticality,\n });\n }\n\n return {\n type: \"ArchitectureNode\",\n label,\n kind: toArchitectureKind(node.element.props.kind),\n status: toArchitectureStatus(node.element.props.status),\n tier: toArchitectureTier(node.element.props.tier),\n technology: toTrimmedNonEmptyString(node.element.props.technology),\n runtime: toTrimmedNonEmptyString(node.element.props.runtime),\n owner: toTrimmedNonEmptyString(node.element.props.owner),\n zoneLabel,\n summary: toTrimmedNonEmptyString(node.element.props.description) ?? \"\",\n tags: toStringArray(node.element.props.tags),\n responsibilities: toStringArray(node.element.props.responsibilities),\n capabilities: toStringArray(node.element.props.capabilities),\n interfaces,\n dataAssets,\n security,\n operations,\n links,\n outgoing,\n sourceAnchor,\n };\n});\n\nconst architectureInspectorNode = computed<ArchitectureInspectorArchitectureView | null>(() => {\n const inspector = architectureInspector.value;\n if (!inspector || inspector.type !== \"ArchitectureNode\") {\n return null;\n }\n\n return inspector;\n});\n\nconst architectureInspectorNodeSafe = computed(() => {\n return architectureInspectorNode.value ?? EMPTY_ARCHITECTURE_INSPECTOR_NODE;\n});\n\nconst architectureInspectorPanelStyle = computed(() => {\n return {\n transform: architectureInspectorOpen.value ? \"translateX(0)\" : \"translateX(100%)\",\n };\n});\n\nconst branchChoices = computed<BranchChoice[]>(() => {\n if (isArchitectureMode.value) {\n return [];\n }\n\n const node = activeNode.value;\n const frame = activeFrame.value;\n if (!node || !frame) return [];\n\n if (frame.localStep < frame.totalLocalSteps - 1) {\n return [];\n }\n\n const options = outgoingNodeKeys.value[node.key] ?? [];\n if (options.length <= 1) return [];\n\n const result: BranchChoice[] = [];\n\n for (const id of options) {\n const target = orderedNodeByKey.value[id];\n if (!target) continue;\n\n const transition = transitionMetaBySource.value[node.key]?.[id];\n\n const targetLabel = toOptionalString(target.element.props.label) ?? id;\n const targetDescription = getNodeSummary(target);\n\n result.push({\n id,\n label: transition?.label ?? targetLabel,\n description: transition?.description ?? targetDescription,\n kind: transition?.kind,\n });\n }\n\n return result;\n});\n\nconst selectedBranchChoiceId = computed(() => {\n const node = activeNode.value;\n if (!node || branchChoices.value.length === 0) return undefined;\n\n const selected = selectedBranchByNode.value[node.key];\n if (selected) return selected;\n\n return nextPlannedNodeKey.value;\n});\n\nfunction chooseChoice(choiceId: string) {\n const node = activeNode.value;\n if (!node) return;\n\n pauseNarrativePlayback();\n\n const options = outgoingNodeKeys.value[node.key] ?? [];\n if (!options.includes(choiceId)) return;\n\n selectedBranchByNode.value = {\n ...selectedBranchByNode.value,\n [node.key]: choiceId,\n };\n\n const prefix = pathFrames.value.slice(0, currentStep.value + 1);\n const suffix = buildGuidedPath(choiceId);\n\n pathFrames.value = [...prefix, ...suffix];\n\n if (pathFrames.value.length > currentStep.value + 1) {\n currentStep.value += 1;\n }\n}\n\nconst containerMinHeight = computed(() => {\n const provided = Number(props.minHeight);\n if (Number.isFinite(provided) && provided >= 320) {\n return Math.floor(provided);\n }\n\n if (isArchitectureMode.value) {\n return 620;\n }\n\n const node = activeNode.value ?? orderedNodeElements.value[0];\n if (!node || node.element.type !== \"CodeNode\") {\n return 520;\n }\n\n const maxLineLength = getCodeNodeMaxLineLength(node.element);\n const nodeWidth = estimateCodeNodeWidth(maxLineLength);\n const codeCharsPerLine = estimateCodeNodeCharsPerLine(nodeWidth);\n const autoWrapEnabled = maxLineLength > CODE_NODE_MAX_INLINE_CHARS;\n const wrapEnabled = toBoolean(node.element.props.wrapLongLines) || autoWrapEnabled;\n\n const codeLines = wrapEnabled\n ? getCodeNodeWrappedLines(node.element, codeCharsPerLine)\n : getCodeNodeMaxLines(node.element);\n const storyLines = getCodeNodeStoryLines(node.element);\n const storyHasMeta = hasCodeNodeStoryMeta(node.element);\n\n const codeViewportHeight = wrapEnabled\n ? Math.min(400, Math.max(190, 72 + codeLines * 16))\n : Math.min(340, Math.max(160, 84 + codeLines * 17));\n\n const storyViewportHeight =\n storyLines > 0 ? Math.min(220, Math.max(88, (storyHasMeta ? 56 : 34) + storyLines * 18)) : 0;\n\n return Math.min(880, Math.max(560, codeViewportHeight + storyViewportHeight + 300));\n});\n\nconst instance = getCurrentInstance();\nconst flowId = `flaier-${instance?.uid ?? 0}`;\nconst { fitView, onNodeClick, onViewportChange, setCenter, viewport } = useVueFlow(flowId);\nconst nodesInitialized = useNodesInitialized();\nconst paneReady = ref(false);\nconst overviewMode = ref(false);\nlet resizeObserver: ResizeObserver | null = null;\n\nconst architectureZoneLayerStyle = computed(() => {\n const x = Number.isFinite(viewport.value.x) ? viewport.value.x : 0;\n const y = Number.isFinite(viewport.value.y) ? viewport.value.y : 0;\n const zoom = Number.isFinite(viewport.value.zoom) ? viewport.value.zoom : 1;\n\n return {\n transform: `translate(${x}px, ${y}px) scale(${zoom})`,\n transformOrigin: \"0 0\",\n };\n});\n\nfunction handleDocumentPointerDown(event: PointerEvent) {\n const target = event.target as Node | null;\n if (!target) return;\n\n if (headerDropdownOpen.value && !headerDropdownRef.value?.contains(target)) {\n closeHeaderDropdown();\n }\n\n if (exportMenuOpen.value && !exportMenuRef.value?.contains(target)) {\n closeExportMenu();\n }\n}\n\nfunction isEditableTarget(target: EventTarget | null) {\n if (!(target instanceof HTMLElement)) {\n return false;\n }\n\n if (target.isContentEditable) {\n return true;\n }\n\n const tagName = target.tagName;\n if (tagName === \"INPUT\" || tagName === \"TEXTAREA\" || tagName === \"SELECT\") {\n return true;\n }\n\n return Boolean(target.closest('[contenteditable=\"true\"]'));\n}\n\nfunction handleDocumentKeydown(event: KeyboardEvent) {\n if (event.key === \"Escape\") {\n closeHeaderDropdown();\n closeExportMenu();\n\n if (isArchitectureMode.value) {\n architectureInspectorOpen.value = false;\n }\n\n return;\n }\n\n if (event.defaultPrevented) return;\n if (event.metaKey || event.ctrlKey || event.altKey) return;\n if (isEditableTarget(event.target)) return;\n if (isArchitectureMode.value) return;\n\n if (event.key === \"ArrowRight\" || event.key === \"ArrowDown\") {\n event.preventDefault();\n next();\n return;\n }\n\n if (event.key === \"ArrowLeft\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n prev();\n return;\n }\n\n if (/^[1-9]$/.test(event.key)) {\n const index = Number(event.key) - 1;\n const choice = branchChoices.value[index];\n if (!choice) return;\n\n event.preventDefault();\n chooseChoice(choice.id);\n }\n}\n\nfunction syncOverviewModeFromZoom(zoom: number) {\n if (overviewMode.value) {\n if (zoom >= OVERVIEW_EXIT_ZOOM) {\n overviewMode.value = false;\n }\n\n return;\n }\n\n if (zoom <= OVERVIEW_ENTER_ZOOM) {\n overviewMode.value = true;\n }\n}\n\nwatch(\n () => viewport.value.zoom,\n (zoom) => {\n if (!Number.isFinite(zoom)) return;\n\n syncOverviewModeFromZoom(zoom);\n },\n { immediate: true },\n);\n\nonViewportChange((transform) => {\n if (!Number.isFinite(transform.zoom)) return;\n\n syncOverviewModeFromZoom(transform.zoom);\n});\n\nonNodeClick(({ node }) => {\n if (isArchitectureMode.value) {\n architectureSelectedNodeKey.value = node.id;\n architectureInspectorOpen.value = true;\n return;\n }\n\n jumpToNode(node.id);\n});\n\nfunction updateContainerReady() {\n const element = containerRef.value;\n containerWidth.value = element?.clientWidth ?? 0;\n containerHeight.value = element?.clientHeight ?? 0;\n containerReady.value = containerWidth.value > 0 && containerHeight.value > 0;\n}\n\nfunction waitForAnimationFrame() {\n return new Promise<void>((resolve) => {\n if (typeof window === \"undefined\" || typeof window.requestAnimationFrame !== \"function\") {\n setTimeout(resolve, 16);\n return;\n }\n\n window.requestAnimationFrame(() => {\n resolve();\n });\n });\n}\n\nasync function waitForViewportLayoutStability() {\n await nextTick();\n await waitForAnimationFrame();\n await waitForAnimationFrame();\n updateContainerReady();\n await nextTick();\n}\n\nfunction getNarrativeFocusZoom(size: NodeSize) {\n const width = Math.max(1, containerWidth.value);\n const height = Math.max(1, containerHeight.value);\n const focusWidth = Math.max(size.width * 1.35, size.width + NARRATIVE_FOCUS_HORIZONTAL_CONTEXT);\n const focusHeight = Math.max(size.height * 1.45, size.height + NARRATIVE_FOCUS_VERTICAL_CONTEXT);\n const zoom = Math.min(width / focusWidth, height / focusHeight);\n\n if (!Number.isFinite(zoom)) {\n return 1;\n }\n\n return Math.max(NARRATIVE_FOCUS_MIN_ZOOM, Math.min(NARRATIVE_FOCUS_MAX_ZOOM, zoom));\n}\n\nconst sceneStyle = computed<Record<string, string>>(() => ({\n height: `${Math.max(containerHeight.value, containerMinHeight.value)}px`,\n}));\n\nonMounted(() => {\n if (typeof document !== \"undefined\") {\n document.addEventListener(\"pointerdown\", handleDocumentPointerDown);\n document.addEventListener(\"keydown\", handleDocumentKeydown);\n }\n\n nextTick(() => {\n updateContainerReady();\n\n if (typeof ResizeObserver === \"undefined\") return;\n\n resizeObserver = new ResizeObserver(() => {\n updateContainerReady();\n });\n\n if (containerRef.value) {\n resizeObserver.observe(containerRef.value);\n }\n });\n});\n\nfunction onInit() {\n paneReady.value = true;\n}\n\nconst viewportReady = computed(\n () => paneReady.value && nodesInitialized.value && containerReady.value && nodes.value.length > 0,\n);\n\nconst canExportDiagram = computed(() => {\n return Boolean(viewportReady.value && diagramBounds.value);\n});\n\nasync function refitViewportAfterContainerChange() {\n if (!nodes.value.length) return;\n\n await waitForViewportLayoutStability();\n\n if (!viewportReady.value || nodes.value.length === 0) {\n return;\n }\n\n if (isArchitectureMode.value || overviewMode.value) {\n await Promise.resolve(\n fitView({\n duration: isArchitectureMode.value ? 260 : 280,\n padding: isArchitectureMode.value ? 0.18 : 0.3,\n maxZoom: isArchitectureMode.value ? 1.15 : 0.95,\n }),\n );\n return;\n }\n\n const target = narrativeFocusTarget.value;\n if (!target) {\n await Promise.resolve(\n fitView({\n duration: 280,\n padding: 0.3,\n maxZoom: 0.95,\n }),\n );\n return;\n }\n\n await nextTick();\n\n await Promise.resolve(\n setCenter(target.x, target.y, {\n duration: 280,\n zoom: target.zoom,\n }),\n );\n}\n\nwatch(canExportDiagram, (canExport) => {\n if (!canExport) {\n closeExportMenu();\n }\n});\n\nconst narrativeFocusTarget = computed(() => {\n if (isArchitectureMode.value || overviewMode.value || !viewportReady.value) {\n return null;\n }\n\n const nodeKey = activeFrame.value?.nodeKey;\n if (!nodeKey) {\n return null;\n }\n\n const node = nodes.value.find((candidate) => candidate.id === nodeKey);\n if (!node) {\n return null;\n }\n\n const size = nodeSizes.value[node.id] ?? { width: 240, height: 120 };\n\n return {\n signature: [\n currentStep.value,\n node.id,\n Math.round(node.position.x),\n Math.round(node.position.y),\n Math.round(size.width),\n Math.round(size.height),\n Math.round(containerWidth.value),\n Math.round(containerHeight.value),\n ].join(\":\"),\n x: node.position.x + size.width / 2,\n y: node.position.y + size.height / 2,\n zoom: getNarrativeFocusZoom(size),\n };\n});\n\nconst narrativeFitSignature = ref(\"\");\nconst suppressNarrativeResizeFit = ref(false);\n\nwatch(\n [viewportReady, isArchitectureMode, nodes, containerWidth, containerHeight],\n ([ready, architectureMode, currentNodes, width, height]) => {\n if (!ready || architectureMode || currentNodes.length === 0) return;\n\n const signature = [\n `${Math.round(width)}x${Math.round(height)}`,\n ...currentNodes.map(\n (node) => `${node.id}:${Math.round(node.position.x)}:${Math.round(node.position.y)}`,\n ),\n ].join(\"|\");\n\n if (signature === narrativeFitSignature.value) {\n return;\n }\n\n if (suppressNarrativeResizeFit.value && narrativeFocusTarget.value) {\n narrativeFitSignature.value = signature;\n return;\n }\n\n narrativeFitSignature.value = signature;\n\n nextTick(() => {\n void fitView({\n duration: 280,\n padding: 0.3,\n maxZoom: 0.95,\n });\n });\n },\n { immediate: true },\n);\n\nwatch(\n () => narrativeFocusTarget.value?.signature ?? \"\",\n () => {\n const target = narrativeFocusTarget.value;\n if (!target) return;\n\n nextTick(() => {\n void setCenter(target.x, target.y, { duration: 280, zoom: target.zoom });\n });\n },\n { immediate: true },\n);\n\nconst architectureFitSignature = ref(\"\");\nconst lastViewportResetToken = ref(0);\n\nwatch(\n [viewportReady, isArchitectureMode, nodes, containerWidth, containerHeight],\n ([ready, architectureMode, currentNodes, width, height]) => {\n if (!ready || !architectureMode || currentNodes.length === 0) return;\n\n const signature = [\n `${Math.round(width)}x${Math.round(height)}`,\n ...currentNodes.map(\n (node) => `${node.id}:${Math.round(node.position.x)}:${Math.round(node.position.y)}`,\n ),\n ].join(\"|\");\n\n if (signature === architectureFitSignature.value) {\n return;\n }\n\n architectureFitSignature.value = signature;\n\n nextTick(() => {\n void fitView({\n duration: 260,\n padding: 0.18,\n maxZoom: 1.15,\n });\n });\n },\n { immediate: true },\n);\n\nwatch(\n [() => runtime.viewportResetToken.value, viewportReady],\n ([token, ready]) => {\n if (!ready || token <= lastViewportResetToken.value) {\n return;\n }\n\n lastViewportResetToken.value = token;\n narrativeFitSignature.value = \"\";\n architectureFitSignature.value = \"\";\n\n const shouldSuppressNarrativeFit = Boolean(narrativeFocusTarget.value);\n\n if (shouldSuppressNarrativeFit) {\n suppressNarrativeResizeFit.value = true;\n }\n\n void (async () => {\n try {\n await refitViewportAfterContainerChange();\n } finally {\n if (shouldSuppressNarrativeFit) {\n await waitForAnimationFrame();\n await waitForAnimationFrame();\n suppressNarrativeResizeFit.value = false;\n }\n }\n })();\n },\n { immediate: true },\n);\n\nwatch(isArchitectureMode, (architectureMode) => {\n if (architectureMode) {\n playing.value = false;\n narrativeFitSignature.value = \"\";\n architectureInspectorOpen.value = defaultArchitectureInspectorOpen.value;\n return;\n }\n\n narrativeFitSignature.value = \"\";\n architectureFitSignature.value = \"\";\n architectureInspectorOpen.value = defaultArchitectureInspectorOpen.value;\n});\n\nonUnmounted(() => {\n clearTimer();\n\n if (typeof document !== \"undefined\") {\n document.removeEventListener(\"pointerdown\", handleDocumentPointerDown);\n document.removeEventListener(\"keydown\", handleDocumentKeydown);\n }\n\n if (resizeObserver) {\n resizeObserver.disconnect();\n resizeObserver = null;\n }\n\n stopDocumentThemeSync();\n});\n</script>\n\n<template>\n <div\n ref=\"containerRef\"\n class=\"flaier relative h-full w-full font-sans antialiased bg-background transition-[min-height] duration-300 ease-out\"\n :style=\"{ minHeight: `${containerMinHeight}px` }\"\n :data-mode=\"isArchitectureMode ? 'architecture' : 'narrative'\"\n :data-focus-mode=\"overviewMode ? 'overview' : 'focus'\"\n :data-theme=\"uiTheme\"\n >\n <div ref=\"sceneRef\" class=\"relative w-full overflow-hidden\" :style=\"sceneStyle\">\n <div\n v-if=\"containerReady && isArchitectureMode && architectureZoneOverlays.length > 0\"\n class=\"pointer-events-none absolute inset-0 z-0\"\n >\n <div class=\"absolute inset-0\" data-zone-overlay=\"true\" :style=\"architectureZoneLayerStyle\">\n <div\n v-for=\"zone in architectureZoneOverlays\"\n :key=\"zone.id\"\n class=\"absolute rounded-2xl border border-dashed\"\n :style=\"architectureZoneCardStyle(zone)\"\n >\n <div\n class=\"absolute left-4 inline-flex items-center gap-2 rounded-full border px-2 py-1 text-[10px] font-semibold uppercase tracking-wider\"\n :style=\"architectureZoneLabelStyle(zone)\"\n >\n <span>{{ zone.label }}</span>\n <span class=\"opacity-80\"\n >{{ zone.nodeCount }} node{{ zone.nodeCount === 1 ? \"\" : \"s\" }}</span\n >\n </div>\n\n <p\n v-if=\"zone.description\"\n class=\"absolute left-4 right-4 text-[10px] leading-snug text-muted-foreground\"\n :style=\"architectureZoneDescriptionStyle(zone)\"\n >\n {{ zone.description }}\n </p>\n </div>\n </div>\n </div>\n\n <VueFlow\n v-if=\"containerReady\"\n :id=\"flowId\"\n :nodes=\"nodes\"\n :edges=\"edges\"\n :node-types=\"customNodeTypes\"\n :fit-view-on-init=\"false\"\n :elements-selectable=\"false\"\n :nodes-focusable=\"false\"\n :nodes-draggable=\"false\"\n :nodes-connectable=\"false\"\n :zoom-on-scroll=\"true\"\n :zoom-on-pinch=\"true\"\n :pan-on-drag=\"true\"\n :pan-on-scroll=\"true\"\n :min-zoom=\"0.15\"\n :max-zoom=\"2\"\n :prevent-scrolling=\"true\"\n class=\"relative z-[10] h-full w-full\"\n @init=\"onInit\"\n >\n <template #node-architecture=\"{ data }\">\n <ArchitectureNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :kind=\"toArchitectureKind(data.props.kind)\"\n :technology=\"toOptionalString(data.props.technology)\"\n :runtime=\"toOptionalString(data.props.runtime)\"\n :owner=\"toOptionalString(data.props.owner)\"\n :tier=\"toArchitectureTier(data.props.tier)\"\n :status=\"toArchitectureStatus(data.props.status)\"\n :tags=\"toStringArray(data.props.tags)\"\n :capabilities=\"toStringArray(data.props.capabilities)\"\n :description=\"toOptionalString(data.props.description)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #edge-architecture=\"edgeProps\">\n <ArchitectureSmoothEdge v-bind=\"edgeProps\" />\n </template>\n\n <template #node-trigger=\"{ data }\">\n <TriggerNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :description=\"toOptionalString(data.props.description)\"\n :color=\"toOptionalString(data.props.color)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-code=\"{ data }\">\n <CodeNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :file=\"toOptionalString(data.props.file)\"\n :language=\"toOptionalString(data.props.language)\"\n :code=\"toRequiredString(data.props.code)\"\n :comment=\"toOptionalString(data.props.comment)\"\n :story=\"toOptionalString(data.props.story)\"\n :wrap-long-lines=\"toBoolean(data.props.wrapLongLines)\"\n :magic-move-steps=\"toMagicMoveSteps(data.props.magicMoveSteps)\"\n :twoslash=\"toOptionalBoolean(data.props.twoslash)\"\n :twoslash-html=\"toTwoslashHtml(data.props.twoslashHtml)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :ui-theme=\"uiTheme\"\n :active=\"isActive(data.key)\"\n :step-index=\"codeStepIndex(data.key)\"\n />\n </template>\n\n <template #node-decision=\"{ data }\">\n <DecisionNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :condition=\"toOptionalString(data.props.condition)\"\n :description=\"toOptionalString(data.props.description)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-payload=\"{ data }\">\n <PayloadNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :payload=\"toOptionalString(data.props.payload)\"\n :before=\"toOptionalString(data.props.before)\"\n :after=\"toOptionalString(data.props.after)\"\n :format=\"toPayloadFormat(data.props.format)\"\n :description=\"toOptionalString(data.props.description)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-error=\"{ data }\">\n <ErrorNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :message=\"toRequiredString(data.props.message)\"\n :code=\"toOptionalString(data.props.code)\"\n :cause=\"toOptionalString(data.props.cause)\"\n :mitigation=\"toOptionalString(data.props.mitigation)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-description=\"{ data }\">\n <DescriptionNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :body=\"toRequiredString(data.props.body)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-link=\"{ data }\">\n <LinkNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :href=\"toRequiredString(data.props.href)\"\n :description=\"toOptionalString(data.props.description)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n </VueFlow>\n\n <div v-else class=\"h-full w-full\" />\n </div>\n\n <div\n v-if=\"showHeaderOverlay && (showFlowSelector || overlayTitle || overlayDescription)\"\n ref=\"headerDropdownRef\"\n class=\"absolute top-4 left-4 z-20 w-[min(90vw,430px)]\"\n >\n <div class=\"relative\">\n <button\n type=\"button\"\n class=\"group w-full rounded-lg border border-border/70 bg-card/85 px-3 py-2 text-left text-xs shadow-lg backdrop-blur-md transition-colors\"\n :class=\"showFlowSelector ? 'cursor-pointer hover:border-primary/45' : 'cursor-default'\"\n :disabled=\"!showFlowSelector\"\n :aria-expanded=\"showFlowSelector ? headerDropdownOpen : undefined\"\n aria-haspopup=\"listbox\"\n @click=\"toggleHeaderDropdown\"\n >\n <div class=\"flex items-start justify-between gap-3\">\n <div class=\"min-w-0\">\n <p class=\"text-[10px] font-medium uppercase tracking-wider text-muted-foreground\">\n {{ headerModeLabel }}\n </p>\n <p v-if=\"overlayTitle\" class=\"mt-1 truncate text-sm font-medium text-foreground\">\n {{ overlayTitle }}\n </p>\n <p\n v-if=\"overlayDescription\"\n class=\"mt-0.5 text-[11px] leading-relaxed text-muted-foreground break-words\"\n >\n {{ overlayDescription }}\n </p>\n </div>\n\n <svg\n v-if=\"showFlowSelector\"\n class=\"mt-0.5 h-4 w-4 shrink-0 transition-all\"\n :class=\"\n headerDropdownOpen\n ? 'rotate-180 text-foreground'\n : 'text-muted-foreground group-hover:text-foreground'\n \"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </div>\n </button>\n\n <div\n v-if=\"showFlowSelector && headerDropdownOpen\"\n class=\"absolute inset-x-0 top-[calc(100%+8px)] rounded-lg border border-border/70 bg-card/95 p-1 shadow-2xl backdrop-blur-md\"\n role=\"listbox\"\n >\n <button\n v-for=\"flow in availableFlows\"\n :key=\"flow.id\"\n type=\"button\"\n class=\"w-full rounded-md px-2.5 py-2 text-left transition-colors\"\n :class=\"\n flow.id === activeFlowId\n ? 'bg-primary/14 text-foreground'\n : 'text-foreground/90 hover:bg-muted/70'\n \"\n @click=\"handleFlowSelect(flow.id)\"\n >\n <div class=\"flex items-center justify-between gap-2\">\n <p class=\"truncate text-xs font-medium\">{{ flow.title }}</p>\n <span\n v-if=\"flow.id === activeFlowId\"\n class=\"rounded-full border border-primary/35 bg-primary/10 px-1.5 py-0.5 text-[10px] uppercase tracking-wide text-primary\"\n >\n Active\n </span>\n </div>\n <p\n v-if=\"flow.description\"\n class=\"mt-0.5 text-[11px] leading-relaxed text-muted-foreground break-words\"\n >\n {{ flow.description }}\n </p>\n </button>\n </div>\n </div>\n </div>\n\n <div\n v-if=\"showTopRightControls\"\n class=\"fn-architecture-controls absolute top-4 right-4 z-20 flex flex-col items-end gap-2\"\n >\n <div ref=\"exportMenuRef\" class=\"relative\">\n <button\n v-if=\"showExportControls\"\n type=\"button\"\n class=\"group inline-flex h-9 items-center gap-2 rounded-full border border-border/70 bg-card/85 px-3 text-[11px] text-muted-foreground shadow-lg backdrop-blur-md transition-colors hover:text-foreground disabled:cursor-default disabled:opacity-55\"\n :aria-label=\"exportButtonLabel\"\n :title=\"exportButtonLabel\"\n :disabled=\"!canExportDiagram || Boolean(exportInFlight)\"\n @click=\"toggleExportMenu\"\n >\n <svg\n class=\"h-3.5 w-3.5\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 3v12\" />\n <path d=\"m7 10 5 5 5-5\" />\n <path d=\"M4 20h16\" />\n </svg>\n <span>Export</span>\n </button>\n\n <div\n v-if=\"showExportControls && exportMenuOpen\"\n class=\"absolute right-0 top-[calc(100%+8px)] w-44 rounded-lg border border-border/70 bg-card/95 p-1 shadow-2xl backdrop-blur-md\"\n >\n <button\n type=\"button\"\n class=\"w-full rounded-md px-2.5 py-2 text-left text-xs text-foreground transition-colors hover:bg-muted/70\"\n :disabled=\"Boolean(exportInFlight)\"\n @click=\"exportDiagram('png')\"\n >\n Export PNG\n </button>\n <button\n type=\"button\"\n class=\"w-full rounded-md px-2.5 py-2 text-left text-xs text-foreground transition-colors hover:bg-muted/70\"\n :disabled=\"Boolean(exportInFlight)\"\n @click=\"exportDiagram('pdf')\"\n >\n Export PDF\n </button>\n </div>\n </div>\n\n <button\n v-if=\"showThemeToggle\"\n type=\"button\"\n class=\"fn-theme-toggle group inline-flex h-9 w-9 items-center justify-center rounded-full border border-border/70 bg-card/85 text-muted-foreground shadow-lg backdrop-blur-md transition-colors hover:text-foreground\"\n :aria-label=\"themeToggleLabel\"\n :title=\"themeToggleLabel\"\n @click=\"toggleTheme\"\n >\n <svg\n v-if=\"isLightTheme\"\n class=\"h-4 w-4\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 3a1 1 0 0 1 1 1v1a1 1 0 1 1-2 0V4a1 1 0 0 1 1-1Z\" />\n <path\n d=\"M18.36 5.64a1 1 0 0 1 1.41 0l.71.71a1 1 0 0 1-1.41 1.41l-.71-.7a1 1 0 0 1 0-1.42Z\"\n />\n <path d=\"M20 11a1 1 0 1 1 0 2h-1a1 1 0 1 1 0-2h1Z\" />\n <path\n d=\"M18.36 18.36a1 1 0 0 1 0-1.41l.71-.71a1 1 0 0 1 1.41 1.41l-.7.71a1 1 0 0 1-1.42 0Z\"\n />\n <path d=\"M12 19a1 1 0 0 1 1 1v1a1 1 0 1 1-2 0v-1a1 1 0 0 1 1-1Z\" />\n <path\n d=\"M5.64 18.36a1 1 0 0 1-1.41 0l-.71-.71a1 1 0 1 1 1.41-1.41l.71.7a1 1 0 0 1 0 1.42Z\"\n />\n <path d=\"M5 11a1 1 0 1 1 0 2H4a1 1 0 1 1 0-2h1Z\" />\n <path\n d=\"M5.64 5.64a1 1 0 0 1 0 1.41l-.71.71a1 1 0 1 1-1.41-1.41l.7-.71a1 1 0 0 1 1.42 0Z\"\n />\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n </svg>\n\n <svg\n v-else\n class=\"h-4 w-4\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 12.79A9 9 0 1 1 11.21 3a7 7 0 1 0 9.79 9.79Z\" />\n </svg>\n </button>\n\n <p\n v-if=\"showExportControls && exportError\"\n class=\"max-w-[260px] rounded-md border border-red-500/45 bg-red-500/12 px-2 py-1 text-[10px] leading-relaxed text-red-200\"\n >\n {{ exportError }}\n </p>\n </div>\n\n <div\n v-if=\"!isArchitectureMode\"\n class=\"pointer-events-none absolute inset-x-0 bottom-2 z-30 flex justify-center px-3\"\n style=\"padding-bottom: max(env(safe-area-inset-bottom), 0px)\"\n >\n <div class=\"pointer-events-auto w-full max-w-[980px]\">\n <TimelineControls\n :current-step=\"currentStep\"\n :total-steps=\"totalSteps\"\n :playing=\"playing\"\n :label=\"activeLabel\"\n :description=\"activeDescription\"\n :source-anchor-label=\"activeSourceAnchor?.label\"\n :source-anchor-href=\"activeSourceAnchor?.href\"\n :choices=\"branchChoices\"\n :selected-choice-id=\"selectedBranchChoiceId\"\n @next=\"next\"\n @prev=\"prev\"\n @go-to=\"goTo\"\n @toggle-play=\"togglePlay\"\n @choose-choice=\"chooseChoice\"\n />\n </div>\n </div>\n\n <div\n v-if=\"isArchitectureMode && showArchitectureInspectorPanel && architectureInspector\"\n class=\"fn-architecture-inspector pointer-events-none absolute bottom-3 right-0 top-16 z-30 w-[min(92vw,430px)]\"\n style=\"\n padding-right: max(env(safe-area-inset-right), 0px);\n padding-bottom: max(env(safe-area-inset-bottom), 0px);\n \"\n >\n <div class=\"absolute inset-0 overflow-visible\">\n <aside\n class=\"pointer-events-auto absolute inset-y-0 right-0 w-full transition-all duration-300 ease-out\"\n :style=\"architectureInspectorPanelStyle\"\n >\n <button\n type=\"button\"\n class=\"fn-architecture-inspector__toggle absolute right-full top-1/2 z-30 inline-flex h-20 w-8 -translate-y-1/2 translate-x-px flex-col items-center justify-center gap-1 rounded-l-lg rounded-r-none border border-border/70 border-r-0 bg-gradient-to-b from-card/95 via-card/88 to-card/78 px-0.5 text-[8px] font-semibold uppercase tracking-[0.12em] text-muted-foreground shadow-2xl backdrop-blur-xl transition-all duration-200 hover:text-foreground\"\n :aria-label=\"architectureInspectorToggleLabel\"\n :title=\"architectureInspectorToggleLabel\"\n @click=\"toggleArchitectureInspector\"\n >\n <svg\n class=\"h-2.5 w-2.5\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path v-if=\"architectureInspectorOpen\" d=\"m14.5 6-5.5 6 5.5 6\" />\n <path v-else d=\"m9.5 6 5.5 6-5.5 6\" />\n </svg>\n <span\n v-if=\"showArchitectureInspectorToggleText\"\n class=\"inline-block font-semibold leading-none\"\n style=\"writing-mode: vertical-rl; transform: rotate(180deg); letter-spacing: 0.1em\"\n >\n Details\n </span>\n </button>\n\n <div\n class=\"fn-architecture-inspector__panel flex h-full flex-col overflow-hidden rounded-2xl border border-border/60 bg-gradient-to-b from-card/95 via-card/90 to-card/82 shadow-2xl backdrop-blur-xl\"\n >\n <div class=\"border-b border-border/60 px-3 py-2.5\">\n <div class=\"flex flex-wrap items-start justify-between gap-2\">\n <div class=\"min-w-0\">\n <p class=\"text-[11px] font-semibold text-foreground leading-snug break-words\">\n {{ architectureInspector.label }}\n </p>\n\n <div v-if=\"architectureInspectorNode\" class=\"mt-1 flex flex-wrap gap-1\">\n <span\n v-if=\"architectureInspectorNodeSafe.kind\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[9px] uppercase tracking-wider text-muted-foreground\"\n >\n {{ architectureInspectorNodeSafe.kind }}\n </span>\n <span\n v-if=\"architectureInspectorNodeSafe.status\"\n class=\"inline-flex items-center rounded border border-primary/35 bg-primary/10 px-1.5 py-0.5 text-[9px] uppercase tracking-wider text-primary\"\n >\n {{ architectureInspectorNodeSafe.status }}\n </span>\n <span\n v-if=\"architectureInspectorNodeSafe.tier\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[9px] uppercase tracking-wider text-muted-foreground\"\n >\n {{ architectureInspectorNodeSafe.tier }}\n </span>\n <span\n v-if=\"architectureInspectorNodeSafe.zoneLabel\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[9px] uppercase tracking-wider text-muted-foreground\"\n >\n Zone: {{ architectureInspectorNodeSafe.zoneLabel }}\n </span>\n </div>\n </div>\n\n <a\n v-if=\"\n architectureInspector.sourceAnchor?.label &&\n architectureInspector.sourceAnchor?.href\n \"\n :href=\"architectureInspector.sourceAnchor.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"inline-flex max-w-full items-center gap-1 rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground transition-colors hover:border-primary/45 hover:text-foreground\"\n >\n <span class=\"truncate\">{{ architectureInspector.sourceAnchor.label }}</span>\n </a>\n\n <p\n v-else-if=\"architectureInspector.sourceAnchor?.label\"\n class=\"inline-flex max-w-full items-center rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground\"\n >\n <span class=\"truncate\">{{ architectureInspector.sourceAnchor.label }}</span>\n </p>\n </div>\n\n <p\n v-if=\"architectureInspector.summary\"\n class=\"mt-1.5 text-[11px] text-muted-foreground leading-relaxed whitespace-pre-wrap break-words\"\n >\n {{ architectureInspector.summary }}\n </p>\n </div>\n\n <div class=\"min-h-0 flex-1 space-y-2 overflow-y-auto px-3 py-2.5\">\n <template v-if=\"architectureInspectorNode\">\n <div class=\"rounded-lg border border-border/60 bg-muted/20 px-2 py-1.5\">\n <p\n class=\"text-[9px] font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n Core\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.technology\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Technology: {{ architectureInspectorNodeSafe.technology }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.runtime\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Runtime: {{ architectureInspectorNodeSafe.runtime }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.owner\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Owner: {{ architectureInspectorNodeSafe.owner }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.operations?.slo\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n SLO: {{ architectureInspectorNodeSafe.operations.slo }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.operations?.alert\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Alert: {{ architectureInspectorNodeSafe.operations.alert }}\n </p>\n </div>\n\n <div\n v-if=\"\n architectureInspectorNodeSafe.security ||\n architectureInspectorNodeSafe.dataAssets.length > 0\n \"\n class=\"rounded-lg border border-border/60 bg-muted/20 px-2 py-1.5\"\n >\n <p\n class=\"text-[9px] font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n Data & Security\n </p>\n <template v-if=\"architectureInspectorNodeSafe.security\">\n <p\n v-if=\"architectureInspectorNodeSafe.security.auth\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Auth: {{ architectureInspectorNodeSafe.security.auth }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.security.encryption\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Encryption: {{ architectureInspectorNodeSafe.security.encryption }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.security.pii !== undefined\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n PII: {{ architectureInspectorNodeSafe.security.pii ? \"Yes\" : \"No\" }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.security.threatModel\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Threat Model: {{ architectureInspectorNodeSafe.security.threatModel }}\n </p>\n </template>\n\n <div\n v-if=\"architectureInspectorNodeSafe.dataAssets.length > 0\"\n class=\"mt-1.5 space-y-1\"\n >\n <p\n v-for=\"asset in architectureInspectorNodeSafe.dataAssets\"\n :key=\"`${asset.name}-${asset.kind ?? ''}`\"\n class=\"text-[10px] text-foreground\"\n >\n {{ asset.name }}<span v-if=\"asset.kind\"> ({{ asset.kind }})</span\n ><span v-if=\"asset.classification\"> - {{ asset.classification }}</span\n ><span v-if=\"asset.retention\"> - {{ asset.retention }}</span>\n </p>\n </div>\n </div>\n\n <div\n v-if=\"\n architectureInspectorNodeSafe.responsibilities.length > 0 ||\n architectureInspectorNodeSafe.capabilities.length > 0 ||\n architectureInspectorNodeSafe.tags.length > 0\n \"\n class=\"rounded-lg border border-border/60 bg-muted/20 px-2 py-1.5\"\n >\n <p\n class=\"text-[9px] font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n Capabilities\n </p>\n\n <div\n v-if=\"architectureInspectorNodeSafe.capabilities.length > 0\"\n class=\"mt-1 flex flex-wrap gap-1\"\n >\n <span\n v-for=\"capability in architectureInspectorNodeSafe.capabilities\"\n :key=\"capability\"\n class=\"inline-flex items-center rounded border border-primary/35 bg-primary/10 px-1.5 py-0.5 text-[9px] text-primary\"\n >\n {{ capability }}\n </span>\n </div>\n\n <div\n v-if=\"architectureInspectorNodeSafe.tags.length > 0\"\n class=\"mt-1 flex flex-wrap gap-1\"\n >\n <span\n v-for=\"tag in architectureInspectorNodeSafe.tags\"\n :key=\"tag\"\n class=\"inline-flex items-center rounded border border-border/70 bg-card/35 px-1.5 py-0.5 text-[9px] text-muted-foreground\"\n >\n #{{ tag }}\n </span>\n </div>\n\n <ul\n v-if=\"architectureInspectorNodeSafe.responsibilities.length > 0\"\n class=\"mt-1 space-y-0.5 text-[10px] text-foreground\"\n >\n <li v-for=\"item in architectureInspectorNodeSafe.responsibilities\" :key=\"item\">\n - {{ item }}\n </li>\n </ul>\n </div>\n\n <div\n v-if=\"\n architectureInspectorNodeSafe.interfaces.length > 0 ||\n architectureInspectorNodeSafe.outgoing.length > 0 ||\n architectureInspectorNodeSafe.links.length > 0 ||\n architectureInspectorNodeSafe.operations?.runbook\n \"\n class=\"rounded-lg border border-border/60 bg-muted/20 px-2 py-1.5\"\n >\n <p\n class=\"text-[9px] font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n Interfaces & Links\n </p>\n\n <div\n v-if=\"architectureInspectorNodeSafe.interfaces.length > 0\"\n class=\"mt-1 space-y-1\"\n >\n <p\n v-for=\"iface in architectureInspectorNodeSafe.interfaces\"\n :key=\"`${iface.name}-${iface.protocol ?? ''}-${iface.direction ?? ''}`\"\n class=\"text-[10px] text-foreground\"\n >\n {{ iface.name }}<span v-if=\"iface.protocol\"> ({{ iface.protocol }})</span\n ><span v-if=\"iface.direction\"> - {{ iface.direction }}</span\n ><span v-if=\"iface.auth\"> - auth: {{ iface.auth }}</span\n ><span v-if=\"iface.contract\"> - {{ iface.contract }}</span>\n </p>\n </div>\n\n <p\n v-if=\"architectureInspectorNodeSafe.operations?.runbook\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Runbook: {{ architectureInspectorNodeSafe.operations.runbook }}\n </p>\n\n <div\n v-if=\"architectureInspectorNodeSafe.outgoing.length > 0\"\n class=\"mt-1 space-y-1\"\n >\n <p\n v-for=\"edge in architectureInspectorNodeSafe.outgoing\"\n :key=\"`${edge.target}-${edge.label ?? ''}-${edge.protocol ?? ''}`\"\n class=\"text-[10px] text-foreground\"\n >\n {{ edge.label ?? \"Connect\" }} -> {{ edge.target\n }}<span v-if=\"edge.protocol\"> ({{ edge.protocol }})</span\n ><span v-if=\"edge.transport\"> - {{ edge.transport }}</span\n ><span v-if=\"edge.auth\"> - auth: {{ edge.auth }}</span\n ><span v-if=\"edge.criticality\"> - {{ edge.criticality }}</span>\n </p>\n </div>\n\n <div\n v-if=\"architectureInspectorNodeSafe.links.length > 0\"\n class=\"mt-1 flex flex-wrap gap-1\"\n >\n <a\n v-for=\"link in architectureInspectorNodeSafe.links\"\n :key=\"`${link.label}-${link.href}`\"\n :href=\"link.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"inline-flex items-center rounded border border-border/70 bg-card/35 px-1.5 py-0.5 text-[9px] text-foreground transition-colors hover:border-primary/45\"\n >\n {{ link.label }}\n </a>\n </div>\n </div>\n </template>\n </div>\n </div>\n </aside>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport dagre from \"@dagrejs/dagre\";\nimport { useStateStore, useStateValue } from \"@json-render/vue\";\nimport {\n Position,\n VueFlow,\n type NodeProps,\n type NodeTypesObject,\n useNodesInitialized,\n useVueFlow,\n} from \"@vue-flow/core\";\nimport {\n computed,\n defineComponent,\n getCurrentInstance,\n h,\n markRaw,\n nextTick,\n onMounted,\n onUnmounted,\n ref,\n watch,\n} from \"vue\";\n\nimport {\n CODE_NODE_MAX_INLINE_CHARS,\n estimateCodeNodeCharsPerLine,\n estimateCodeNodeWidth,\n} from \"../../code-node-sizing\";\nimport { exportFlowDiagram, type DiagramExportFormat } from \"../../composables/useDiagramExport\";\nimport { useFlaierRuntime } from \"../../composables/useFlaierRuntime\";\nimport {\n hasTwoslashHints,\n hasTwoslashHtml,\n normalizeTwoslashHtml,\n normalizeTwoslashLanguage,\n} from \"../../twoslash\";\nimport type {\n ArchitectureDataAsset,\n ArchitectureInterface,\n ArchitectureLink,\n ArchitectureNodeProps,\n FlaierCustomNodeContext,\n FlaierCustomNodeDefinition,\n FlaierCustomNodeSize,\n FlaierResolvedSourceAnchor,\n ArchitectureOperations,\n ArchitectureSecurity,\n ArchitectureZone,\n EdgeTransitionKind,\n FlowEdge,\n FlowNode,\n FlowNodeData,\n FlowNodeType,\n MagicMoveStep,\n SpecElement,\n TwoslashHtml,\n} from \"../../types\";\nimport TimelineControls from \"../controls/TimelineControls.vue\";\nimport ArchitectureSmoothEdge from \"../edges/ArchitectureSmoothEdge.vue\";\nimport ArchitectureNodeVue from \"../nodes/ArchitectureNode.vue\";\nimport CodeNodeVue from \"../nodes/CodeNode.vue\";\nimport DecisionNodeVue from \"../nodes/DecisionNode.vue\";\nimport DescriptionNodeVue from \"../nodes/DescriptionNode.vue\";\nimport ErrorNodeVue from \"../nodes/ErrorNode.vue\";\nimport LinkNodeVue from \"../nodes/LinkNode.vue\";\nimport PayloadNodeVue from \"../nodes/PayloadNode.vue\";\nimport TriggerNodeVue from \"../nodes/TriggerNode.vue\";\n\nconst props = withDefaults(\n defineProps<{\n title: string;\n description?: string;\n mode?: \"narrative\" | \"architecture\";\n zones?: ArchitectureZone[];\n direction?: \"horizontal\" | \"vertical\";\n minHeight?: number;\n layoutEngine?: \"dagre\" | \"manual\";\n layoutRankSep?: number;\n layoutNodeSep?: number;\n layoutEdgeSep?: number;\n themeMode?: \"local\" | \"document\";\n showHeaderOverlay?: boolean;\n showExportControls?: boolean;\n showThemeToggle?: boolean;\n showArchitectureInspector?: boolean;\n defaultArchitectureInspectorOpen?: boolean;\n showArchitectureInspectorToggleText?: boolean;\n }>(),\n {\n mode: \"narrative\",\n direction: \"horizontal\",\n layoutEngine: \"dagre\",\n themeMode: \"local\",\n showHeaderOverlay: true,\n showExportControls: true,\n showThemeToggle: true,\n showArchitectureInspector: true,\n defaultArchitectureInspectorOpen: true,\n showArchitectureInspectorToggleText: true,\n },\n);\n\nconst TYPE_MAP: Record<string, FlowNodeType> = {\n ArchitectureNode: \"architecture\",\n TriggerNode: \"trigger\",\n CodeNode: \"code\",\n DecisionNode: \"decision\",\n PayloadNode: \"payload\",\n ErrorNode: \"error\",\n DescriptionNode: \"description\",\n LinkNode: \"link\",\n};\n\nfunction toNodeType(elementType: string): FlowNodeType | undefined {\n if (TYPE_MAP[elementType]) {\n return TYPE_MAP[elementType];\n }\n\n return customNodes.value[elementType] ? elementType : undefined;\n}\n\nfunction getCustomNodeDefinition(elementType: string): FlaierCustomNodeDefinition | undefined {\n return customNodes.value[elementType];\n}\n\nconst DEFAULT_LAYOUT_ENGINE = \"dagre\";\nconst DEFAULT_FALLBACK_GAP = 420;\nconst DEFAULT_DAGRE_RANK_SEP_HORIZONTAL = 260;\nconst DEFAULT_DAGRE_NODE_SEP_HORIZONTAL = 120;\nconst DEFAULT_DAGRE_RANK_SEP_VERTICAL = 220;\nconst DEFAULT_DAGRE_NODE_SEP_VERTICAL = 120;\nconst DEFAULT_DAGRE_EDGE_SEP = 30;\nconst OVERVIEW_ENTER_ZOOM = 0.52;\nconst OVERVIEW_EXIT_ZOOM = 0.62;\nconst NARRATIVE_FOCUS_HORIZONTAL_CONTEXT = 420;\nconst NARRATIVE_FOCUS_VERTICAL_CONTEXT = 320;\nconst NARRATIVE_FOCUS_MIN_ZOOM = 0.58;\nconst NARRATIVE_FOCUS_MAX_ZOOM = 1.35;\nconst FLAIER_THEME_STORAGE_KEY = \"flaier-ui-theme\";\nconst ARCHITECTURE_ZONE_MIN_CONTENT_PADDING = 44;\nconst ARCHITECTURE_ZONE_MIN_BOTTOM_PADDING = 88;\nconst ARCHITECTURE_ZONE_LABEL_TOP = 12;\nconst ARCHITECTURE_ZONE_LABEL_HEIGHT = 22;\nconst ARCHITECTURE_ZONE_DESCRIPTION_HEIGHT = 16;\nconst ARCHITECTURE_ZONE_LABEL_TO_DESCRIPTION_GAP = 6;\nconst ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP = 12;\nconst ARCHITECTURE_ZONE_NESTED_LABEL_STEP = 18;\nconst ARCHITECTURE_ZONE_CONTAINED_ZONE_GAP = 46;\nconst EDGE_TRANSITION_KINDS: EdgeTransitionKind[] = [\n \"default\",\n \"success\",\n \"error\",\n \"warning\",\n \"retry\",\n \"async\",\n];\nconst EDGE_TRANSITION_KIND_SET = new Set(EDGE_TRANSITION_KINDS);\nconst EDGE_TRANSITION_TRANSPORT_SET = new Set([\"sync\", \"async\"]);\nconst EDGE_TRANSITION_CRITICALITY_SET = new Set([\"low\", \"medium\", \"high\"]);\nconst ARCHITECTURE_NODE_KINDS: Array<NonNullable<ArchitectureNodeProps[\"kind\"]>> = [\n \"service\",\n \"database\",\n \"queue\",\n \"cache\",\n \"gateway\",\n \"external\",\n \"compute\",\n];\nconst ARCHITECTURE_NODE_KIND_SET = new Set(ARCHITECTURE_NODE_KINDS);\nconst ARCHITECTURE_NODE_STATUS_VALUES: Array<NonNullable<ArchitectureNodeProps[\"status\"]>> = [\n \"planned\",\n \"active\",\n \"degraded\",\n \"retired\",\n];\nconst ARCHITECTURE_NODE_STATUS_SET = new Set(ARCHITECTURE_NODE_STATUS_VALUES);\nconst ARCHITECTURE_NODE_TIER_VALUES: Array<NonNullable<ArchitectureNodeProps[\"tier\"]>> = [\n \"edge\",\n \"application\",\n \"integration\",\n \"data\",\n \"platform\",\n \"external\",\n];\nconst ARCHITECTURE_NODE_TIER_SET = new Set(ARCHITECTURE_NODE_TIER_VALUES);\nconst ARCHITECTURE_INTERFACE_DIRECTION_VALUES: Array<\n NonNullable<ArchitectureInterface[\"direction\"]>\n> = [\"inbound\", \"outbound\", \"bidirectional\"];\nconst ARCHITECTURE_INTERFACE_DIRECTION_SET = new Set(ARCHITECTURE_INTERFACE_DIRECTION_VALUES);\nconst ARCHITECTURE_DATA_CLASSIFICATION_VALUES: Array<\n NonNullable<ArchitectureDataAsset[\"classification\"]>\n> = [\"public\", \"internal\", \"confidential\", \"restricted\"];\nconst ARCHITECTURE_DATA_CLASSIFICATION_SET = new Set(ARCHITECTURE_DATA_CLASSIFICATION_VALUES);\nconst ARCHITECTURE_ZONE_COLOR_PALETTE = [\n \"#38bdf8\",\n \"#22c55e\",\n \"#f59e0b\",\n \"#f97316\",\n \"#a78bfa\",\n \"#14b8a6\",\n \"#fb7185\",\n];\nconst SOURCE_ANCHOR_LINK_PATTERN = /^(https?:\\/\\/|vscode:\\/\\/|idea:\\/\\/)/i;\nconst SOURCE_ANCHOR_TRAILING_LOCATION_PATTERN = /^(.*?):(\\d+)(?::(\\d+))?$/;\n\ninterface NodeSize {\n width: number;\n height: number;\n}\n\ninterface OrderedNodeElement {\n key: string;\n index: number;\n nodeType: FlowNodeType;\n element: SpecElement;\n}\n\ninterface TimelineFrame {\n nodeIndex: number;\n nodeKey: string;\n localStep: number;\n totalLocalSteps: number;\n}\n\ninterface BranchChoice {\n id: string;\n label: string;\n description?: string;\n kind?: EdgeTransitionKind;\n}\n\ninterface ParsedTransition {\n to: string;\n label?: string;\n description?: string;\n kind?: EdgeTransitionKind;\n protocol?: string;\n transport?: \"sync\" | \"async\";\n auth?: string;\n contract?: string;\n criticality?: \"low\" | \"medium\" | \"high\";\n}\n\ninterface ParsedSourceAnchor {\n label: string;\n href?: string;\n}\n\ninterface ParsedAnchorLocation {\n path: string;\n line?: number;\n column?: number;\n}\n\ninterface ResolvedArchitectureZone extends ArchitectureZone {\n padding: number;\n}\n\ninterface ArchitectureZoneOverlay {\n id: string;\n label: string;\n description?: string;\n color: string;\n x: number;\n y: number;\n width: number;\n height: number;\n nodeCount: number;\n nestingDepth: number;\n labelLane: number;\n labelOffsetY: number;\n descriptionOffsetY: number;\n}\n\ninterface ArchitectureOutgoingEdge {\n target: string;\n label?: string;\n protocol?: string;\n transport?: \"sync\" | \"async\";\n auth?: string;\n criticality?: \"low\" | \"medium\" | \"high\";\n}\n\ninterface ArchitectureInspectorArchitectureView {\n type: \"ArchitectureNode\";\n label: string;\n sourceAnchor?: ParsedSourceAnchor;\n kind?: ArchitectureNodeProps[\"kind\"];\n status?: ArchitectureNodeProps[\"status\"];\n tier?: ArchitectureNodeProps[\"tier\"];\n technology?: string;\n runtime?: string;\n owner?: string;\n zoneLabel?: string;\n summary: string;\n tags: string[];\n responsibilities: string[];\n capabilities: string[];\n interfaces: ArchitectureInterface[];\n dataAssets: ArchitectureDataAsset[];\n security?: ArchitectureSecurity;\n operations?: ArchitectureOperations;\n links: ArchitectureLink[];\n outgoing: ArchitectureOutgoingEdge[];\n}\n\ninterface ArchitectureInspectorGenericView {\n type: \"Other\";\n label: string;\n sourceAnchor?: ParsedSourceAnchor;\n summary: string;\n elementType: string;\n}\n\ntype ArchitectureInspectorView =\n | ArchitectureInspectorArchitectureView\n | ArchitectureInspectorGenericView;\n\nconst EMPTY_ARCHITECTURE_INSPECTOR_NODE: ArchitectureInspectorArchitectureView = {\n type: \"ArchitectureNode\",\n label: \"\",\n summary: \"\",\n tags: [],\n responsibilities: [],\n capabilities: [],\n interfaces: [],\n dataAssets: [],\n links: [],\n outgoing: [],\n};\n\nconst runtime = useFlaierRuntime();\nconst spec = computed(() => runtime.spec.value);\nconst customNodes = computed(() => runtime.nodes.value);\nconst availableFlows = computed(() => runtime.flowOptions.value);\nconst activeFlowId = computed(() => runtime.activeFlowId.value);\nconst activeFlow = computed(() => {\n const activeId = activeFlowId.value;\n if (!activeId) return undefined;\n return availableFlows.value.find((flow) => flow.id === activeId);\n});\nconst showFlowSelector = computed(() => availableFlows.value.length > 1);\nconst showHeaderOverlay = computed(() => props.showHeaderOverlay !== false);\nconst overlayTitle = computed(() => activeFlow.value?.title ?? props.title);\nconst overlayDescription = computed(() => activeFlow.value?.description ?? props.description);\nconst headerModeLabel = computed(() => {\n if (showFlowSelector.value) {\n return \"Flow\";\n }\n\n return isArchitectureMode.value ? \"Diagram\" : \"Narrative\";\n});\nconst headerDropdownRef = ref<HTMLDivElement | null>(null);\nconst headerDropdownOpen = ref(false);\nconst exportMenuRef = ref<HTMLDivElement | null>(null);\nconst exportMenuOpen = ref(false);\nconst exportInFlight = ref<DiagramExportFormat | null>(null);\nconst exportError = ref<string | null>(null);\nconst containerRef = ref<HTMLDivElement | null>(null);\nconst sceneRef = ref<HTMLElement | null>(null);\nconst containerReady = ref(false);\nconst containerWidth = ref(0);\nconst containerHeight = ref(0);\nconst uiTheme = ref<\"dark\" | \"light\">(\"dark\");\nlet documentThemeObserver: MutationObserver | null = null;\nlet documentThemeMediaQuery: MediaQueryList | null = null;\nlet handleDocumentThemeMediaQueryChange: ((event: MediaQueryListEvent) => void) | null = null;\nconst isLightTheme = computed(() => uiTheme.value === \"light\");\nconst themeMode = computed(() => (props.themeMode === \"document\" ? \"document\" : \"local\"));\nconst isArchitectureMode = computed(() => props.mode === \"architecture\");\nconst showExportControls = computed(() => props.showExportControls !== false);\nconst showThemeToggle = computed(() => props.showThemeToggle !== false);\nconst showArchitectureInspectorPanel = computed(() => props.showArchitectureInspector !== false);\nconst defaultArchitectureInspectorOpen = computed(\n () => props.defaultArchitectureInspectorOpen !== false,\n);\nconst showArchitectureInspectorToggleText = computed(\n () => props.showArchitectureInspectorToggleText !== false,\n);\nconst showTopRightControls = computed(() => {\n return (\n showExportControls.value ||\n showThemeToggle.value ||\n (showExportControls.value && Boolean(exportError.value))\n );\n});\nconst architectureInspectorOpen = ref(props.defaultArchitectureInspectorOpen !== false);\nconst themeToggleLabel = computed(() => {\n return isLightTheme.value ? \"Switch to dark mode\" : \"Switch to light mode\";\n});\n\nconst architectureInspectorToggleLabel = computed(() => {\n return architectureInspectorOpen.value\n ? \"Hide architecture details sidebar\"\n : \"Show architecture details sidebar\";\n});\n\nconst exportButtonLabel = computed(() => {\n if (exportInFlight.value === \"png\") {\n return \"Exporting PNG...\";\n }\n\n if (exportInFlight.value === \"pdf\") {\n return \"Exporting PDF...\";\n }\n\n return \"Export full diagram\";\n});\n\nfunction toggleTheme() {\n if (themeMode.value === \"document\") {\n applyDocumentTheme(isLightTheme.value ? \"dark\" : \"light\");\n return;\n }\n\n uiTheme.value = isLightTheme.value ? \"dark\" : \"light\";\n}\n\nfunction toggleArchitectureInspector() {\n architectureInspectorOpen.value = !architectureInspectorOpen.value;\n}\n\nfunction normalizeTheme(value: unknown): \"dark\" | \"light\" | null {\n if (value === \"dark\" || value === \"light\") {\n return value;\n }\n\n return null;\n}\n\nfunction readStoredTheme() {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n try {\n return normalizeTheme(window.localStorage.getItem(FLAIER_THEME_STORAGE_KEY));\n } catch {\n return null;\n }\n}\n\nfunction getPreferredSystemTheme(): \"dark\" | \"light\" {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") {\n return \"dark\";\n }\n\n return window.matchMedia(\"(prefers-color-scheme: light)\").matches ? \"light\" : \"dark\";\n}\n\nfunction getDocumentTheme(): \"dark\" | \"light\" | null {\n if (typeof document === \"undefined\") {\n return null;\n }\n\n const root = document.documentElement;\n const dataTheme = root.getAttribute(\"data-theme\")?.trim().toLowerCase();\n\n if (dataTheme === \"dark\" || dataTheme === \"light\") {\n return dataTheme;\n }\n\n if (root.classList.contains(\"dark\")) {\n return \"dark\";\n }\n\n if (root.classList.contains(\"light\")) {\n return \"light\";\n }\n\n const colorScheme = root.style.colorScheme?.trim().toLowerCase();\n if (colorScheme === \"dark\" || colorScheme === \"light\") {\n return colorScheme;\n }\n\n return null;\n}\n\nfunction applyDocumentTheme(theme: \"dark\" | \"light\") {\n if (typeof document === \"undefined\") {\n return;\n }\n\n const root = document.documentElement;\n root.classList.toggle(\"dark\", theme === \"dark\");\n root.style.colorScheme = theme;\n}\n\nfunction persistTheme(theme: \"dark\" | \"light\") {\n if (typeof window === \"undefined\") {\n return;\n }\n\n try {\n window.localStorage.setItem(FLAIER_THEME_STORAGE_KEY, theme);\n } catch {\n // no-op when storage is unavailable\n }\n}\n\nfunction syncDocumentTheme() {\n uiTheme.value = getDocumentTheme() ?? getPreferredSystemTheme();\n}\n\nfunction startDocumentThemeSync() {\n if (typeof document !== \"undefined\" && typeof MutationObserver !== \"undefined\") {\n if (!documentThemeObserver) {\n documentThemeObserver = new MutationObserver(() => {\n syncDocumentTheme();\n });\n\n documentThemeObserver.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\", \"style\", \"data-theme\"],\n });\n }\n }\n\n if (typeof window !== \"undefined\" && typeof window.matchMedia === \"function\") {\n if (!documentThemeMediaQuery) {\n documentThemeMediaQuery = window.matchMedia(\"(prefers-color-scheme: light)\");\n }\n\n if (!handleDocumentThemeMediaQueryChange) {\n handleDocumentThemeMediaQueryChange = () => {\n syncDocumentTheme();\n };\n\n if (typeof documentThemeMediaQuery.addEventListener === \"function\") {\n documentThemeMediaQuery.addEventListener(\"change\", handleDocumentThemeMediaQueryChange);\n } else {\n documentThemeMediaQuery.addListener(handleDocumentThemeMediaQueryChange);\n }\n }\n }\n}\n\nfunction stopDocumentThemeSync() {\n if (documentThemeObserver) {\n documentThemeObserver.disconnect();\n documentThemeObserver = null;\n }\n\n if (documentThemeMediaQuery && handleDocumentThemeMediaQueryChange) {\n if (typeof documentThemeMediaQuery.removeEventListener === \"function\") {\n documentThemeMediaQuery.removeEventListener(\"change\", handleDocumentThemeMediaQueryChange);\n } else {\n documentThemeMediaQuery.removeListener(handleDocumentThemeMediaQueryChange);\n }\n }\n\n handleDocumentThemeMediaQueryChange = null;\n documentThemeMediaQuery = null;\n}\n\nfunction toggleHeaderDropdown() {\n if (!showFlowSelector.value) return;\n closeExportMenu();\n headerDropdownOpen.value = !headerDropdownOpen.value;\n}\n\nfunction closeHeaderDropdown() {\n headerDropdownOpen.value = false;\n}\n\nfunction toggleExportMenu() {\n if (exportInFlight.value) return;\n if (!canExportDiagram.value) return;\n\n closeHeaderDropdown();\n exportMenuOpen.value = !exportMenuOpen.value;\n}\n\nfunction closeExportMenu() {\n exportMenuOpen.value = false;\n}\n\nfunction handleFlowSelect(flowId: string) {\n if (!flowId) return;\n\n runtime.setActiveFlow(flowId);\n headerDropdownOpen.value = false;\n closeExportMenu();\n}\n\nwatch(showFlowSelector, (show) => {\n if (!show) {\n headerDropdownOpen.value = false;\n }\n});\n\nwatch(activeFlowId, () => {\n headerDropdownOpen.value = false;\n closeExportMenu();\n});\n\nwatch(uiTheme, (theme) => {\n if (themeMode.value === \"document\") {\n return;\n }\n\n persistTheme(theme);\n});\n\nwatch(\n themeMode,\n (mode) => {\n if (mode === \"document\") {\n startDocumentThemeSync();\n syncDocumentTheme();\n return;\n }\n\n stopDocumentThemeSync();\n uiTheme.value = readStoredTheme() ?? getPreferredSystemTheme();\n },\n { immediate: true },\n);\n\nconst rootElement = computed(() => {\n const activeSpec = spec.value;\n if (!activeSpec) return undefined;\n return activeSpec.elements[activeSpec.root];\n});\n\nconst orderedNodeElements = computed<OrderedNodeElement[]>(() => {\n const activeSpec = spec.value;\n const root = rootElement.value;\n\n if (!activeSpec || !root?.children?.length) return [];\n\n const result: OrderedNodeElement[] = [];\n const queue = [...root.children];\n const seen = new Set<string>();\n\n while (queue.length > 0) {\n const key = queue.shift();\n if (!key || seen.has(key)) continue;\n\n const element = activeSpec.elements[key];\n if (!element) continue;\n\n const nodeType = toNodeType(element.type);\n if (!nodeType) continue;\n\n seen.add(key);\n result.push({ key, index: result.length, nodeType, element });\n\n for (const childKey of element.children ?? []) {\n if (!seen.has(childKey)) {\n queue.push(childKey);\n }\n }\n }\n\n return result;\n});\n\nconst orderedNodeByKey = computed<Record<string, OrderedNodeElement>>(() => {\n const map: Record<string, OrderedNodeElement> = {};\n\n for (const node of orderedNodeElements.value) {\n map[node.key] = node;\n }\n\n return map;\n});\n\nconst rootLinearNextByKey = computed<Record<string, string>>(() => {\n const root = rootElement.value;\n if (!root?.children?.length) return {};\n const rootChildren = root.children;\n\n const map: Record<string, string> = {};\n\n rootChildren.forEach((key, index) => {\n const nextKey = rootChildren[index + 1];\n if (!nextKey) return;\n\n if (orderedNodeByKey.value[key] && orderedNodeByKey.value[nextKey]) {\n map[key] = nextKey;\n }\n });\n\n return map;\n});\n\nconst transitionMetaBySource = computed<Record<string, Record<string, ParsedTransition>>>(() => {\n const map: Record<string, Record<string, ParsedTransition>> = {};\n\n for (const node of orderedNodeElements.value) {\n const transitions = toTransitions(node.element.props.transitions).filter((transition) =>\n Boolean(orderedNodeByKey.value[transition.to]),\n );\n\n if (transitions.length === 0) continue;\n\n const byTarget: Record<string, ParsedTransition> = {};\n for (const transition of transitions) {\n if (byTarget[transition.to]) continue;\n byTarget[transition.to] = transition;\n }\n\n if (Object.keys(byTarget).length > 0) {\n map[node.key] = byTarget;\n }\n }\n\n return map;\n});\n\nconst outgoingNodeKeys = computed<Record<string, string[]>>(() => {\n const map: Record<string, string[]> = {};\n\n for (const node of orderedNodeElements.value) {\n const transitionTargets = toTransitions(node.element.props.transitions)\n .map((transition) => transition.to)\n .filter((key) => Boolean(orderedNodeByKey.value[key]));\n\n const explicit = (node.element.children ?? []).filter((key) =>\n Boolean(orderedNodeByKey.value[key]),\n );\n\n const combined = mergeOutgoingTargets(transitionTargets, explicit);\n\n if (combined.length > 0) {\n map[node.key] = combined;\n continue;\n }\n\n const fallback = rootLinearNextByKey.value[node.key];\n map[node.key] = fallback ? [fallback] : [];\n }\n\n return map;\n});\n\nconst incomingNodeKeys = computed<Record<string, string[]>>(() => {\n const map: Record<string, string[]> = {};\n\n for (const node of orderedNodeElements.value) {\n map[node.key] = [];\n }\n\n for (const [source, targets] of Object.entries(outgoingNodeKeys.value)) {\n for (const target of targets) {\n if (!map[target]) continue;\n map[target].push(source);\n }\n }\n\n return map;\n});\n\nconst startNodeKey = computed(() => {\n const root = rootElement.value;\n if (!root?.children?.length) return undefined;\n\n return root.children.find((key) => Boolean(orderedNodeByKey.value[key]));\n});\n\nfunction toOptionalString(value: unknown) {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction toStringArray(value: unknown) {\n if (!Array.isArray(value)) {\n return [];\n }\n\n return value\n .map((entry) => toTrimmedNonEmptyString(entry))\n .filter((entry): entry is string => Boolean(entry));\n}\n\nfunction toTrimmedNonEmptyString(value: unknown) {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction toRequiredString(value: unknown) {\n return toOptionalString(value) ?? \"\";\n}\n\nfunction toBoolean(value: unknown, fallback = false) {\n return typeof value === \"boolean\" ? value : fallback;\n}\n\nfunction toOptionalBoolean(value: unknown) {\n return typeof value === \"boolean\" ? value : undefined;\n}\n\nfunction toTwoslashHtml(value: unknown): TwoslashHtml | undefined {\n return normalizeTwoslashHtml(value);\n}\n\nfunction toPayloadFormat(value: unknown): \"json\" | \"yaml\" | \"text\" | undefined {\n if (value === \"json\" || value === \"yaml\" || value === \"text\") {\n return value;\n }\n\n return undefined;\n}\n\nfunction toArchitectureKind(value: unknown): ArchitectureNodeProps[\"kind\"] | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n if (ARCHITECTURE_NODE_KIND_SET.has(value as NonNullable<ArchitectureNodeProps[\"kind\"]>)) {\n return value as ArchitectureNodeProps[\"kind\"];\n }\n\n return undefined;\n}\n\nfunction toArchitectureZoneId(value: unknown) {\n return toTrimmedNonEmptyString(value);\n}\n\nfunction toArchitectureStatus(value: unknown): ArchitectureNodeProps[\"status\"] | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n if (ARCHITECTURE_NODE_STATUS_SET.has(value as NonNullable<ArchitectureNodeProps[\"status\"]>)) {\n return value as ArchitectureNodeProps[\"status\"];\n }\n\n return undefined;\n}\n\nfunction toArchitectureTier(value: unknown): ArchitectureNodeProps[\"tier\"] | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n if (ARCHITECTURE_NODE_TIER_SET.has(value as NonNullable<ArchitectureNodeProps[\"tier\"]>)) {\n return value as ArchitectureNodeProps[\"tier\"];\n }\n\n return undefined;\n}\n\nfunction toArchitectureInterfaces(value: unknown): ArchitectureInterface[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n const result: ArchitectureInterface[] = [];\n\n for (const rawEntry of value) {\n if (!rawEntry || typeof rawEntry !== \"object\") {\n continue;\n }\n\n const entry = rawEntry as Record<string, unknown>;\n const name = toTrimmedNonEmptyString(entry.name);\n if (!name) {\n continue;\n }\n\n const directionRaw = toTrimmedNonEmptyString(entry.direction);\n const direction =\n directionRaw &&\n ARCHITECTURE_INTERFACE_DIRECTION_SET.has(\n directionRaw as NonNullable<ArchitectureInterface[\"direction\"]>,\n )\n ? (directionRaw as ArchitectureInterface[\"direction\"])\n : undefined;\n\n result.push({\n name,\n protocol: toTrimmedNonEmptyString(entry.protocol),\n direction,\n contract: toTrimmedNonEmptyString(entry.contract),\n auth: toTrimmedNonEmptyString(entry.auth),\n notes: toTrimmedNonEmptyString(entry.notes),\n });\n }\n\n return result;\n}\n\nfunction toArchitectureDataAssets(value: unknown): ArchitectureDataAsset[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n const result: ArchitectureDataAsset[] = [];\n\n for (const rawEntry of value) {\n if (!rawEntry || typeof rawEntry !== \"object\") {\n continue;\n }\n\n const entry = rawEntry as Record<string, unknown>;\n const name = toTrimmedNonEmptyString(entry.name);\n if (!name) {\n continue;\n }\n\n const classificationRaw = toTrimmedNonEmptyString(entry.classification);\n const classification =\n classificationRaw &&\n ARCHITECTURE_DATA_CLASSIFICATION_SET.has(\n classificationRaw as NonNullable<ArchitectureDataAsset[\"classification\"]>,\n )\n ? (classificationRaw as ArchitectureDataAsset[\"classification\"])\n : undefined;\n\n result.push({\n name,\n kind: toTrimmedNonEmptyString(entry.kind),\n classification,\n retention: toTrimmedNonEmptyString(entry.retention),\n notes: toTrimmedNonEmptyString(entry.notes),\n });\n }\n\n return result;\n}\n\nfunction toArchitectureSecurity(value: unknown): ArchitectureSecurity | undefined {\n if (!value || typeof value !== \"object\") {\n return undefined;\n }\n\n const record = value as Record<string, unknown>;\n const security = {\n auth: toTrimmedNonEmptyString(record.auth),\n encryption: toTrimmedNonEmptyString(record.encryption),\n pii: toOptionalBoolean(record.pii),\n threatModel: toTrimmedNonEmptyString(record.threatModel),\n } satisfies ArchitectureSecurity;\n\n if (\n !security.auth &&\n !security.encryption &&\n security.pii === undefined &&\n !security.threatModel\n ) {\n return undefined;\n }\n\n return security;\n}\n\nfunction toArchitectureOperations(value: unknown): ArchitectureOperations | undefined {\n if (!value || typeof value !== \"object\") {\n return undefined;\n }\n\n const record = value as Record<string, unknown>;\n const operations = {\n owner: toTrimmedNonEmptyString(record.owner),\n slo: toTrimmedNonEmptyString(record.slo),\n alert: toTrimmedNonEmptyString(record.alert),\n runbook: toTrimmedNonEmptyString(record.runbook),\n } satisfies ArchitectureOperations;\n\n if (!operations.owner && !operations.slo && !operations.alert && !operations.runbook) {\n return undefined;\n }\n\n return operations;\n}\n\nfunction toArchitectureLinks(value: unknown): ArchitectureLink[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n const result: ArchitectureLink[] = [];\n\n for (const rawEntry of value) {\n if (!rawEntry || typeof rawEntry !== \"object\") {\n continue;\n }\n\n const entry = rawEntry as Record<string, unknown>;\n const label = toTrimmedNonEmptyString(entry.label);\n const href = toTrimmedNonEmptyString(entry.href);\n if (!label || !href) {\n continue;\n }\n\n result.push({\n label,\n href,\n });\n }\n\n return result;\n}\n\nfunction toArchitectureZones(value: unknown): ResolvedArchitectureZone[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n const seen = new Set<string>();\n const result: ResolvedArchitectureZone[] = [];\n\n for (const rawEntry of value) {\n if (!rawEntry || typeof rawEntry !== \"object\") {\n continue;\n }\n\n const entry = rawEntry as Record<string, unknown>;\n const id = toTrimmedNonEmptyString(entry.id);\n const label = toTrimmedNonEmptyString(entry.label);\n if (!id || !label || seen.has(id)) {\n continue;\n }\n\n seen.add(id);\n\n const paddingRaw = entry.padding;\n const padding =\n typeof paddingRaw === \"number\" && Number.isFinite(paddingRaw)\n ? Math.max(28, Math.min(180, Math.round(paddingRaw)))\n : 62;\n\n result.push({\n id,\n label,\n description: toTrimmedNonEmptyString(entry.description),\n color: toTrimmedNonEmptyString(entry.color),\n padding,\n });\n }\n\n return result;\n}\n\nfunction humanizeZoneId(value: string) {\n return value\n .replace(/[-_]+/g, \" \")\n .replace(/\\s+/g, \" \")\n .trim()\n .replace(/(^|\\s)\\w/g, (char) => char.toUpperCase());\n}\n\nfunction resolveZoneColor(index: number, explicitColor?: string) {\n return (\n explicitColor ||\n ARCHITECTURE_ZONE_COLOR_PALETTE[index % ARCHITECTURE_ZONE_COLOR_PALETTE.length] ||\n \"#38bdf8\"\n );\n}\n\nfunction toHexChannel(value: string) {\n return Number.parseInt(value, 16);\n}\n\nfunction hexToRgb(value: string) {\n const hex = value.trim().replace(/^#/, \"\");\n if (hex.length === 3) {\n const r = toHexChannel(`${hex[0]}${hex[0]}`);\n const g = toHexChannel(`${hex[1]}${hex[1]}`);\n const b = toHexChannel(`${hex[2]}${hex[2]}`);\n if ([r, g, b].every((channel) => Number.isFinite(channel))) {\n return { r, g, b };\n }\n\n return undefined;\n }\n\n if (hex.length === 6) {\n const r = toHexChannel(hex.slice(0, 2));\n const g = toHexChannel(hex.slice(2, 4));\n const b = toHexChannel(hex.slice(4, 6));\n if ([r, g, b].every((channel) => Number.isFinite(channel))) {\n return { r, g, b };\n }\n }\n\n return undefined;\n}\n\nfunction withAlpha(color: string, alpha: number) {\n const rgb = hexToRgb(color);\n if (!rgb) {\n return color;\n }\n\n return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`;\n}\n\nfunction toPositiveInteger(value: unknown) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n return undefined;\n }\n\n const asInteger = Math.floor(value);\n return asInteger > 0 ? asInteger : undefined;\n}\n\nfunction parseInlineSourceAnchorLocation(value: string): ParsedAnchorLocation | undefined {\n const trimmed = value.trim();\n if (!trimmed) return undefined;\n\n const matched = SOURCE_ANCHOR_TRAILING_LOCATION_PATTERN.exec(trimmed);\n if (!matched) {\n return {\n path: trimmed,\n };\n }\n\n const rawPath = matched[1]?.trim();\n const rawLine = matched[2];\n const rawColumn = matched[3];\n\n if (!rawPath || !rawLine) {\n return {\n path: trimmed,\n };\n }\n\n const line = Number(rawLine);\n const column = rawColumn ? Number(rawColumn) : undefined;\n\n return {\n path: rawPath,\n line: Number.isFinite(line) && line > 0 ? Math.floor(line) : undefined,\n column: Number.isFinite(column) && (column ?? 0) > 0 ? Math.floor(column as number) : undefined,\n };\n}\n\nfunction toVsCodeFileHref(path: string, line?: number, column?: number) {\n const normalizedPath = path.trim().replace(/\\\\/g, \"/\");\n if (!normalizedPath) return undefined;\n\n const encodedPath = encodeURI(normalizedPath);\n const linePart = line ? `:${line}` : \"\";\n const columnPart = line && column ? `:${column}` : \"\";\n\n return `vscode://file/${encodedPath}${linePart}${columnPart}`;\n}\n\nfunction resolveSourceAnchorHref(\n path: string,\n line?: number,\n column?: number,\n explicitHref?: string,\n) {\n if (explicitHref) {\n return explicitHref;\n }\n\n if (SOURCE_ANCHOR_LINK_PATTERN.test(path)) {\n return path;\n }\n\n return toVsCodeFileHref(path, line, column);\n}\n\nfunction toSourceAnchor(value: unknown): ParsedSourceAnchor | undefined {\n const inlineAnchor = toTrimmedNonEmptyString(value);\n if (inlineAnchor) {\n const parsed = parseInlineSourceAnchorLocation(inlineAnchor);\n\n return {\n label: inlineAnchor,\n href: parsed ? resolveSourceAnchorHref(parsed.path, parsed.line, parsed.column) : undefined,\n };\n }\n\n if (!value || typeof value !== \"object\") {\n return undefined;\n }\n\n const record = value as Record<string, unknown>;\n const path = toTrimmedNonEmptyString(record.path);\n if (!path) {\n return undefined;\n }\n\n const line = toPositiveInteger(record.line);\n const column = toPositiveInteger(record.column);\n const explicitLabel = toTrimmedNonEmptyString(record.label);\n const explicitHref = toTrimmedNonEmptyString(record.href);\n\n const location = [path];\n if (line !== undefined) {\n location.push(String(line));\n\n if (column !== undefined) {\n location.push(String(column));\n }\n }\n\n const label = explicitLabel ?? location.join(\":\");\n\n return {\n label,\n href: resolveSourceAnchorHref(path, line, column, explicitHref),\n };\n}\n\nfunction resolveNodeSourceAnchor(nodeProps: Record<string, unknown>) {\n const explicit = toSourceAnchor(nodeProps.sourceAnchor);\n if (explicit) {\n return explicit;\n }\n\n const fileFallback = toTrimmedNonEmptyString(nodeProps.file);\n if (!fileFallback) {\n return undefined;\n }\n\n return {\n label: fileFallback,\n } satisfies ParsedSourceAnchor;\n}\n\nfunction createCustomNodeContext(\n node: OrderedNodeElement,\n): FlaierCustomNodeContext<Record<string, unknown>> {\n return {\n key: node.key,\n elementType: node.element.type,\n props: node.element.props,\n sourceAnchor: resolveNodeSourceAnchor(node.element.props) as\n | FlaierResolvedSourceAnchor\n | undefined,\n };\n}\n\nfunction toCustomNodeSize(value: FlaierCustomNodeSize | undefined): NodeSize | undefined {\n if (!value) {\n return undefined;\n }\n\n const width = Number(value.width);\n const height = Number(value.height);\n\n if (!Number.isFinite(width) || !Number.isFinite(height)) {\n return undefined;\n }\n\n return {\n width: Math.max(120, Math.round(width)),\n height: Math.max(72, Math.round(height)),\n };\n}\n\nfunction getNodeSummary(node: OrderedNodeElement) {\n const customNode = getCustomNodeDefinition(node.element.type);\n if (customNode?.getSummary) {\n return customNode.getSummary(createCustomNodeContext(node)) ?? \"\";\n }\n\n if (node.element.type === \"CodeNode\") {\n return (\n toTrimmedNonEmptyString(node.element.props.story) ??\n toTrimmedNonEmptyString(node.element.props.comment) ??\n \"\"\n );\n }\n\n if (node.element.type === \"DescriptionNode\") {\n return toTrimmedNonEmptyString(node.element.props.body) ?? \"\";\n }\n\n if (node.element.type === \"DecisionNode\") {\n return (\n toTrimmedNonEmptyString(node.element.props.description) ??\n toTrimmedNonEmptyString(node.element.props.condition) ??\n \"\"\n );\n }\n\n if (node.element.type === \"PayloadNode\") {\n return toTrimmedNonEmptyString(node.element.props.description) ?? \"\";\n }\n\n if (node.element.type === \"ErrorNode\") {\n const message = toTrimmedNonEmptyString(node.element.props.message);\n const cause = toTrimmedNonEmptyString(node.element.props.cause);\n const mitigation = toTrimmedNonEmptyString(node.element.props.mitigation);\n\n return [message, cause ? `Cause: ${cause}` : \"\", mitigation ? `Mitigation: ${mitigation}` : \"\"]\n .filter((value): value is string => typeof value === \"string\" && value.length > 0)\n .join(\" \");\n }\n\n if (node.element.type === \"ArchitectureNode\") {\n const technology = toTrimmedNonEmptyString(node.element.props.technology);\n const description = toTrimmedNonEmptyString(node.element.props.description);\n\n return [technology ? `Technology: ${technology}` : \"\", description ?? \"\"]\n .filter((value): value is string => typeof value === \"string\" && value.length > 0)\n .join(\" \");\n }\n\n return toTrimmedNonEmptyString(node.element.props.description) ?? \"\";\n}\n\nfunction createCustomNodeRenderer(\n elementType: string,\n definition: FlaierCustomNodeDefinition,\n displayName: string,\n) {\n return markRaw(\n defineComponent<NodeProps<FlowNodeData>>({\n name: `Flaier${displayName}Node`,\n props: [\n \"id\",\n \"type\",\n \"selected\",\n \"connectable\",\n \"position\",\n \"dimensions\",\n \"label\",\n \"isValidTargetPos\",\n \"isValidSourcePos\",\n \"parent\",\n \"parentNodeId\",\n \"dragging\",\n \"resizing\",\n \"zIndex\",\n \"targetPosition\",\n \"sourcePosition\",\n \"dragHandle\",\n \"data\",\n \"events\",\n ],\n setup(nodeProps) {\n return () =>\n h(definition.component, {\n ...nodeProps.data?.props,\n active: nodeProps.data?.active,\n nodeKey: nodeProps.data?.key,\n elementType: nodeProps.data?.elementType ?? elementType,\n sourceAnchor: nodeProps.data?.sourceAnchor,\n });\n },\n }),\n );\n}\n\nconst customNodeTypes = computed<NodeTypesObject>(() => {\n return Object.fromEntries(\n Object.entries(customNodes.value).map(([elementType, definition]) => {\n const displayName = elementType.replace(/[^a-z0-9]+/gi, \"\") || \"Custom\";\n\n return [elementType, createCustomNodeRenderer(elementType, definition, displayName)];\n }),\n );\n});\n\nfunction codeNodeTwoslashEnabled(element: SpecElement) {\n if (element.type !== \"CodeNode\") return false;\n\n if (!normalizeTwoslashLanguage(toOptionalString(element.props.language))) {\n return false;\n }\n\n if (!hasTwoslashHtml(toTwoslashHtml(element.props.twoslashHtml))) {\n return false;\n }\n\n const requested = toOptionalBoolean(element.props.twoslash);\n if (requested === true) return true;\n if (requested === false) return false;\n\n const variants = [\n toRequiredString(element.props.code),\n ...toMagicMoveSteps(element.props.magicMoveSteps).map((step) => step.code),\n ];\n\n return variants.some((code) => hasTwoslashHints(code));\n}\n\nfunction toPositiveNumber(value: unknown, fallback: number, min = 1) {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return Math.max(min, Math.floor(value));\n }\n\n return fallback;\n}\n\nfunction toMagicMoveSteps(value: unknown): MagicMoveStep[] {\n if (!Array.isArray(value)) return [];\n\n return value\n .filter((item): item is MagicMoveStep => {\n if (!item || typeof item !== \"object\") return false;\n\n const record = item as Record<string, unknown>;\n if (typeof record.code !== \"string\") return false;\n\n const optionalKeys: Array<\"title\" | \"comment\" | \"story\" | \"speaker\"> = [\n \"title\",\n \"comment\",\n \"story\",\n \"speaker\",\n ];\n\n return optionalKeys.every((key) => {\n const current = record[key];\n return current === undefined || typeof current === \"string\";\n });\n })\n .map((item) => ({\n code: item.code,\n title: toOptionalString(item.title),\n comment: toOptionalString(item.comment),\n story: toOptionalString(item.story),\n speaker: toOptionalString(item.speaker),\n }));\n}\n\nfunction toTransitionKind(value: unknown): EdgeTransitionKind | undefined {\n if (typeof value !== \"string\") return undefined;\n return EDGE_TRANSITION_KIND_SET.has(value as EdgeTransitionKind)\n ? (value as EdgeTransitionKind)\n : undefined;\n}\n\nfunction toTransitionTransport(value: unknown): \"sync\" | \"async\" | undefined {\n if (typeof value !== \"string\") return undefined;\n return EDGE_TRANSITION_TRANSPORT_SET.has(value) ? (value as \"sync\" | \"async\") : undefined;\n}\n\nfunction toTransitionCriticality(value: unknown): \"low\" | \"medium\" | \"high\" | undefined {\n if (typeof value !== \"string\") return undefined;\n return EDGE_TRANSITION_CRITICALITY_SET.has(value)\n ? (value as \"low\" | \"medium\" | \"high\")\n : undefined;\n}\n\nfunction toTransitions(value: unknown): ParsedTransition[] {\n if (!Array.isArray(value)) return [];\n\n return value\n .filter((item): item is Record<string, unknown> => {\n if (!item || typeof item !== \"object\") return false;\n if (!toOptionalString(item.to)) return false;\n\n const label = item.label;\n const description = item.description;\n const kind = item.kind;\n const protocol = item.protocol;\n const transport = item.transport;\n const auth = item.auth;\n const contract = item.contract;\n const criticality = item.criticality;\n\n if (label !== undefined && typeof label !== \"string\") return false;\n if (description !== undefined && typeof description !== \"string\") return false;\n if (kind !== undefined && !toTransitionKind(kind)) return false;\n if (protocol !== undefined && typeof protocol !== \"string\") return false;\n if (transport !== undefined && !toTransitionTransport(transport)) return false;\n if (auth !== undefined && typeof auth !== \"string\") return false;\n if (contract !== undefined && typeof contract !== \"string\") return false;\n if (criticality !== undefined && !toTransitionCriticality(criticality)) return false;\n\n return true;\n })\n .map((item) => ({\n to: toRequiredString(item.to),\n label: toOptionalString(item.label),\n description: toOptionalString(item.description),\n kind: toTransitionKind(item.kind),\n protocol: toOptionalString(item.protocol),\n transport: toTransitionTransport(item.transport),\n auth: toOptionalString(item.auth),\n contract: toOptionalString(item.contract),\n criticality: toTransitionCriticality(item.criticality),\n }));\n}\n\nfunction resolveTransitionEdgeLabel(transition?: ParsedTransition) {\n if (!transition) {\n return undefined;\n }\n\n const metadataParts = [transition.protocol, transition.transport, transition.criticality].filter(\n (value): value is string => Boolean(value),\n );\n\n if (transition.label) {\n return metadataParts.length > 0\n ? `${transition.label} (${metadataParts.join(\" | \")})`\n : transition.label;\n }\n\n if (metadataParts.length > 0) {\n return metadataParts.join(\" | \");\n }\n\n return undefined;\n}\n\nfunction mergeOutgoingTargets(primary: string[], secondary: string[]) {\n const merged: string[] = [];\n const seen = new Set<string>();\n\n for (const target of [...primary, ...secondary]) {\n if (!target || seen.has(target)) continue;\n\n seen.add(target);\n merged.push(target);\n }\n\n return merged;\n}\n\nfunction getNodeFrameCount(element: SpecElement) {\n if (element.type !== \"CodeNode\") return 1;\n\n const magicMoveSteps = toMagicMoveSteps(element.props.magicMoveSteps);\n const baseSteps = Math.max(1, magicMoveSteps.length);\n\n if (magicMoveSteps.length > 0 && codeNodeTwoslashEnabled(element)) {\n return baseSteps + 1;\n }\n\n return baseSteps;\n}\n\nfunction getCodeNodeMaxLines(element: SpecElement) {\n const rootCodeLines = toRequiredString(element.props.code).split(\"\\n\").length;\n const stepLines = toMagicMoveSteps(element.props.magicMoveSteps).map(\n (step) => step.code.split(\"\\n\").length,\n );\n\n return Math.max(rootCodeLines, ...stepLines);\n}\n\nfunction getCodeNodeMaxLineLength(element: SpecElement) {\n const variants = [\n toRequiredString(element.props.code),\n ...toMagicMoveSteps(element.props.magicMoveSteps).map((step) => step.code),\n ];\n\n return variants.reduce((max, code) => {\n const lineMax = code\n .split(\"\\n\")\n .reduce((lineLengthMax, line) => Math.max(lineLengthMax, line.length), 0);\n\n return Math.max(max, lineMax);\n }, 0);\n}\n\nfunction estimateWrappedLines(text: string, charsPerLine = 48) {\n return text\n .split(\"\\n\")\n .reduce((total, line) => total + Math.max(1, Math.ceil(line.length / charsPerLine)), 0);\n}\n\nfunction getCodeNodeWrappedLines(element: SpecElement, charsPerLine = 44) {\n const variants = [\n toRequiredString(element.props.code),\n ...toMagicMoveSteps(element.props.magicMoveSteps).map((step) => step.code),\n ];\n\n return variants.reduce((max, code) => {\n return Math.max(max, estimateWrappedLines(code, charsPerLine));\n }, 1);\n}\n\nfunction hasCodeNodeStoryMeta(element: SpecElement) {\n return toMagicMoveSteps(element.props.magicMoveSteps).some((step) => step.title || step.speaker);\n}\n\nfunction getCodeNodeStoryLines(element: SpecElement) {\n const variants = [\n toOptionalString(element.props.story),\n toOptionalString(element.props.comment),\n ...toMagicMoveSteps(element.props.magicMoveSteps).flatMap((step) => [step.story, step.comment]),\n ].filter((value): value is string => typeof value === \"string\" && value.length > 0);\n\n if (variants.length === 0) return 0;\n\n return variants.reduce((max, current) => Math.max(max, estimateWrappedLines(current)), 1);\n}\n\nfunction estimateNodeTextLines(value: unknown, charsPerLine: number) {\n const text = toOptionalString(value);\n if (!text) return 0;\n return estimateWrappedLines(text, charsPerLine);\n}\n\nfunction estimateCodeNodeSize(element: SpecElement): NodeSize {\n const maxLineLength = getCodeNodeMaxLineLength(element);\n const nodeWidth = estimateCodeNodeWidth(maxLineLength);\n const codeCharsPerLine = estimateCodeNodeCharsPerLine(nodeWidth);\n const autoWrapEnabled = maxLineLength > CODE_NODE_MAX_INLINE_CHARS;\n const wrapEnabled = toBoolean(element.props.wrapLongLines) || autoWrapEnabled;\n\n const codeLines = wrapEnabled\n ? getCodeNodeWrappedLines(element, codeCharsPerLine)\n : getCodeNodeMaxLines(element);\n const storyLines = getCodeNodeStoryLines(element);\n const storyHasMeta = hasCodeNodeStoryMeta(element);\n\n const codeViewportHeight = wrapEnabled\n ? Math.min(400, Math.max(190, 72 + codeLines * 16))\n : Math.min(340, Math.max(160, 84 + codeLines * 17));\n\n const storyViewportHeight =\n storyLines > 0 ? Math.min(220, Math.max(88, (storyHasMeta ? 56 : 34) + storyLines * 18)) : 0;\n\n return {\n width: nodeWidth,\n height: Math.min(760, Math.max(230, 42 + codeViewportHeight + storyViewportHeight + 14)),\n };\n}\n\nfunction estimateNodeSize(node: OrderedNodeElement): NodeSize {\n const { element } = node;\n const customNode = getCustomNodeDefinition(element.type);\n\n if (customNode?.estimateSize) {\n const customSize = toCustomNodeSize(customNode.estimateSize(createCustomNodeContext(node)));\n if (customSize) {\n return customSize;\n }\n }\n\n if (customNode) {\n return {\n width: 240,\n height: 120,\n };\n }\n\n if (element.type === \"ArchitectureNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 28));\n const technologyLines = estimateNodeTextLines(element.props.technology, 30);\n const ownerLines = estimateNodeTextLines(element.props.owner, 30);\n const runtimeLines = estimateNodeTextLines(element.props.runtime, 30);\n const descriptionLines = estimateNodeTextLines(element.props.description, 34);\n const capabilityCount = Math.min(4, toStringArray(element.props.capabilities).length);\n const tagCount = Math.min(4, toStringArray(element.props.tags).length);\n const chipRows =\n (capabilityCount > 0 ? Math.ceil(capabilityCount / 2) : 0) + (tagCount > 0 ? 1 : 0);\n const metaRows =\n toArchitectureStatus(element.props.status) || toArchitectureTier(element.props.tier) ? 1 : 0;\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 270,\n height: Math.min(\n 460,\n Math.max(\n 144,\n 58 +\n labelLines * 19 +\n technologyLines * 14 +\n ownerLines * 12 +\n runtimeLines * 12 +\n descriptionLines * 15 +\n metaRows * 16 +\n chipRows * 18 +\n anchorHeight,\n ),\n ),\n };\n }\n\n if (element.type === \"CodeNode\") {\n return estimateCodeNodeSize(element);\n }\n\n if (element.type === \"TriggerNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 24));\n const descriptionLines = estimateNodeTextLines(element.props.description, 30);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 220,\n height: Math.min(\n 300,\n Math.max(100, 46 + labelLines * 18 + descriptionLines * 15 + anchorHeight),\n ),\n };\n }\n\n if (element.type === \"DecisionNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 26));\n const conditionLines = estimateNodeTextLines(element.props.condition, 34);\n const descriptionLines = estimateNodeTextLines(element.props.description, 34);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 250,\n height: Math.min(\n 360,\n Math.max(\n 122,\n 50 + labelLines * 18 + conditionLines * 16 + descriptionLines * 15 + anchorHeight,\n ),\n ),\n };\n }\n\n if (element.type === \"PayloadNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 32));\n const descriptionLines = estimateNodeTextLines(element.props.description, 34);\n const beforeLines = estimateNodeTextLines(element.props.before, 40);\n const afterLines = estimateNodeTextLines(element.props.after, 40);\n const payloadLines = estimateNodeTextLines(element.props.payload, 40);\n const bodyLines = Math.max(payloadLines, beforeLines + afterLines);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 300,\n height: Math.min(\n 540,\n Math.max(160, 60 + labelLines * 18 + descriptionLines * 14 + bodyLines * 10 + anchorHeight),\n ),\n };\n }\n\n if (element.type === \"ErrorNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 30));\n const messageLines = Math.max(1, estimateNodeTextLines(element.props.message, 34));\n const causeLines = estimateNodeTextLines(element.props.cause, 34);\n const mitigationLines = estimateNodeTextLines(element.props.mitigation, 34);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 280,\n height: Math.min(\n 440,\n Math.max(\n 140,\n 58 +\n labelLines * 18 +\n messageLines * 16 +\n causeLines * 15 +\n mitigationLines * 15 +\n anchorHeight,\n ),\n ),\n };\n }\n\n if (element.type === \"DescriptionNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 26));\n const bodyLines = Math.max(1, estimateNodeTextLines(element.props.body, 30));\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 240,\n height: Math.min(360, Math.max(118, 44 + labelLines * 18 + bodyLines * 16 + anchorHeight)),\n };\n }\n\n if (element.type === \"LinkNode\") {\n const labelLines = Math.max(1, estimateNodeTextLines(element.props.label, 24));\n const descriptionLines = estimateNodeTextLines(element.props.description, 30);\n const anchorHeight = resolveNodeSourceAnchor(element.props) ? 18 : 0;\n\n return {\n width: 220,\n height: Math.min(\n 300,\n Math.max(98, 42 + labelLines * 18 + descriptionLines * 15 + anchorHeight),\n ),\n };\n }\n\n return {\n width: 240,\n height: 120,\n };\n}\n\nconst selectedBranchByNode = ref<Record<string, string>>({});\nconst pathFrames = ref<TimelineFrame[]>([]);\n\nfunction createFramesForNode(nodeKey: string): TimelineFrame[] {\n const node = orderedNodeByKey.value[nodeKey];\n if (!node) return [];\n\n const totalLocalSteps = getNodeFrameCount(node.element);\n\n return Array.from({ length: totalLocalSteps }, (_, localStep) => ({\n nodeIndex: node.index,\n nodeKey,\n localStep,\n totalLocalSteps,\n }));\n}\n\nfunction resolveNextNode(nodeKey: string, options: string[]) {\n const selected = selectedBranchByNode.value[nodeKey];\n if (selected && options.includes(selected)) {\n return selected;\n }\n\n return options[0];\n}\n\nfunction buildGuidedPath(startKey: string, maxFrames = 450): TimelineFrame[] {\n const frames: TimelineFrame[] = [];\n const visitedEdges = new Map<string, number>();\n let currentKey: string | undefined = startKey;\n\n while (currentKey && frames.length < maxFrames) {\n const nodeFrames = createFramesForNode(currentKey);\n if (nodeFrames.length === 0) break;\n\n frames.push(...nodeFrames);\n\n const options = outgoingNodeKeys.value[currentKey] ?? [];\n if (options.length === 0) break;\n\n const nextKey = resolveNextNode(currentKey, options);\n if (!nextKey) break;\n\n const edgeKey = `${currentKey}->${nextKey}`;\n const edgeVisits = (visitedEdges.get(edgeKey) ?? 0) + 1;\n visitedEdges.set(edgeKey, edgeVisits);\n if (edgeVisits > 2) break;\n\n currentKey = nextKey;\n }\n\n return frames;\n}\n\nfunction findNearestFrameIndex(frames: TimelineFrame[], nodeKey: string, anchor = 0) {\n let bestIndex = -1;\n let bestDistance = Number.POSITIVE_INFINITY;\n\n for (let index = 0; index < frames.length; index += 1) {\n if (frames[index]?.nodeKey !== nodeKey) continue;\n\n const distance = Math.abs(index - anchor);\n if (distance < bestDistance) {\n bestDistance = distance;\n bestIndex = index;\n }\n }\n\n return bestIndex;\n}\n\nfunction sortOptionsForTraversal(sourceKey: string, options: string[]) {\n const selected = selectedBranchByNode.value[sourceKey];\n\n return [...options].sort((a, b) => {\n const aSelected = a === selected;\n const bSelected = b === selected;\n\n if (aSelected !== bSelected) {\n return aSelected ? -1 : 1;\n }\n\n const aIndex = orderedNodeByKey.value[a]?.index ?? Number.MAX_SAFE_INTEGER;\n const bIndex = orderedNodeByKey.value[b]?.index ?? Number.MAX_SAFE_INTEGER;\n\n return aIndex - bIndex;\n });\n}\n\nfunction findPathKeysToNode(startKey: string, targetKey: string) {\n if (startKey === targetKey) {\n return [startKey];\n }\n\n const queue: Array<{ key: string; path: string[]; depth: number }> = [\n {\n key: startKey,\n path: [startKey],\n depth: 0,\n },\n ];\n\n const visitedDepth = new Map<string, number>([[startKey, 0]]);\n const maxDepth = Math.max(8, orderedNodeElements.value.length + 8);\n const maxIterations = Math.max(\n 80,\n orderedNodeElements.value.length * orderedNodeElements.value.length * 2,\n );\n let guard = 0;\n\n while (queue.length > 0 && guard < maxIterations) {\n guard += 1;\n\n const current = queue.shift();\n if (!current) continue;\n if (current.depth >= maxDepth) continue;\n\n const options = sortOptionsForTraversal(current.key, outgoingNodeKeys.value[current.key] ?? []);\n\n for (const option of options) {\n if (!orderedNodeByKey.value[option]) continue;\n\n const nextDepth = current.depth + 1;\n if (option === targetKey) {\n return [...current.path, option];\n }\n\n const knownDepth = visitedDepth.get(option);\n if (knownDepth !== undefined && knownDepth <= nextDepth) {\n continue;\n }\n\n visitedDepth.set(option, nextDepth);\n queue.push({\n key: option,\n path: [...current.path, option],\n depth: nextDepth,\n });\n }\n }\n\n return null;\n}\n\nfunction applyBranchSelectionsForPath(pathKeys: string[]) {\n if (pathKeys.length < 2) return;\n\n const nextSelected = { ...selectedBranchByNode.value };\n\n for (let index = 0; index < pathKeys.length - 1; index += 1) {\n const source = pathKeys[index];\n const target = pathKeys[index + 1];\n if (!source || !target) continue;\n\n const options = outgoingNodeKeys.value[source] ?? [];\n if (options.length > 1 && options.includes(target)) {\n nextSelected[source] = target;\n }\n }\n\n selectedBranchByNode.value = nextSelected;\n}\n\nconst totalSteps = computed(() => pathFrames.value.length);\nconst maxStepIndex = computed(() => Math.max(0, totalSteps.value - 1));\n\nconst { set } = useStateStore();\nconst currentStepState = useStateValue<number>(\"/currentStep\");\nconst playingState = useStateValue<boolean>(\"/playing\");\n\nfunction clampStep(value: number) {\n if (!Number.isFinite(value)) return 0;\n const step = Math.floor(value);\n return Math.max(0, Math.min(step, maxStepIndex.value));\n}\n\nconst currentStep = computed<number>({\n get() {\n return clampStep(Number(currentStepState.value ?? 0));\n },\n set(value: number) {\n set(\"/currentStep\", clampStep(value));\n },\n});\n\nconst playing = computed<boolean>({\n get() {\n return Boolean(playingState.value ?? false);\n },\n set(value: boolean) {\n set(\"/playing\", value);\n },\n});\n\nwatch(\n [startNodeKey, orderedNodeElements, isArchitectureMode],\n ([start, , architectureMode]) => {\n if (architectureMode) {\n selectedBranchByNode.value = {};\n pathFrames.value = [];\n currentStep.value = 0;\n playing.value = false;\n return;\n }\n\n selectedBranchByNode.value = {};\n\n if (!start) {\n pathFrames.value = [];\n currentStep.value = 0;\n return;\n }\n\n const built = buildGuidedPath(start);\n pathFrames.value = built.length > 0 ? built : createFramesForNode(start);\n currentStep.value = clampStep(Number(currentStepState.value ?? 0));\n },\n { immediate: true },\n);\n\nwatch(totalSteps, () => {\n currentStep.value = clampStep(currentStep.value);\n});\n\nconst intervalMs = computed(() => {\n const value = Number(runtime.interval.value);\n if (!Number.isFinite(value) || value <= 0) return 3000;\n return Math.max(250, Math.floor(value));\n});\n\nlet timer: ReturnType<typeof setInterval> | null = null;\n\nfunction clearTimer() {\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n}\n\nfunction pauseNarrativePlayback() {\n if (!isArchitectureMode.value) {\n playing.value = false;\n }\n}\n\nfunction next(manual = true) {\n if (isArchitectureMode.value) {\n return false;\n }\n\n if (manual) {\n pauseNarrativePlayback();\n }\n\n if (currentStep.value >= totalSteps.value - 1) {\n return false;\n }\n\n currentStep.value += 1;\n return true;\n}\n\nwatch(\n [playing, totalSteps, intervalMs],\n ([isPlaying, steps, interval]) => {\n clearTimer();\n\n if (!isPlaying || steps <= 1) return;\n\n timer = setInterval(() => {\n const advanced = next(false);\n if (!advanced) {\n playing.value = false;\n }\n }, interval);\n },\n { immediate: true },\n);\n\nfunction prev(manual = true) {\n if (isArchitectureMode.value) {\n return;\n }\n\n if (manual) {\n pauseNarrativePlayback();\n }\n\n if (currentStep.value > 0) {\n currentStep.value -= 1;\n }\n}\n\nfunction goTo(step: number, manual = true) {\n if (isArchitectureMode.value) {\n return;\n }\n\n if (manual) {\n pauseNarrativePlayback();\n }\n\n currentStep.value = clampStep(step);\n}\n\nfunction togglePlay() {\n if (isArchitectureMode.value) {\n playing.value = false;\n return;\n }\n\n if (totalSteps.value <= 1) {\n playing.value = false;\n return;\n }\n\n playing.value = !playing.value;\n}\n\nconst activeFrame = computed(() => pathFrames.value[currentStep.value]);\nconst nextPlannedNodeKey = computed(() => pathFrames.value[currentStep.value + 1]?.nodeKey);\n\nfunction jumpToNode(nodeKey: string) {\n if (!orderedNodeByKey.value[nodeKey]) return;\n\n playing.value = false;\n\n const existingIndex = findNearestFrameIndex(pathFrames.value, nodeKey, currentStep.value);\n if (existingIndex >= 0) {\n currentStep.value = existingIndex;\n return;\n }\n\n const start = startNodeKey.value;\n if (!start) {\n const standaloneFrames = createFramesForNode(nodeKey);\n if (standaloneFrames.length === 0) return;\n\n pathFrames.value = standaloneFrames;\n currentStep.value = 0;\n return;\n }\n\n const pathKeys = findPathKeysToNode(start, nodeKey);\n if (pathKeys) {\n applyBranchSelectionsForPath(pathKeys);\n }\n\n const rebuiltFrames = buildGuidedPath(start);\n pathFrames.value = rebuiltFrames.length > 0 ? rebuiltFrames : createFramesForNode(start);\n\n const rebuiltIndex = findNearestFrameIndex(pathFrames.value, nodeKey, currentStep.value);\n if (rebuiltIndex >= 0) {\n currentStep.value = rebuiltIndex;\n return;\n }\n\n const standaloneFrames = createFramesForNode(nodeKey);\n if (standaloneFrames.length === 0) return;\n\n pathFrames.value = standaloneFrames;\n currentStep.value = 0;\n}\n\nconst resolvedLayoutEngine = computed<\"dagre\" | \"manual\">(() => {\n return props.layoutEngine === \"manual\" ? \"manual\" : DEFAULT_LAYOUT_ENGINE;\n});\n\nconst resolvedLayoutRankSep = computed(() => {\n const fallback =\n props.direction === \"vertical\"\n ? DEFAULT_DAGRE_RANK_SEP_VERTICAL\n : DEFAULT_DAGRE_RANK_SEP_HORIZONTAL;\n\n return toPositiveNumber(props.layoutRankSep, fallback, 80);\n});\n\nconst resolvedLayoutNodeSep = computed(() => {\n const fallback =\n props.direction === \"vertical\"\n ? DEFAULT_DAGRE_NODE_SEP_VERTICAL\n : DEFAULT_DAGRE_NODE_SEP_HORIZONTAL;\n\n return toPositiveNumber(props.layoutNodeSep, fallback, 40);\n});\n\nconst resolvedLayoutEdgeSep = computed(() => {\n return toPositiveNumber(props.layoutEdgeSep, DEFAULT_DAGRE_EDGE_SEP, 8);\n});\n\nfunction createFallbackLayoutPositions(\n nodes: OrderedNodeElement[],\n rankGap = DEFAULT_FALLBACK_GAP,\n) {\n const mainGap = Math.max(80, rankGap);\n const positions: Record<string, { x: number; y: number }> = {};\n\n for (const node of nodes) {\n if (props.direction === \"vertical\") {\n positions[node.key] = { x: 0, y: node.index * mainGap };\n continue;\n }\n\n positions[node.key] = { x: node.index * mainGap, y: 0 };\n }\n\n return positions;\n}\n\nfunction normalizePositions(positions: Record<string, { x: number; y: number }>) {\n if (Object.keys(positions).length === 0) {\n return positions;\n }\n\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n\n for (const position of Object.values(positions)) {\n minX = Math.min(minX, position.x);\n minY = Math.min(minY, position.y);\n }\n\n for (const key of Object.keys(positions)) {\n const currentPosition = positions[key];\n if (!currentPosition) continue;\n\n positions[key] = {\n x: currentPosition.x - minX,\n y: currentPosition.y - minY,\n };\n }\n\n return positions;\n}\n\nfunction createManualLayoutPositions(\n orderedNodes: OrderedNodeElement[],\n rankGap: number,\n laneGap: number,\n) {\n if (orderedNodes.length === 0) return {};\n\n const depthByKey: Record<string, number> = {};\n for (const node of orderedNodes) {\n depthByKey[node.key] = Number.NEGATIVE_INFINITY;\n }\n\n const startKey = startNodeKey.value ?? orderedNodes[0]?.key;\n if (!startKey) {\n return createFallbackLayoutPositions(orderedNodes, rankGap);\n }\n\n depthByKey[startKey] = 0;\n\n const queue: string[] = [startKey];\n const maxDepth = Math.max(0, orderedNodes.length - 1);\n let guard = 0;\n const maxIterations = Math.max(24, orderedNodes.length * orderedNodes.length);\n\n while (queue.length > 0 && guard < maxIterations) {\n guard += 1;\n\n const key = queue.shift();\n if (!key) continue;\n\n const baseDepth = depthByKey[key] ?? Number.NEGATIVE_INFINITY;\n if (!Number.isFinite(baseDepth)) continue;\n\n for (const target of outgoingNodeKeys.value[key] ?? []) {\n if (!(target in depthByKey)) continue;\n\n const candidateDepth = Math.min(maxDepth, baseDepth + 1);\n const currentDepth = depthByKey[target] ?? Number.NEGATIVE_INFINITY;\n\n if (candidateDepth > currentDepth) {\n depthByKey[target] = candidateDepth;\n queue.push(target);\n }\n }\n }\n\n let fallbackDepth = 0;\n for (const node of orderedNodes) {\n if (Number.isFinite(depthByKey[node.key])) continue;\n\n depthByKey[node.key] = Math.min(maxDepth, fallbackDepth);\n fallbackDepth += 1;\n }\n\n const layers: Record<number, string[]> = {};\n for (const node of orderedNodes) {\n const depth = depthByKey[node.key] ?? 0;\n if (!layers[depth]) {\n layers[depth] = [];\n }\n\n layers[depth].push(node.key);\n }\n\n const laneByKey: Record<string, number> = {};\n const sortedDepths = Object.keys(layers)\n .map(Number)\n .sort((a, b) => a - b);\n\n for (const depth of sortedDepths) {\n const layerKeys = [...(layers[depth] ?? [])];\n\n layerKeys.sort((a, b) => {\n const aParents = (incomingNodeKeys.value[a] ?? []).filter((parent) => {\n const parentDepth = depthByKey[parent] ?? Number.NEGATIVE_INFINITY;\n return Number.isFinite(parentDepth) && parentDepth < depth;\n });\n const bParents = (incomingNodeKeys.value[b] ?? []).filter((parent) => {\n const parentDepth = depthByKey[parent] ?? Number.NEGATIVE_INFINITY;\n return Number.isFinite(parentDepth) && parentDepth < depth;\n });\n\n const aAnchor =\n aParents.length > 0\n ? aParents.reduce((sum, parent) => sum + (laneByKey[parent] ?? 0), 0) / aParents.length\n : 0;\n const bAnchor =\n bParents.length > 0\n ? bParents.reduce((sum, parent) => sum + (laneByKey[parent] ?? 0), 0) / bParents.length\n : 0;\n\n if (aAnchor === bAnchor) {\n const aIndex = orderedNodeByKey.value[a]?.index ?? 0;\n const bIndex = orderedNodeByKey.value[b]?.index ?? 0;\n return aIndex - bIndex;\n }\n\n return aAnchor - bAnchor;\n });\n\n const count = layerKeys.length;\n layerKeys.forEach((key, index) => {\n laneByKey[key] = (index - (count - 1) / 2) * laneGap;\n });\n }\n\n const positions: Record<string, { x: number; y: number }> = {};\n\n for (const node of orderedNodes) {\n const depth = depthByKey[node.key] ?? 0;\n const lane = laneByKey[node.key] ?? 0;\n\n if (props.direction === \"vertical\") {\n positions[node.key] = {\n x: Math.round(lane),\n y: Math.round(depth * rankGap),\n };\n continue;\n }\n\n positions[node.key] = {\n x: Math.round(depth * rankGap),\n y: Math.round(lane),\n };\n }\n\n return normalizePositions(positions);\n}\n\nconst nodeSizes = computed<Record<string, NodeSize>>(() => {\n const sizes: Record<string, NodeSize> = {};\n\n for (const node of orderedNodeElements.value) {\n sizes[node.key] = estimateNodeSize(node);\n }\n\n return sizes;\n});\n\nconst architectureZoneDefinitions = computed<ResolvedArchitectureZone[]>(() => {\n if (!isArchitectureMode.value) {\n return [];\n }\n\n const rootZones = toArchitectureZones(props.zones ?? rootElement.value?.props.zones);\n const byId = new Map<string, ResolvedArchitectureZone>();\n\n for (const zone of rootZones) {\n byId.set(zone.id, zone);\n }\n\n for (const node of orderedNodeElements.value) {\n const zoneId = toArchitectureZoneId(node.element.props.zone);\n if (!zoneId || byId.has(zoneId)) {\n continue;\n }\n\n byId.set(zoneId, {\n id: zoneId,\n label: humanizeZoneId(zoneId),\n padding: 62,\n });\n }\n\n return Array.from(byId.values());\n});\n\nconst architectureZoneLabelById = computed<Record<string, string>>(() => {\n const map: Record<string, string> = {};\n\n for (const zone of architectureZoneDefinitions.value) {\n map[zone.id] = zone.label;\n }\n\n return map;\n});\n\nconst architectureNodeZoneByKey = computed<Record<string, string>>(() => {\n const map: Record<string, string> = {};\n\n for (const node of orderedNodeElements.value) {\n const zoneId = toArchitectureZoneId(node.element.props.zone);\n if (!zoneId) {\n continue;\n }\n\n map[node.key] = zoneId;\n }\n\n return map;\n});\n\nconst architectureZoneOverlays = computed<ArchitectureZoneOverlay[]>(() => {\n if (!isArchitectureMode.value) {\n return [];\n }\n\n const rawOverlays: Array<{\n id: string;\n label: string;\n description?: string;\n color: string;\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n padding: number;\n nodeCount: number;\n sourceIndex: number;\n }> = [];\n\n architectureZoneDefinitions.value.forEach((zone, index) => {\n const members = orderedNodeElements.value.filter(\n (node) => architectureNodeZoneByKey.value[node.key] === zone.id,\n );\n if (members.length === 0) {\n return;\n }\n\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n\n for (const member of members) {\n const position = layoutPositions.value[member.key];\n if (!position) {\n continue;\n }\n\n const size = nodeSizes.value[member.key] ?? { width: 240, height: 120 };\n\n minX = Math.min(minX, position.x);\n minY = Math.min(minY, position.y);\n maxX = Math.max(maxX, position.x + size.width);\n maxY = Math.max(maxY, position.y + size.height);\n }\n\n if (\n !Number.isFinite(minX) ||\n !Number.isFinite(minY) ||\n !Number.isFinite(maxX) ||\n !Number.isFinite(maxY)\n ) {\n return;\n }\n\n const padding = zone.padding;\n rawOverlays.push({\n id: zone.id,\n label: zone.label,\n description: zone.description,\n color: resolveZoneColor(index, zone.color),\n minX,\n minY,\n maxX,\n maxY,\n padding,\n nodeCount: members.length,\n sourceIndex: index,\n });\n });\n\n const provisionalBounds = rawOverlays.map((overlay) => ({\n id: overlay.id,\n x: overlay.minX - overlay.padding,\n y: overlay.minY - overlay.padding,\n width: overlay.maxX - overlay.minX + overlay.padding * 2,\n height: overlay.maxY - overlay.minY + overlay.padding * 2,\n }));\n\n const nestingDepthById = new Map<string, number>();\n const containsNestedZoneById = new Map<string, boolean>();\n\n for (const current of provisionalBounds) {\n const depth = provisionalBounds.reduce((count, candidate) => {\n if (candidate.id === current.id) {\n return count;\n }\n\n const containsCurrent =\n candidate.x <= current.x + 12 &&\n candidate.y <= current.y + 12 &&\n candidate.x + candidate.width >= current.x + current.width - 12 &&\n candidate.y + candidate.height >= current.y + current.height - 12;\n\n return containsCurrent ? count + 1 : count;\n }, 0);\n\n nestingDepthById.set(current.id, depth);\n containsNestedZoneById.set(\n current.id,\n provisionalBounds.some((candidate) => {\n if (candidate.id === current.id) {\n return false;\n }\n\n return (\n current.x <= candidate.x + 12 &&\n current.y <= candidate.y + 12 &&\n current.x + current.width >= candidate.x + candidate.width - 12 &&\n current.y + current.height >= candidate.y + candidate.height - 12\n );\n }),\n );\n }\n\n const overlappingZoneIds = new Set<string>();\n for (let index = 0; index < provisionalBounds.length; index += 1) {\n const current = provisionalBounds[index];\n if (!current) {\n continue;\n }\n\n for (let compareIndex = index + 1; compareIndex < provisionalBounds.length; compareIndex += 1) {\n const candidate = provisionalBounds[compareIndex];\n if (!candidate) {\n continue;\n }\n\n const overlaps =\n current.x < candidate.x + candidate.width &&\n current.x + current.width > candidate.x &&\n current.y < candidate.y + candidate.height &&\n current.y + current.height > candidate.y;\n\n if (!overlaps) {\n continue;\n }\n\n overlappingZoneIds.add(current.id);\n overlappingZoneIds.add(candidate.id);\n }\n }\n\n const labelLaneById = new Map<string, number>();\n const placedLabelBoxes: Array<{\n id: string;\n lane: number;\n x: number;\n y: number;\n width: number;\n height: number;\n }> = [];\n const sortedForLabelPlacement = rawOverlays\n .map((overlay) => {\n const sidePadding = Math.max(overlay.padding, ARCHITECTURE_ZONE_MIN_CONTENT_PADDING);\n const descriptionReserve = overlay.description\n ? ARCHITECTURE_ZONE_DESCRIPTION_HEIGHT + ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP\n : 0;\n const topPadding =\n sidePadding +\n ARCHITECTURE_ZONE_LABEL_HEIGHT +\n ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP +\n descriptionReserve;\n const width = Math.min(\n Math.max(132, overlay.label.length * 7 + String(overlay.nodeCount).length * 14 + 86),\n Math.max(148, overlay.maxX - overlay.minX + sidePadding * 2 - 28),\n );\n\n return {\n id: overlay.id,\n x: overlay.minX - sidePadding + 16,\n y: overlay.minY - topPadding + ARCHITECTURE_ZONE_LABEL_TOP,\n width,\n };\n })\n .sort((a, b) => {\n if (a.y !== b.y) {\n return a.y - b.y;\n }\n\n return a.x - b.x;\n });\n\n for (const labelCandidate of sortedForLabelPlacement) {\n let lane = 0;\n\n while (\n placedLabelBoxes.some((placed) => {\n if (placed.lane !== lane) {\n return false;\n }\n\n const currentY = labelCandidate.y + lane * ARCHITECTURE_ZONE_NESTED_LABEL_STEP;\n return (\n labelCandidate.x < placed.x + placed.width &&\n labelCandidate.x + labelCandidate.width > placed.x &&\n currentY < placed.y + placed.height &&\n currentY + ARCHITECTURE_ZONE_LABEL_HEIGHT > placed.y\n );\n })\n ) {\n lane += 1;\n }\n\n labelLaneById.set(labelCandidate.id, lane);\n placedLabelBoxes.push({\n id: labelCandidate.id,\n lane,\n x: labelCandidate.x,\n y: labelCandidate.y + lane * ARCHITECTURE_ZONE_NESTED_LABEL_STEP,\n width: labelCandidate.width,\n height: ARCHITECTURE_ZONE_LABEL_HEIGHT,\n });\n }\n\n const maxLabelLane = placedLabelBoxes.reduce((max, placed) => Math.max(max, placed.lane), 0);\n\n return rawOverlays\n .map((overlay) => {\n const nestingDepth = nestingDepthById.get(overlay.id) ?? 0;\n const nestedZoneGap = containsNestedZoneById.get(overlay.id)\n ? ARCHITECTURE_ZONE_CONTAINED_ZONE_GAP\n : 0;\n const baseSidePadding = Math.max(overlay.padding, ARCHITECTURE_ZONE_MIN_CONTENT_PADDING);\n const sidePadding = baseSidePadding + nestedZoneGap;\n const bottomPadding =\n Math.max(baseSidePadding, ARCHITECTURE_ZONE_MIN_BOTTOM_PADDING) + nestedZoneGap;\n const labelLane = labelLaneById.get(overlay.id) ?? 0;\n const labelOffsetY =\n ARCHITECTURE_ZONE_LABEL_TOP + labelLane * ARCHITECTURE_ZONE_NESTED_LABEL_STEP;\n const showDescription = Boolean(overlay.description) && !overlappingZoneIds.has(overlay.id);\n const descriptionOffsetY =\n labelOffsetY + ARCHITECTURE_ZONE_LABEL_HEIGHT + ARCHITECTURE_ZONE_LABEL_TO_DESCRIPTION_GAP;\n const descriptionReserve = showDescription\n ? ARCHITECTURE_ZONE_DESCRIPTION_HEIGHT + ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP\n : 0;\n const topPadding =\n sidePadding +\n ARCHITECTURE_ZONE_LABEL_HEIGHT +\n ARCHITECTURE_ZONE_LABEL_TO_CONTENT_GAP +\n descriptionReserve +\n maxLabelLane * ARCHITECTURE_ZONE_NESTED_LABEL_STEP;\n\n return {\n id: overlay.id,\n label: overlay.label,\n description: showDescription ? overlay.description : undefined,\n color: overlay.color,\n x: Math.round(overlay.minX - sidePadding),\n y: Math.round(overlay.minY - topPadding),\n width: Math.max(120, Math.round(overlay.maxX - overlay.minX + sidePadding * 2)),\n height: Math.max(100, Math.round(overlay.maxY - overlay.minY + topPadding + bottomPadding)),\n nodeCount: overlay.nodeCount,\n nestingDepth,\n labelLane,\n labelOffsetY,\n descriptionOffsetY,\n sourceIndex: overlay.sourceIndex,\n };\n })\n .sort((a, b) => {\n const areaDiff = b.width * b.height - a.width * a.height;\n if (areaDiff !== 0) {\n return areaDiff;\n }\n\n return a.sourceIndex - b.sourceIndex;\n })\n .map(({ sourceIndex: _sourceIndex, ...overlay }) => overlay);\n});\n\nfunction architectureZoneCardStyle(zone: ArchitectureZoneOverlay) {\n return {\n left: `${zone.x}px`,\n top: `${zone.y}px`,\n width: `${zone.width}px`,\n height: `${zone.height}px`,\n borderColor: withAlpha(zone.color, 0.38),\n background: `linear-gradient(180deg, ${withAlpha(zone.color, 0.1)} 0%, ${withAlpha(zone.color, 0.045)} 62%, ${withAlpha(zone.color, 0.03)} 100%)`,\n boxShadow: `inset 0 0 0 1px ${withAlpha(zone.color, 0.1)}`,\n };\n}\n\nfunction architectureZoneLabelStyle(zone: ArchitectureZoneOverlay) {\n return {\n top: `${zone.labelOffsetY}px`,\n borderColor: withAlpha(zone.color, 0.55),\n background: withAlpha(zone.color, 0.18),\n color: zone.color,\n };\n}\n\nfunction architectureZoneDescriptionStyle(zone: ArchitectureZoneOverlay) {\n return {\n top: `${zone.descriptionOffsetY}px`,\n };\n}\n\nconst layoutPositions = computed<Record<string, { x: number; y: number }>>(() => {\n const orderedNodes = orderedNodeElements.value;\n if (orderedNodes.length === 0) return {};\n\n const rankGap = resolvedLayoutRankSep.value;\n const nodeGap = resolvedLayoutNodeSep.value;\n const edgeGap = resolvedLayoutEdgeSep.value;\n const fallback = createFallbackLayoutPositions(orderedNodes, rankGap);\n\n if (resolvedLayoutEngine.value === \"manual\") {\n return createManualLayoutPositions(orderedNodes, rankGap, nodeGap);\n }\n\n const graph = new dagre.graphlib.Graph();\n graph.setDefaultEdgeLabel(() => ({}));\n graph.setGraph({\n rankdir: props.direction === \"vertical\" ? \"TB\" : \"LR\",\n ranker: \"network-simplex\",\n acyclicer: \"greedy\",\n align: \"UL\",\n marginx: 36,\n marginy: 36,\n ranksep: rankGap,\n nodesep: nodeGap,\n edgesep: edgeGap,\n });\n\n for (const node of orderedNodes) {\n const size = nodeSizes.value[node.key] ?? { width: 240, height: 120 };\n\n graph.setNode(node.key, {\n width: size.width,\n height: size.height,\n });\n }\n\n for (const node of orderedNodes) {\n const targets = outgoingNodeKeys.value[node.key] ?? [];\n const preferredTarget = resolveNextNode(node.key, targets);\n\n for (const target of targets) {\n if (!orderedNodeByKey.value[target]) continue;\n\n graph.setEdge(node.key, target, {\n minlen: 1,\n weight: target === preferredTarget ? 3 : 1,\n });\n }\n }\n\n try {\n dagre.layout(graph);\n } catch {\n return fallback;\n }\n\n const positions: Record<string, { x: number; y: number }> = {};\n\n for (const node of orderedNodes) {\n const layoutNode = graph.node(node.key);\n if (!layoutNode || typeof layoutNode.x !== \"number\" || typeof layoutNode.y !== \"number\") {\n continue;\n }\n\n const size = nodeSizes.value[node.key] ?? { width: 240, height: 120 };\n\n positions[node.key] = {\n x: Math.round(layoutNode.x - size.width / 2),\n y: Math.round(layoutNode.y - size.height / 2),\n };\n }\n\n if (Object.keys(positions).length === 0) {\n return fallback;\n }\n\n return normalizePositions(positions);\n});\n\nconst nodes = computed<FlowNode[]>(() => {\n const fallbackPositions = createFallbackLayoutPositions(\n orderedNodeElements.value,\n resolvedLayoutRankSep.value,\n );\n\n return orderedNodeElements.value.map(({ key, nodeType, element, index }) => ({\n id: key,\n type: nodeType,\n targetPosition: Position.Left,\n sourcePosition: Position.Right,\n position:\n layoutPositions.value[key] ??\n fallbackPositions[key] ??\n (props.direction === \"vertical\"\n ? { x: 0, y: index * DEFAULT_FALLBACK_GAP }\n : { x: index * DEFAULT_FALLBACK_GAP, y: 0 }),\n data: {\n key,\n type: nodeType,\n elementType: element.type,\n props: element.props,\n active: isActive(key),\n sourceAnchor: resolveNodeSourceAnchor(element.props),\n index,\n },\n }));\n});\n\nconst edges = computed<FlowEdge[]>(() => {\n const result: FlowEdge[] = [];\n\n for (const node of orderedNodeElements.value) {\n const targets = outgoingNodeKeys.value[node.key] ?? [];\n\n for (const target of targets) {\n if (!orderedNodeByKey.value[target]) continue;\n\n const isActiveEdge =\n !isArchitectureMode.value &&\n activeFrame.value?.nodeKey === node.key &&\n nextPlannedNodeKey.value === target;\n const transition = transitionMetaBySource.value[node.key]?.[target];\n const edgeClasses = [\n isActiveEdge ? \"active-edge\" : null,\n transition?.kind ? `edge-kind-${transition.kind}` : null,\n ].filter((value): value is string => Boolean(value));\n\n const edgeLabel = resolveTransitionEdgeLabel(transition);\n const hasLabel = Boolean(edgeLabel);\n\n result.push({\n id: `e-${node.key}-${target}`,\n source: node.key,\n target,\n type: isArchitectureMode.value ? \"architecture\" : \"smoothstep\",\n animated: !isArchitectureMode.value,\n class: edgeClasses.length > 0 ? edgeClasses.join(\" \") : undefined,\n label: edgeLabel,\n labelShowBg: hasLabel && !isArchitectureMode.value,\n labelBgPadding: hasLabel && !isArchitectureMode.value ? [6, 3] : undefined,\n labelBgBorderRadius: hasLabel && !isArchitectureMode.value ? 6 : undefined,\n labelBgStyle:\n hasLabel && !isArchitectureMode.value\n ? { fill: \"var(--color-card)\", fillOpacity: 0.985, stroke: \"var(--color-border)\" }\n : undefined,\n labelStyle:\n hasLabel && !isArchitectureMode.value\n ? {\n fill: \"var(--color-foreground)\",\n fontSize: \"10px\",\n fontWeight: 600,\n }\n : undefined,\n });\n }\n }\n\n return result;\n});\n\nconst diagramBounds = computed(() => {\n if (nodes.value.length === 0) {\n return null;\n }\n\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n\n for (const node of nodes.value) {\n const size = nodeSizes.value[node.id] ?? { width: 240, height: 120 };\n minX = Math.min(minX, node.position.x);\n minY = Math.min(minY, node.position.y);\n maxX = Math.max(maxX, node.position.x + size.width);\n maxY = Math.max(maxY, node.position.y + size.height);\n }\n\n for (const zone of architectureZoneOverlays.value) {\n minX = Math.min(minX, zone.x);\n minY = Math.min(minY, zone.y);\n maxX = Math.max(maxX, zone.x + zone.width);\n maxY = Math.max(maxY, zone.y + zone.height);\n }\n\n if (\n !Number.isFinite(minX) ||\n !Number.isFinite(minY) ||\n !Number.isFinite(maxX) ||\n !Number.isFinite(maxY)\n ) {\n return null;\n }\n\n return {\n x: Math.floor(minX),\n y: Math.floor(minY),\n width: Math.max(1, Math.ceil(maxX - minX)),\n height: Math.max(1, Math.ceil(maxY - minY)),\n };\n});\n\nfunction createExportFileBaseName() {\n const rawName = activeFlow.value?.id ?? overlayTitle.value ?? props.title ?? \"flow-diagram\";\n\n const slug = rawName\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n return slug || \"flow-diagram\";\n}\n\nasync function exportDiagram(format: DiagramExportFormat) {\n if (exportInFlight.value) return;\n if (!canExportDiagram.value) return;\n\n const flowElement = sceneRef.value;\n const bounds = diagramBounds.value;\n\n if (!flowElement || !bounds) {\n exportError.value = \"Diagram is still initializing. Try again in a moment.\";\n return;\n }\n\n exportError.value = null;\n exportMenuOpen.value = false;\n exportInFlight.value = format;\n\n try {\n await exportFlowDiagram({\n flowElement,\n theme: uiTheme.value,\n bounds,\n fileNameBase: createExportFileBaseName(),\n format,\n });\n } catch (error) {\n exportError.value =\n error instanceof Error ? error.message : `Failed to export ${format.toUpperCase()} diagram.`;\n } finally {\n exportInFlight.value = null;\n }\n}\n\nfunction isActive(nodeKey: string) {\n if (isArchitectureMode.value) {\n return true;\n }\n\n return activeFrame.value?.nodeKey === nodeKey;\n}\n\nfunction codeStepIndex(nodeKey: string) {\n if (activeFrame.value?.nodeKey !== nodeKey) {\n return 0;\n }\n\n return activeFrame.value.localStep;\n}\n\nconst activeNode = computed(() => {\n const key = activeFrame.value?.nodeKey;\n if (!key) return undefined;\n return orderedNodeByKey.value[key];\n});\n\nconst activeLocalStep = computed(() => activeFrame.value?.localStep ?? 0);\n\nconst activeLabel = computed(() => {\n const node = activeNode.value;\n if (!node) return \"\";\n\n const base = toOptionalString(node.element.props.label) ?? \"\";\n\n if (node.element.type !== \"CodeNode\") {\n return base;\n }\n\n const steps = toMagicMoveSteps(node.element.props.magicMoveSteps);\n if (steps.length === 0) return base;\n\n const title = steps[Math.min(activeLocalStep.value, steps.length - 1)]?.title;\n return title ? `${base} - ${title}` : base;\n});\n\nconst activeDescription = computed(() => {\n const node = activeNode.value;\n if (!node) return \"\";\n\n if (node.element.type === \"CodeNode\") {\n const steps = toMagicMoveSteps(node.element.props.magicMoveSteps);\n const defaultStory =\n toOptionalString(node.element.props.story) ?? toOptionalString(node.element.props.comment);\n\n if (steps.length > 0) {\n const beat = steps[Math.min(activeLocalStep.value, steps.length - 1)];\n\n return beat?.story ?? beat?.comment ?? defaultStory ?? \"\";\n }\n\n return defaultStory ?? \"\";\n }\n\n return getNodeSummary(node);\n});\n\nconst activeSourceAnchor = computed(() => {\n const node = activeNode.value;\n if (!node) return undefined;\n\n return resolveNodeSourceAnchor(node.element.props);\n});\n\nconst architectureSelectedNodeKey = ref<string | null>(null);\n\nconst architectureSelectedNode = computed(() => {\n if (!isArchitectureMode.value) {\n return undefined;\n }\n\n const selected = architectureSelectedNodeKey.value;\n if (selected && orderedNodeByKey.value[selected]) {\n return orderedNodeByKey.value[selected];\n }\n\n return orderedNodeElements.value[0];\n});\n\nwatch(\n [isArchitectureMode, orderedNodeElements],\n ([architectureMode, ordered]) => {\n if (!architectureMode) {\n architectureSelectedNodeKey.value = null;\n return;\n }\n\n const selected = architectureSelectedNodeKey.value;\n if (selected && ordered.some((node) => node.key === selected)) {\n return;\n }\n\n architectureSelectedNodeKey.value = ordered[0]?.key ?? null;\n },\n { immediate: true },\n);\n\nconst architectureInspector = computed<ArchitectureInspectorView | null>(() => {\n const node = architectureSelectedNode.value;\n if (!node) {\n return null;\n }\n\n const label = toTrimmedNonEmptyString(node.element.props.label) ?? node.key;\n const sourceAnchor = resolveNodeSourceAnchor(node.element.props);\n\n if (node.element.type !== \"ArchitectureNode\") {\n return {\n type: \"Other\",\n label,\n summary: getNodeSummary(node),\n sourceAnchor,\n elementType: node.element.type,\n };\n }\n\n const zoneId = toArchitectureZoneId(node.element.props.zone);\n const zoneLabel = zoneId\n ? (architectureZoneLabelById.value[zoneId] ?? humanizeZoneId(zoneId))\n : undefined;\n const interfaces = toArchitectureInterfaces(node.element.props.interfaces);\n const dataAssets = toArchitectureDataAssets(node.element.props.data);\n const security = toArchitectureSecurity(node.element.props.security);\n const operations = toArchitectureOperations(node.element.props.operations);\n const links = toArchitectureLinks(node.element.props.links);\n const outgoing: ArchitectureOutgoingEdge[] = [];\n\n for (const targetKey of outgoingNodeKeys.value[node.key] ?? []) {\n const targetNode = orderedNodeByKey.value[targetKey];\n if (!targetNode) {\n continue;\n }\n\n const transition = transitionMetaBySource.value[node.key]?.[targetKey];\n\n outgoing.push({\n target: toTrimmedNonEmptyString(targetNode.element.props.label) ?? targetKey,\n label: transition?.label,\n protocol: transition?.protocol,\n transport: transition?.transport,\n auth: transition?.auth,\n criticality: transition?.criticality,\n });\n }\n\n return {\n type: \"ArchitectureNode\",\n label,\n kind: toArchitectureKind(node.element.props.kind),\n status: toArchitectureStatus(node.element.props.status),\n tier: toArchitectureTier(node.element.props.tier),\n technology: toTrimmedNonEmptyString(node.element.props.technology),\n runtime: toTrimmedNonEmptyString(node.element.props.runtime),\n owner: toTrimmedNonEmptyString(node.element.props.owner),\n zoneLabel,\n summary: toTrimmedNonEmptyString(node.element.props.description) ?? \"\",\n tags: toStringArray(node.element.props.tags),\n responsibilities: toStringArray(node.element.props.responsibilities),\n capabilities: toStringArray(node.element.props.capabilities),\n interfaces,\n dataAssets,\n security,\n operations,\n links,\n outgoing,\n sourceAnchor,\n };\n});\n\nconst architectureInspectorNode = computed<ArchitectureInspectorArchitectureView | null>(() => {\n const inspector = architectureInspector.value;\n if (!inspector || inspector.type !== \"ArchitectureNode\") {\n return null;\n }\n\n return inspector;\n});\n\nconst architectureInspectorNodeSafe = computed(() => {\n return architectureInspectorNode.value ?? EMPTY_ARCHITECTURE_INSPECTOR_NODE;\n});\n\nconst architectureInspectorPanelStyle = computed(() => {\n return {\n transform: architectureInspectorOpen.value ? \"translateX(0)\" : \"translateX(100%)\",\n };\n});\n\nconst branchChoices = computed<BranchChoice[]>(() => {\n if (isArchitectureMode.value) {\n return [];\n }\n\n const node = activeNode.value;\n const frame = activeFrame.value;\n if (!node || !frame) return [];\n\n if (frame.localStep < frame.totalLocalSteps - 1) {\n return [];\n }\n\n const options = outgoingNodeKeys.value[node.key] ?? [];\n if (options.length <= 1) return [];\n\n const result: BranchChoice[] = [];\n\n for (const id of options) {\n const target = orderedNodeByKey.value[id];\n if (!target) continue;\n\n const transition = transitionMetaBySource.value[node.key]?.[id];\n\n const targetLabel = toOptionalString(target.element.props.label) ?? id;\n const targetDescription = getNodeSummary(target);\n\n result.push({\n id,\n label: transition?.label ?? targetLabel,\n description: transition?.description ?? targetDescription,\n kind: transition?.kind,\n });\n }\n\n return result;\n});\n\nconst selectedBranchChoiceId = computed(() => {\n const node = activeNode.value;\n if (!node || branchChoices.value.length === 0) return undefined;\n\n const selected = selectedBranchByNode.value[node.key];\n if (selected) return selected;\n\n return nextPlannedNodeKey.value;\n});\n\nfunction chooseChoice(choiceId: string) {\n const node = activeNode.value;\n if (!node) return;\n\n pauseNarrativePlayback();\n\n const options = outgoingNodeKeys.value[node.key] ?? [];\n if (!options.includes(choiceId)) return;\n\n selectedBranchByNode.value = {\n ...selectedBranchByNode.value,\n [node.key]: choiceId,\n };\n\n const prefix = pathFrames.value.slice(0, currentStep.value + 1);\n const suffix = buildGuidedPath(choiceId);\n\n pathFrames.value = [...prefix, ...suffix];\n\n if (pathFrames.value.length > currentStep.value + 1) {\n currentStep.value += 1;\n }\n}\n\nconst containerMinHeight = computed(() => {\n const provided = Number(props.minHeight);\n if (Number.isFinite(provided) && provided >= 320) {\n return Math.floor(provided);\n }\n\n if (isArchitectureMode.value) {\n return 620;\n }\n\n const node = activeNode.value ?? orderedNodeElements.value[0];\n if (!node || node.element.type !== \"CodeNode\") {\n return 520;\n }\n\n const maxLineLength = getCodeNodeMaxLineLength(node.element);\n const nodeWidth = estimateCodeNodeWidth(maxLineLength);\n const codeCharsPerLine = estimateCodeNodeCharsPerLine(nodeWidth);\n const autoWrapEnabled = maxLineLength > CODE_NODE_MAX_INLINE_CHARS;\n const wrapEnabled = toBoolean(node.element.props.wrapLongLines) || autoWrapEnabled;\n\n const codeLines = wrapEnabled\n ? getCodeNodeWrappedLines(node.element, codeCharsPerLine)\n : getCodeNodeMaxLines(node.element);\n const storyLines = getCodeNodeStoryLines(node.element);\n const storyHasMeta = hasCodeNodeStoryMeta(node.element);\n\n const codeViewportHeight = wrapEnabled\n ? Math.min(400, Math.max(190, 72 + codeLines * 16))\n : Math.min(340, Math.max(160, 84 + codeLines * 17));\n\n const storyViewportHeight =\n storyLines > 0 ? Math.min(220, Math.max(88, (storyHasMeta ? 56 : 34) + storyLines * 18)) : 0;\n\n return Math.min(880, Math.max(560, codeViewportHeight + storyViewportHeight + 300));\n});\n\nconst instance = getCurrentInstance();\nconst flowId = `flaier-${instance?.uid ?? 0}`;\nconst { fitView, onNodeClick, onViewportChange, setCenter, viewport } = useVueFlow(flowId);\nconst nodesInitialized = useNodesInitialized();\nconst paneReady = ref(false);\nconst overviewMode = ref(false);\nlet resizeObserver: ResizeObserver | null = null;\n\nconst architectureZoneLayerStyle = computed(() => {\n const x = Number.isFinite(viewport.value.x) ? viewport.value.x : 0;\n const y = Number.isFinite(viewport.value.y) ? viewport.value.y : 0;\n const zoom = Number.isFinite(viewport.value.zoom) ? viewport.value.zoom : 1;\n\n return {\n transform: `translate(${x}px, ${y}px) scale(${zoom})`,\n transformOrigin: \"0 0\",\n };\n});\n\nfunction handleDocumentPointerDown(event: PointerEvent) {\n const target = event.target as Node | null;\n if (!target) return;\n\n if (headerDropdownOpen.value && !headerDropdownRef.value?.contains(target)) {\n closeHeaderDropdown();\n }\n\n if (exportMenuOpen.value && !exportMenuRef.value?.contains(target)) {\n closeExportMenu();\n }\n}\n\nfunction isEditableTarget(target: EventTarget | null) {\n if (!(target instanceof HTMLElement)) {\n return false;\n }\n\n if (target.isContentEditable) {\n return true;\n }\n\n const tagName = target.tagName;\n if (tagName === \"INPUT\" || tagName === \"TEXTAREA\" || tagName === \"SELECT\") {\n return true;\n }\n\n return Boolean(target.closest('[contenteditable=\"true\"]'));\n}\n\nfunction handleDocumentKeydown(event: KeyboardEvent) {\n if (event.key === \"Escape\") {\n closeHeaderDropdown();\n closeExportMenu();\n\n if (isArchitectureMode.value) {\n architectureInspectorOpen.value = false;\n }\n\n return;\n }\n\n if (event.defaultPrevented) return;\n if (event.metaKey || event.ctrlKey || event.altKey) return;\n if (isEditableTarget(event.target)) return;\n if (isArchitectureMode.value) return;\n\n if (event.key === \"ArrowRight\" || event.key === \"ArrowDown\") {\n event.preventDefault();\n next();\n return;\n }\n\n if (event.key === \"ArrowLeft\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n prev();\n return;\n }\n\n if (/^[1-9]$/.test(event.key)) {\n const index = Number(event.key) - 1;\n const choice = branchChoices.value[index];\n if (!choice) return;\n\n event.preventDefault();\n chooseChoice(choice.id);\n }\n}\n\nfunction syncOverviewModeFromZoom(zoom: number) {\n if (overviewMode.value) {\n if (zoom >= OVERVIEW_EXIT_ZOOM) {\n overviewMode.value = false;\n }\n\n return;\n }\n\n if (zoom <= OVERVIEW_ENTER_ZOOM) {\n overviewMode.value = true;\n }\n}\n\nwatch(\n () => viewport.value.zoom,\n (zoom) => {\n if (!Number.isFinite(zoom)) return;\n\n syncOverviewModeFromZoom(zoom);\n },\n { immediate: true },\n);\n\nonViewportChange((transform) => {\n if (!Number.isFinite(transform.zoom)) return;\n\n syncOverviewModeFromZoom(transform.zoom);\n});\n\nonNodeClick(({ node }) => {\n if (isArchitectureMode.value) {\n architectureSelectedNodeKey.value = node.id;\n architectureInspectorOpen.value = true;\n return;\n }\n\n jumpToNode(node.id);\n});\n\nfunction updateContainerReady() {\n const element = containerRef.value;\n containerWidth.value = element?.clientWidth ?? 0;\n containerHeight.value = element?.clientHeight ?? 0;\n containerReady.value = containerWidth.value > 0 && containerHeight.value > 0;\n}\n\nfunction waitForAnimationFrame() {\n return new Promise<void>((resolve) => {\n if (typeof window === \"undefined\" || typeof window.requestAnimationFrame !== \"function\") {\n setTimeout(resolve, 16);\n return;\n }\n\n window.requestAnimationFrame(() => {\n resolve();\n });\n });\n}\n\nasync function waitForViewportLayoutStability() {\n await nextTick();\n await waitForAnimationFrame();\n await waitForAnimationFrame();\n updateContainerReady();\n await nextTick();\n}\n\nfunction getNarrativeFocusZoom(size: NodeSize) {\n const width = Math.max(1, containerWidth.value);\n const height = Math.max(1, containerHeight.value);\n const focusWidth = Math.max(size.width * 1.35, size.width + NARRATIVE_FOCUS_HORIZONTAL_CONTEXT);\n const focusHeight = Math.max(size.height * 1.45, size.height + NARRATIVE_FOCUS_VERTICAL_CONTEXT);\n const zoom = Math.min(width / focusWidth, height / focusHeight);\n\n if (!Number.isFinite(zoom)) {\n return 1;\n }\n\n return Math.max(NARRATIVE_FOCUS_MIN_ZOOM, Math.min(NARRATIVE_FOCUS_MAX_ZOOM, zoom));\n}\n\nconst sceneStyle = computed<Record<string, string>>(() => ({\n height: `${Math.max(containerHeight.value, containerMinHeight.value)}px`,\n}));\n\nonMounted(() => {\n if (typeof document !== \"undefined\") {\n document.addEventListener(\"pointerdown\", handleDocumentPointerDown);\n document.addEventListener(\"keydown\", handleDocumentKeydown);\n }\n\n nextTick(() => {\n updateContainerReady();\n\n if (typeof ResizeObserver === \"undefined\") return;\n\n resizeObserver = new ResizeObserver(() => {\n updateContainerReady();\n });\n\n if (containerRef.value) {\n resizeObserver.observe(containerRef.value);\n }\n });\n});\n\nfunction onInit() {\n paneReady.value = true;\n}\n\nconst viewportReady = computed(\n () => paneReady.value && nodesInitialized.value && containerReady.value && nodes.value.length > 0,\n);\n\nconst canExportDiagram = computed(() => {\n return Boolean(viewportReady.value && diagramBounds.value);\n});\n\nasync function refitViewportAfterContainerChange() {\n if (!nodes.value.length) return;\n\n await waitForViewportLayoutStability();\n\n if (!viewportReady.value || nodes.value.length === 0) {\n return;\n }\n\n if (isArchitectureMode.value || overviewMode.value) {\n await Promise.resolve(\n fitView({\n duration: isArchitectureMode.value ? 260 : 280,\n padding: isArchitectureMode.value ? 0.18 : 0.3,\n maxZoom: isArchitectureMode.value ? 1.15 : 0.95,\n }),\n );\n return;\n }\n\n const target = narrativeFocusTarget.value;\n if (!target) {\n await Promise.resolve(\n fitView({\n duration: 280,\n padding: 0.3,\n maxZoom: 0.95,\n }),\n );\n return;\n }\n\n await nextTick();\n\n await Promise.resolve(\n setCenter(target.x, target.y, {\n duration: 280,\n zoom: target.zoom,\n }),\n );\n}\n\nwatch(canExportDiagram, (canExport) => {\n if (!canExport) {\n closeExportMenu();\n }\n});\n\nconst narrativeFocusTarget = computed(() => {\n if (isArchitectureMode.value || overviewMode.value || !viewportReady.value) {\n return null;\n }\n\n const nodeKey = activeFrame.value?.nodeKey;\n if (!nodeKey) {\n return null;\n }\n\n const node = nodes.value.find((candidate) => candidate.id === nodeKey);\n if (!node) {\n return null;\n }\n\n const size = nodeSizes.value[node.id] ?? { width: 240, height: 120 };\n\n return {\n signature: [\n currentStep.value,\n node.id,\n Math.round(node.position.x),\n Math.round(node.position.y),\n Math.round(size.width),\n Math.round(size.height),\n Math.round(containerWidth.value),\n Math.round(containerHeight.value),\n ].join(\":\"),\n x: node.position.x + size.width / 2,\n y: node.position.y + size.height / 2,\n zoom: getNarrativeFocusZoom(size),\n };\n});\n\nconst narrativeFitSignature = ref(\"\");\nconst suppressNarrativeResizeFit = ref(false);\n\nwatch(\n [viewportReady, isArchitectureMode, nodes, containerWidth, containerHeight],\n ([ready, architectureMode, currentNodes, width, height]) => {\n if (!ready || architectureMode || currentNodes.length === 0) return;\n\n const signature = [\n `${Math.round(width)}x${Math.round(height)}`,\n ...currentNodes.map(\n (node) => `${node.id}:${Math.round(node.position.x)}:${Math.round(node.position.y)}`,\n ),\n ].join(\"|\");\n\n if (signature === narrativeFitSignature.value) {\n return;\n }\n\n if (suppressNarrativeResizeFit.value && narrativeFocusTarget.value) {\n narrativeFitSignature.value = signature;\n return;\n }\n\n narrativeFitSignature.value = signature;\n\n nextTick(() => {\n void fitView({\n duration: 280,\n padding: 0.3,\n maxZoom: 0.95,\n });\n });\n },\n { immediate: true },\n);\n\nwatch(\n () => narrativeFocusTarget.value?.signature ?? \"\",\n () => {\n const target = narrativeFocusTarget.value;\n if (!target) return;\n\n nextTick(() => {\n void setCenter(target.x, target.y, { duration: 280, zoom: target.zoom });\n });\n },\n { immediate: true },\n);\n\nconst architectureFitSignature = ref(\"\");\nconst lastViewportResetToken = ref(0);\n\nwatch(\n [viewportReady, isArchitectureMode, nodes, containerWidth, containerHeight],\n ([ready, architectureMode, currentNodes, width, height]) => {\n if (!ready || !architectureMode || currentNodes.length === 0) return;\n\n const signature = [\n `${Math.round(width)}x${Math.round(height)}`,\n ...currentNodes.map(\n (node) => `${node.id}:${Math.round(node.position.x)}:${Math.round(node.position.y)}`,\n ),\n ].join(\"|\");\n\n if (signature === architectureFitSignature.value) {\n return;\n }\n\n architectureFitSignature.value = signature;\n\n nextTick(() => {\n void fitView({\n duration: 260,\n padding: 0.18,\n maxZoom: 1.15,\n });\n });\n },\n { immediate: true },\n);\n\nwatch(\n [() => runtime.viewportResetToken.value, viewportReady],\n ([token, ready]) => {\n if (!ready || token <= lastViewportResetToken.value) {\n return;\n }\n\n lastViewportResetToken.value = token;\n narrativeFitSignature.value = \"\";\n architectureFitSignature.value = \"\";\n\n const shouldSuppressNarrativeFit = Boolean(narrativeFocusTarget.value);\n\n if (shouldSuppressNarrativeFit) {\n suppressNarrativeResizeFit.value = true;\n }\n\n void (async () => {\n try {\n await refitViewportAfterContainerChange();\n } finally {\n if (shouldSuppressNarrativeFit) {\n await waitForAnimationFrame();\n await waitForAnimationFrame();\n suppressNarrativeResizeFit.value = false;\n }\n }\n })();\n },\n { immediate: true },\n);\n\nwatch(isArchitectureMode, (architectureMode) => {\n if (architectureMode) {\n playing.value = false;\n narrativeFitSignature.value = \"\";\n architectureInspectorOpen.value = defaultArchitectureInspectorOpen.value;\n return;\n }\n\n narrativeFitSignature.value = \"\";\n architectureFitSignature.value = \"\";\n architectureInspectorOpen.value = defaultArchitectureInspectorOpen.value;\n});\n\nonUnmounted(() => {\n clearTimer();\n\n if (typeof document !== \"undefined\") {\n document.removeEventListener(\"pointerdown\", handleDocumentPointerDown);\n document.removeEventListener(\"keydown\", handleDocumentKeydown);\n }\n\n if (resizeObserver) {\n resizeObserver.disconnect();\n resizeObserver = null;\n }\n\n stopDocumentThemeSync();\n});\n</script>\n\n<template>\n <div\n ref=\"containerRef\"\n class=\"flaier relative h-full w-full font-sans antialiased bg-background transition-[min-height] duration-300 ease-out\"\n :style=\"{ minHeight: `${containerMinHeight}px` }\"\n :data-mode=\"isArchitectureMode ? 'architecture' : 'narrative'\"\n :data-focus-mode=\"overviewMode ? 'overview' : 'focus'\"\n :data-theme=\"uiTheme\"\n >\n <div ref=\"sceneRef\" class=\"relative w-full overflow-hidden\" :style=\"sceneStyle\">\n <div\n v-if=\"containerReady && isArchitectureMode && architectureZoneOverlays.length > 0\"\n class=\"pointer-events-none absolute inset-0 z-0\"\n >\n <div class=\"absolute inset-0\" data-zone-overlay=\"true\" :style=\"architectureZoneLayerStyle\">\n <div\n v-for=\"zone in architectureZoneOverlays\"\n :key=\"zone.id\"\n class=\"absolute rounded-2xl border border-dashed\"\n :style=\"architectureZoneCardStyle(zone)\"\n >\n <div\n class=\"absolute left-4 inline-flex items-center gap-2 rounded-full border px-2 py-1 text-[10px] font-semibold uppercase tracking-wider\"\n :style=\"architectureZoneLabelStyle(zone)\"\n >\n <span>{{ zone.label }}</span>\n <span class=\"opacity-80\"\n >{{ zone.nodeCount }} node{{ zone.nodeCount === 1 ? \"\" : \"s\" }}</span\n >\n </div>\n\n <p\n v-if=\"zone.description\"\n class=\"absolute left-4 right-4 text-[10px] leading-snug text-muted-foreground\"\n :style=\"architectureZoneDescriptionStyle(zone)\"\n >\n {{ zone.description }}\n </p>\n </div>\n </div>\n </div>\n\n <VueFlow\n v-if=\"containerReady\"\n :id=\"flowId\"\n :nodes=\"nodes\"\n :edges=\"edges\"\n :node-types=\"customNodeTypes\"\n :fit-view-on-init=\"false\"\n :elements-selectable=\"false\"\n :nodes-focusable=\"false\"\n :nodes-draggable=\"false\"\n :nodes-connectable=\"false\"\n :zoom-on-scroll=\"true\"\n :zoom-on-pinch=\"true\"\n :pan-on-drag=\"true\"\n :pan-on-scroll=\"true\"\n :min-zoom=\"0.15\"\n :max-zoom=\"2\"\n :prevent-scrolling=\"true\"\n class=\"relative z-[10] h-full w-full\"\n @init=\"onInit\"\n >\n <template #node-architecture=\"{ data }\">\n <ArchitectureNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :kind=\"toArchitectureKind(data.props.kind)\"\n :technology=\"toOptionalString(data.props.technology)\"\n :runtime=\"toOptionalString(data.props.runtime)\"\n :owner=\"toOptionalString(data.props.owner)\"\n :tier=\"toArchitectureTier(data.props.tier)\"\n :status=\"toArchitectureStatus(data.props.status)\"\n :tags=\"toStringArray(data.props.tags)\"\n :capabilities=\"toStringArray(data.props.capabilities)\"\n :description=\"toOptionalString(data.props.description)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #edge-architecture=\"edgeProps\">\n <ArchitectureSmoothEdge v-bind=\"edgeProps\" />\n </template>\n\n <template #node-trigger=\"{ data }\">\n <TriggerNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :description=\"toOptionalString(data.props.description)\"\n :color=\"toOptionalString(data.props.color)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-code=\"{ data }\">\n <CodeNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :file=\"toOptionalString(data.props.file)\"\n :language=\"toOptionalString(data.props.language)\"\n :code=\"toRequiredString(data.props.code)\"\n :comment=\"toOptionalString(data.props.comment)\"\n :story=\"toOptionalString(data.props.story)\"\n :wrap-long-lines=\"toBoolean(data.props.wrapLongLines)\"\n :magic-move-steps=\"toMagicMoveSteps(data.props.magicMoveSteps)\"\n :twoslash=\"toOptionalBoolean(data.props.twoslash)\"\n :twoslash-html=\"toTwoslashHtml(data.props.twoslashHtml)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :ui-theme=\"uiTheme\"\n :active=\"isActive(data.key)\"\n :step-index=\"codeStepIndex(data.key)\"\n />\n </template>\n\n <template #node-decision=\"{ data }\">\n <DecisionNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :condition=\"toOptionalString(data.props.condition)\"\n :description=\"toOptionalString(data.props.description)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-payload=\"{ data }\">\n <PayloadNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :payload=\"toOptionalString(data.props.payload)\"\n :before=\"toOptionalString(data.props.before)\"\n :after=\"toOptionalString(data.props.after)\"\n :format=\"toPayloadFormat(data.props.format)\"\n :description=\"toOptionalString(data.props.description)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-error=\"{ data }\">\n <ErrorNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :message=\"toRequiredString(data.props.message)\"\n :code=\"toOptionalString(data.props.code)\"\n :cause=\"toOptionalString(data.props.cause)\"\n :mitigation=\"toOptionalString(data.props.mitigation)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-description=\"{ data }\">\n <DescriptionNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :body=\"toRequiredString(data.props.body)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n\n <template #node-link=\"{ data }\">\n <LinkNodeVue\n :label=\"toRequiredString(data.props.label)\"\n :href=\"toRequiredString(data.props.href)\"\n :description=\"toOptionalString(data.props.description)\"\n :source-anchor=\"resolveNodeSourceAnchor(data.props)\"\n :active=\"isActive(data.key)\"\n />\n </template>\n </VueFlow>\n\n <div v-else class=\"h-full w-full\" />\n </div>\n\n <div\n v-if=\"showHeaderOverlay && (showFlowSelector || overlayTitle || overlayDescription)\"\n ref=\"headerDropdownRef\"\n class=\"absolute top-4 left-4 z-20 w-[min(90vw,430px)]\"\n >\n <div class=\"relative\">\n <button\n type=\"button\"\n class=\"group w-full rounded-lg border border-border/70 bg-card/85 px-3 py-2 text-left text-xs shadow-lg backdrop-blur-md transition-colors\"\n :class=\"showFlowSelector ? 'cursor-pointer hover:border-primary/45' : 'cursor-default'\"\n :disabled=\"!showFlowSelector\"\n :aria-expanded=\"showFlowSelector ? headerDropdownOpen : undefined\"\n aria-haspopup=\"listbox\"\n @click=\"toggleHeaderDropdown\"\n >\n <div class=\"flex items-start justify-between gap-3\">\n <div class=\"min-w-0\">\n <p class=\"text-[10px] font-medium uppercase tracking-wider text-muted-foreground\">\n {{ headerModeLabel }}\n </p>\n <p v-if=\"overlayTitle\" class=\"mt-1 truncate text-sm font-medium text-foreground\">\n {{ overlayTitle }}\n </p>\n <p\n v-if=\"overlayDescription\"\n class=\"mt-0.5 text-[11px] leading-relaxed text-muted-foreground break-words\"\n >\n {{ overlayDescription }}\n </p>\n </div>\n\n <svg\n v-if=\"showFlowSelector\"\n class=\"mt-0.5 h-4 w-4 shrink-0 transition-all\"\n :class=\"\n headerDropdownOpen\n ? 'rotate-180 text-foreground'\n : 'text-muted-foreground group-hover:text-foreground'\n \"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </div>\n </button>\n\n <div\n v-if=\"showFlowSelector && headerDropdownOpen\"\n class=\"absolute inset-x-0 top-[calc(100%+8px)] rounded-lg border border-border/70 bg-card/95 p-1 shadow-2xl backdrop-blur-md\"\n role=\"listbox\"\n >\n <button\n v-for=\"flow in availableFlows\"\n :key=\"flow.id\"\n type=\"button\"\n class=\"w-full rounded-md px-2.5 py-2 text-left transition-colors\"\n :class=\"\n flow.id === activeFlowId\n ? 'bg-primary/14 text-foreground'\n : 'text-foreground/90 hover:bg-muted/70'\n \"\n @click=\"handleFlowSelect(flow.id)\"\n >\n <div class=\"flex items-center justify-between gap-2\">\n <p class=\"truncate text-xs font-medium\">{{ flow.title }}</p>\n <span\n v-if=\"flow.id === activeFlowId\"\n class=\"rounded-full border border-primary/35 bg-primary/10 px-1.5 py-0.5 text-[10px] uppercase tracking-wide text-primary\"\n >\n Active\n </span>\n </div>\n <p\n v-if=\"flow.description\"\n class=\"mt-0.5 text-[11px] leading-relaxed text-muted-foreground break-words\"\n >\n {{ flow.description }}\n </p>\n </button>\n </div>\n </div>\n </div>\n\n <div\n v-if=\"showTopRightControls\"\n class=\"fn-architecture-controls absolute top-4 right-4 z-20 flex flex-col items-end gap-2\"\n >\n <div ref=\"exportMenuRef\" class=\"relative\">\n <button\n v-if=\"showExportControls\"\n type=\"button\"\n class=\"group inline-flex h-9 items-center gap-2 rounded-full border border-border/70 bg-card/85 px-3 text-[11px] text-muted-foreground shadow-lg backdrop-blur-md transition-colors hover:text-foreground disabled:cursor-default disabled:opacity-55\"\n :aria-label=\"exportButtonLabel\"\n :title=\"exportButtonLabel\"\n :disabled=\"!canExportDiagram || Boolean(exportInFlight)\"\n @click=\"toggleExportMenu\"\n >\n <svg\n class=\"h-3.5 w-3.5\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 3v12\" />\n <path d=\"m7 10 5 5 5-5\" />\n <path d=\"M4 20h16\" />\n </svg>\n <span>Export</span>\n </button>\n\n <div\n v-if=\"showExportControls && exportMenuOpen\"\n class=\"absolute right-0 top-[calc(100%+8px)] w-44 rounded-lg border border-border/70 bg-card/95 p-1 shadow-2xl backdrop-blur-md\"\n >\n <button\n type=\"button\"\n class=\"w-full rounded-md px-2.5 py-2 text-left text-xs text-foreground transition-colors hover:bg-muted/70\"\n :disabled=\"Boolean(exportInFlight)\"\n @click=\"exportDiagram('png')\"\n >\n Export PNG\n </button>\n <button\n type=\"button\"\n class=\"w-full rounded-md px-2.5 py-2 text-left text-xs text-foreground transition-colors hover:bg-muted/70\"\n :disabled=\"Boolean(exportInFlight)\"\n @click=\"exportDiagram('pdf')\"\n >\n Export PDF\n </button>\n </div>\n </div>\n\n <button\n v-if=\"showThemeToggle\"\n type=\"button\"\n class=\"fn-theme-toggle group inline-flex h-9 w-9 items-center justify-center rounded-full border border-border/70 bg-card/85 text-muted-foreground shadow-lg backdrop-blur-md transition-colors hover:text-foreground\"\n :aria-label=\"themeToggleLabel\"\n :title=\"themeToggleLabel\"\n @click=\"toggleTheme\"\n >\n <svg\n v-if=\"isLightTheme\"\n class=\"h-4 w-4\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 3a1 1 0 0 1 1 1v1a1 1 0 1 1-2 0V4a1 1 0 0 1 1-1Z\" />\n <path\n d=\"M18.36 5.64a1 1 0 0 1 1.41 0l.71.71a1 1 0 0 1-1.41 1.41l-.71-.7a1 1 0 0 1 0-1.42Z\"\n />\n <path d=\"M20 11a1 1 0 1 1 0 2h-1a1 1 0 1 1 0-2h1Z\" />\n <path\n d=\"M18.36 18.36a1 1 0 0 1 0-1.41l.71-.71a1 1 0 0 1 1.41 1.41l-.7.71a1 1 0 0 1-1.42 0Z\"\n />\n <path d=\"M12 19a1 1 0 0 1 1 1v1a1 1 0 1 1-2 0v-1a1 1 0 0 1 1-1Z\" />\n <path\n d=\"M5.64 18.36a1 1 0 0 1-1.41 0l-.71-.71a1 1 0 1 1 1.41-1.41l.71.7a1 1 0 0 1 0 1.42Z\"\n />\n <path d=\"M5 11a1 1 0 1 1 0 2H4a1 1 0 1 1 0-2h1Z\" />\n <path\n d=\"M5.64 5.64a1 1 0 0 1 0 1.41l-.71.71a1 1 0 1 1-1.41-1.41l.7-.71a1 1 0 0 1 1.42 0Z\"\n />\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n </svg>\n\n <svg\n v-else\n class=\"h-4 w-4\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M21 12.79A9 9 0 1 1 11.21 3a7 7 0 1 0 9.79 9.79Z\" />\n </svg>\n </button>\n\n <p\n v-if=\"showExportControls && exportError\"\n class=\"max-w-[260px] rounded-md border border-red-500/45 bg-red-500/12 px-2 py-1 text-[10px] leading-relaxed text-red-200\"\n >\n {{ exportError }}\n </p>\n </div>\n\n <div\n v-if=\"!isArchitectureMode\"\n class=\"pointer-events-none absolute inset-x-0 bottom-2 z-30 flex justify-center px-3\"\n style=\"padding-bottom: max(env(safe-area-inset-bottom), 0px)\"\n >\n <div class=\"pointer-events-auto w-full max-w-[980px]\">\n <TimelineControls\n :current-step=\"currentStep\"\n :total-steps=\"totalSteps\"\n :playing=\"playing\"\n :label=\"activeLabel\"\n :description=\"activeDescription\"\n :source-anchor-label=\"activeSourceAnchor?.label\"\n :source-anchor-href=\"activeSourceAnchor?.href\"\n :choices=\"branchChoices\"\n :selected-choice-id=\"selectedBranchChoiceId\"\n @next=\"next\"\n @prev=\"prev\"\n @go-to=\"goTo\"\n @toggle-play=\"togglePlay\"\n @choose-choice=\"chooseChoice\"\n />\n </div>\n </div>\n\n <div\n v-if=\"isArchitectureMode && showArchitectureInspectorPanel && architectureInspector\"\n class=\"fn-architecture-inspector pointer-events-none absolute bottom-3 right-0 top-16 z-30 w-[min(92vw,430px)]\"\n style=\"\n padding-right: max(env(safe-area-inset-right), 0px);\n padding-bottom: max(env(safe-area-inset-bottom), 0px);\n \"\n >\n <div class=\"absolute inset-0 overflow-visible\">\n <aside\n class=\"pointer-events-auto absolute inset-y-0 right-0 w-full transition-all duration-300 ease-out\"\n :style=\"architectureInspectorPanelStyle\"\n >\n <button\n type=\"button\"\n class=\"fn-architecture-inspector__toggle absolute right-full top-1/2 z-30 inline-flex h-20 w-8 -translate-y-1/2 translate-x-px flex-col items-center justify-center gap-1 rounded-l-lg rounded-r-none border border-border/70 border-r-0 bg-gradient-to-b from-card/95 via-card/88 to-card/78 px-0.5 text-[8px] font-semibold uppercase tracking-[0.12em] text-muted-foreground shadow-2xl backdrop-blur-xl transition-all duration-200 hover:text-foreground\"\n :aria-label=\"architectureInspectorToggleLabel\"\n :title=\"architectureInspectorToggleLabel\"\n @click=\"toggleArchitectureInspector\"\n >\n <svg\n class=\"h-2.5 w-2.5\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path v-if=\"architectureInspectorOpen\" d=\"m14.5 6-5.5 6 5.5 6\" />\n <path v-else d=\"m9.5 6 5.5 6-5.5 6\" />\n </svg>\n <span\n v-if=\"showArchitectureInspectorToggleText\"\n class=\"inline-block font-semibold leading-none\"\n style=\"writing-mode: vertical-rl; transform: rotate(180deg); letter-spacing: 0.1em\"\n >\n Details\n </span>\n </button>\n\n <div\n class=\"fn-architecture-inspector__panel flex h-full flex-col overflow-hidden rounded-2xl border border-border/60 bg-gradient-to-b from-card/95 via-card/90 to-card/82 shadow-2xl backdrop-blur-xl\"\n >\n <div class=\"border-b border-border/60 px-3 py-2.5\">\n <div class=\"flex flex-wrap items-start justify-between gap-2\">\n <div class=\"min-w-0\">\n <p class=\"text-[11px] font-semibold text-foreground leading-snug break-words\">\n {{ architectureInspector.label }}\n </p>\n\n <div v-if=\"architectureInspectorNode\" class=\"mt-1 flex flex-wrap gap-1\">\n <span\n v-if=\"architectureInspectorNodeSafe.kind\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[9px] uppercase tracking-wider text-muted-foreground\"\n >\n {{ architectureInspectorNodeSafe.kind }}\n </span>\n <span\n v-if=\"architectureInspectorNodeSafe.status\"\n class=\"inline-flex items-center rounded border border-primary/35 bg-primary/10 px-1.5 py-0.5 text-[9px] uppercase tracking-wider text-primary\"\n >\n {{ architectureInspectorNodeSafe.status }}\n </span>\n <span\n v-if=\"architectureInspectorNodeSafe.tier\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[9px] uppercase tracking-wider text-muted-foreground\"\n >\n {{ architectureInspectorNodeSafe.tier }}\n </span>\n <span\n v-if=\"architectureInspectorNodeSafe.zoneLabel\"\n class=\"inline-flex items-center rounded border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[9px] uppercase tracking-wider text-muted-foreground\"\n >\n Zone: {{ architectureInspectorNodeSafe.zoneLabel }}\n </span>\n </div>\n </div>\n\n <a\n v-if=\"\n architectureInspector.sourceAnchor?.label &&\n architectureInspector.sourceAnchor?.href\n \"\n :href=\"architectureInspector.sourceAnchor.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"inline-flex max-w-full items-center gap-1 rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground transition-colors hover:border-primary/45 hover:text-foreground\"\n >\n <span class=\"truncate\">{{ architectureInspector.sourceAnchor.label }}</span>\n </a>\n\n <p\n v-else-if=\"architectureInspector.sourceAnchor?.label\"\n class=\"inline-flex max-w-full items-center rounded-md border border-border/70 bg-muted/25 px-1.5 py-0.5 text-[10px] font-mono text-muted-foreground\"\n >\n <span class=\"truncate\">{{ architectureInspector.sourceAnchor.label }}</span>\n </p>\n </div>\n\n <p\n v-if=\"architectureInspector.summary\"\n class=\"mt-1.5 text-[11px] text-muted-foreground leading-relaxed whitespace-pre-wrap break-words\"\n >\n {{ architectureInspector.summary }}\n </p>\n </div>\n\n <div class=\"min-h-0 flex-1 space-y-2 overflow-y-auto px-3 py-2.5\">\n <template v-if=\"architectureInspectorNode\">\n <div class=\"rounded-lg border border-border/60 bg-muted/20 px-2 py-1.5\">\n <p\n class=\"text-[9px] font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n Core\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.technology\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Technology: {{ architectureInspectorNodeSafe.technology }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.runtime\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Runtime: {{ architectureInspectorNodeSafe.runtime }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.owner\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Owner: {{ architectureInspectorNodeSafe.owner }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.operations?.slo\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n SLO: {{ architectureInspectorNodeSafe.operations.slo }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.operations?.alert\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Alert: {{ architectureInspectorNodeSafe.operations.alert }}\n </p>\n </div>\n\n <div\n v-if=\"\n architectureInspectorNodeSafe.security ||\n architectureInspectorNodeSafe.dataAssets.length > 0\n \"\n class=\"rounded-lg border border-border/60 bg-muted/20 px-2 py-1.5\"\n >\n <p\n class=\"text-[9px] font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n Data & Security\n </p>\n <template v-if=\"architectureInspectorNodeSafe.security\">\n <p\n v-if=\"architectureInspectorNodeSafe.security.auth\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Auth: {{ architectureInspectorNodeSafe.security.auth }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.security.encryption\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Encryption: {{ architectureInspectorNodeSafe.security.encryption }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.security.pii !== undefined\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n PII: {{ architectureInspectorNodeSafe.security.pii ? \"Yes\" : \"No\" }}\n </p>\n <p\n v-if=\"architectureInspectorNodeSafe.security.threatModel\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Threat Model: {{ architectureInspectorNodeSafe.security.threatModel }}\n </p>\n </template>\n\n <div\n v-if=\"architectureInspectorNodeSafe.dataAssets.length > 0\"\n class=\"mt-1.5 space-y-1\"\n >\n <p\n v-for=\"asset in architectureInspectorNodeSafe.dataAssets\"\n :key=\"`${asset.name}-${asset.kind ?? ''}`\"\n class=\"text-[10px] text-foreground\"\n >\n {{ asset.name }}<span v-if=\"asset.kind\"> ({{ asset.kind }})</span\n ><span v-if=\"asset.classification\"> - {{ asset.classification }}</span\n ><span v-if=\"asset.retention\"> - {{ asset.retention }}</span>\n </p>\n </div>\n </div>\n\n <div\n v-if=\"\n architectureInspectorNodeSafe.responsibilities.length > 0 ||\n architectureInspectorNodeSafe.capabilities.length > 0 ||\n architectureInspectorNodeSafe.tags.length > 0\n \"\n class=\"rounded-lg border border-border/60 bg-muted/20 px-2 py-1.5\"\n >\n <p\n class=\"text-[9px] font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n Capabilities\n </p>\n\n <div\n v-if=\"architectureInspectorNodeSafe.capabilities.length > 0\"\n class=\"mt-1 flex flex-wrap gap-1\"\n >\n <span\n v-for=\"capability in architectureInspectorNodeSafe.capabilities\"\n :key=\"capability\"\n class=\"inline-flex items-center rounded border border-primary/35 bg-primary/10 px-1.5 py-0.5 text-[9px] text-primary\"\n >\n {{ capability }}\n </span>\n </div>\n\n <div\n v-if=\"architectureInspectorNodeSafe.tags.length > 0\"\n class=\"mt-1 flex flex-wrap gap-1\"\n >\n <span\n v-for=\"tag in architectureInspectorNodeSafe.tags\"\n :key=\"tag\"\n class=\"inline-flex items-center rounded border border-border/70 bg-card/35 px-1.5 py-0.5 text-[9px] text-muted-foreground\"\n >\n #{{ tag }}\n </span>\n </div>\n\n <ul\n v-if=\"architectureInspectorNodeSafe.responsibilities.length > 0\"\n class=\"mt-1 space-y-0.5 text-[10px] text-foreground\"\n >\n <li v-for=\"item in architectureInspectorNodeSafe.responsibilities\" :key=\"item\">\n - {{ item }}\n </li>\n </ul>\n </div>\n\n <div\n v-if=\"\n architectureInspectorNodeSafe.interfaces.length > 0 ||\n architectureInspectorNodeSafe.outgoing.length > 0 ||\n architectureInspectorNodeSafe.links.length > 0 ||\n architectureInspectorNodeSafe.operations?.runbook\n \"\n class=\"rounded-lg border border-border/60 bg-muted/20 px-2 py-1.5\"\n >\n <p\n class=\"text-[9px] font-semibold uppercase tracking-wider text-muted-foreground\"\n >\n Interfaces & Links\n </p>\n\n <div\n v-if=\"architectureInspectorNodeSafe.interfaces.length > 0\"\n class=\"mt-1 space-y-1\"\n >\n <p\n v-for=\"iface in architectureInspectorNodeSafe.interfaces\"\n :key=\"`${iface.name}-${iface.protocol ?? ''}-${iface.direction ?? ''}`\"\n class=\"text-[10px] text-foreground\"\n >\n {{ iface.name }}<span v-if=\"iface.protocol\"> ({{ iface.protocol }})</span\n ><span v-if=\"iface.direction\"> - {{ iface.direction }}</span\n ><span v-if=\"iface.auth\"> - auth: {{ iface.auth }}</span\n ><span v-if=\"iface.contract\"> - {{ iface.contract }}</span>\n </p>\n </div>\n\n <p\n v-if=\"architectureInspectorNodeSafe.operations?.runbook\"\n class=\"mt-1 text-[10px] text-foreground\"\n >\n Runbook: {{ architectureInspectorNodeSafe.operations.runbook }}\n </p>\n\n <div\n v-if=\"architectureInspectorNodeSafe.outgoing.length > 0\"\n class=\"mt-1 space-y-1\"\n >\n <p\n v-for=\"edge in architectureInspectorNodeSafe.outgoing\"\n :key=\"`${edge.target}-${edge.label ?? ''}-${edge.protocol ?? ''}`\"\n class=\"text-[10px] text-foreground\"\n >\n {{ edge.label ?? \"Connect\" }} -> {{ edge.target\n }}<span v-if=\"edge.protocol\"> ({{ edge.protocol }})</span\n ><span v-if=\"edge.transport\"> - {{ edge.transport }}</span\n ><span v-if=\"edge.auth\"> - auth: {{ edge.auth }}</span\n ><span v-if=\"edge.criticality\"> - {{ edge.criticality }}</span>\n </p>\n </div>\n\n <div\n v-if=\"architectureInspectorNodeSafe.links.length > 0\"\n class=\"mt-1 flex flex-wrap gap-1\"\n >\n <a\n v-for=\"link in architectureInspectorNodeSafe.links\"\n :key=\"`${link.label}-${link.href}`\"\n :href=\"link.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"inline-flex items-center rounded border border-border/70 bg-card/35 px-1.5 py-0.5 text-[9px] text-foreground transition-colors hover:border-primary/45\"\n >\n {{ link.label }}\n </a>\n </div>\n </div>\n </template>\n </div>\n </div>\n </aside>\n </div>\n </div>\n </div>\n</template>\n","import { h } from \"vue\";\nimport type { ComponentFn, ComponentRegistry } from \"@json-render/vue\";\nimport { defineRegistry } from \"@json-render/vue\";\nimport { catalog, createFlaierCatalog } from \"./catalog\";\nimport FlowTimelineRenderer from \"./components/renderer/FlowTimelineRenderer.vue\";\nimport { createFlaierCustomRegistryComponents } from \"./custom-nodes\";\nimport type { FlaierCatalogOptions } from \"./types\";\n\nconst FlowTimelineComponent: ComponentFn<typeof catalog, \"FlowTimeline\"> = ({ props }) =>\n h(FlowTimelineRenderer, {\n title: props.title,\n description: props.description,\n mode: props.mode,\n zones: props.zones,\n direction: props.direction,\n minHeight: props.minHeight,\n layoutEngine: props.layoutEngine,\n layoutRankSep: props.layoutRankSep,\n layoutNodeSep: props.layoutNodeSep,\n layoutEdgeSep: props.layoutEdgeSep,\n themeMode: props.themeMode,\n showHeaderOverlay: props.showHeaderOverlay,\n showExportControls: props.showExportControls,\n showThemeToggle: props.showThemeToggle,\n showArchitectureInspector: props.showArchitectureInspector,\n defaultArchitectureInspectorOpen: props.defaultArchitectureInspectorOpen,\n showArchitectureInspectorToggleText: props.showArchitectureInspectorToggleText,\n });\n\nconst ArchitectureNodeComponent: ComponentFn<typeof catalog, \"ArchitectureNode\"> = () => null;\nconst TriggerNodeComponent: ComponentFn<typeof catalog, \"TriggerNode\"> = () => null;\nconst CodeNodeComponent: ComponentFn<typeof catalog, \"CodeNode\"> = () => null;\nconst DecisionNodeComponent: ComponentFn<typeof catalog, \"DecisionNode\"> = () => null;\nconst PayloadNodeComponent: ComponentFn<typeof catalog, \"PayloadNode\"> = () => null;\nconst ErrorNodeComponent: ComponentFn<typeof catalog, \"ErrorNode\"> = () => null;\nconst DescriptionNodeComponent: ComponentFn<typeof catalog, \"DescriptionNode\"> = () => null;\nconst LinkNodeComponent: ComponentFn<typeof catalog, \"LinkNode\"> = () => null;\n\nconst baseRegistryResult = defineRegistry(catalog, {\n components: {\n FlowTimeline: FlowTimelineComponent,\n ArchitectureNode: ArchitectureNodeComponent,\n TriggerNode: TriggerNodeComponent,\n CodeNode: CodeNodeComponent,\n DecisionNode: DecisionNodeComponent,\n PayloadNode: PayloadNodeComponent,\n ErrorNode: ErrorNodeComponent,\n DescriptionNode: DescriptionNodeComponent,\n LinkNode: LinkNodeComponent,\n },\n});\n\nexport const registry = baseRegistryResult.registry;\n\nexport function createFlaierRendererRegistry<\n TNodes extends NonNullable<FlaierCatalogOptions[\"nodes\"]>,\n>(options?: FlaierCatalogOptions<TNodes>): ComponentRegistry {\n return {\n ...registry,\n ...createFlaierCustomRegistryComponents(options?.nodes),\n };\n}\n\nexport function createFlaierRegistry<TNodes extends NonNullable<FlaierCatalogOptions[\"nodes\"]>>(\n options?: FlaierCatalogOptions<TNodes>,\n) {\n return {\n catalog: createFlaierCatalog(options),\n registry: createFlaierRendererRegistry(options),\n };\n}\n","<script setup lang=\"ts\">\nimport { ActionProvider, Renderer, StateProvider, VisibilityProvider } from \"@json-render/vue\";\nimport { autoFixSpec, formatSpecIssues, type Spec, validateSpec } from \"@json-render/core\";\nimport { computed, provide, ref, toRef, watch } from \"vue\";\nimport { flaierRuntimeKey } from \"../context\";\nimport { normalizeFlaierCustomNodes } from \"../custom-nodes\";\nimport { createFlaierRendererRegistry } from \"../registry\";\nimport type {\n FlaierFlowOption,\n FlaierManifest,\n FlaierManifestFlow,\n FlaierProps,\n FlaierSource,\n FlaierSpec,\n} from \"../types\";\n\nconst props = withDefaults(defineProps<FlaierProps>(), {\n autoPlay: false,\n interval: 3000,\n});\n\nconst emit = defineEmits<{\n loaded: [spec: FlaierSpec];\n \"load-error\": [message: string];\n \"state-change\": [changes: Array<{ path: string; value: unknown }>];\n}>();\n\ninterface ResolvedFlowDocument {\n id: string;\n title?: string;\n description?: string;\n tags?: string[];\n entrypoints?: string[];\n source: FlaierSpec | string;\n}\n\nconst resolvedSpec = ref<FlaierSpec | null>(null);\nconst loading = ref(false);\nconst loadError = ref<string | null>(null);\nconst specVersion = ref(0);\nconst flowDocuments = ref<ResolvedFlowDocument[]>([]);\nconst flowOptions = ref<FlaierFlowOption[]>([]);\nconst activeFlowId = ref<string | null>(null);\n\nlet sourceRequestId = 0;\nlet flowRequestId = 0;\n\nconst customNodes = computed(() => normalizeFlaierCustomNodes(props.nodes));\nconst viewportResetToken = computed(() => {\n return typeof props.viewportResetToken === \"number\" && Number.isFinite(props.viewportResetToken)\n ? Math.max(0, Math.floor(props.viewportResetToken))\n : 0;\n});\nconst rendererRegistry = computed(() => createFlaierRendererRegistry({ nodes: customNodes.value }));\n\nprovide(flaierRuntimeKey, {\n spec: resolvedSpec,\n interval: toRef(props, \"interval\"),\n nodes: customNodes,\n flowOptions,\n activeFlowId,\n viewportResetToken,\n setActiveFlow,\n});\n\nwatch(\n [() => props.src, () => props.themeMode],\n () => {\n void loadSourceCollection();\n },\n { immediate: true },\n);\n\nconst initialState = computed<Record<string, unknown>>(() => {\n const specState = (resolvedSpec.value?.state ?? {}) as Record<string, unknown>;\n const parsedCurrentStep = Number(specState.currentStep);\n\n return {\n ...specState,\n currentStep: Number.isFinite(parsedCurrentStep)\n ? Math.max(0, Math.floor(parsedCurrentStep))\n : 0,\n playing: props.autoPlay ? true : Boolean(specState.playing),\n };\n});\n\nconst providerKey = computed(() => {\n const spec = resolvedSpec.value;\n if (!spec) return \"flaier-empty\";\n return `${specVersion.value}-${spec.root}-${Object.keys(spec.elements).length}-${props.autoPlay ? \"auto\" : \"manual\"}-${props.themeMode ?? \"spec\"}`;\n});\n\nasync function loadSourceCollection() {\n const requestId = ++sourceRequestId;\n\n loading.value = true;\n loadError.value = null;\n resolvedSpec.value = null;\n\n try {\n const resolved = await resolveFlowDocuments(props.src);\n if (requestId !== sourceRequestId) return;\n\n if (resolved.flows.length === 0) {\n throw new Error(\"No flow specs were found in source.\");\n }\n\n flowDocuments.value = resolved.flows;\n syncFlowOptions();\n\n const nextActive = pickActiveFlowId(resolved.defaultFlowId);\n activeFlowId.value = nextActive;\n\n if (!nextActive) {\n resolvedSpec.value = null;\n return;\n }\n\n await loadFlowSpec(nextActive, requestId);\n } catch (error) {\n if (requestId !== sourceRequestId) return;\n\n const message = error instanceof Error ? error.message : \"Failed to load flaier source.\";\n\n loadError.value = message;\n resolvedSpec.value = null;\n flowDocuments.value = [];\n flowOptions.value = [];\n activeFlowId.value = null;\n emit(\"load-error\", message);\n } finally {\n if (requestId === sourceRequestId) {\n loading.value = false;\n }\n }\n}\n\nfunction pickActiveFlowId(defaultFlowId?: string) {\n if (defaultFlowId && flowDocuments.value.some((flow) => flow.id === defaultFlowId)) {\n return defaultFlowId;\n }\n\n const current = activeFlowId.value;\n if (current && flowDocuments.value.some((flow) => flow.id === current)) {\n return current;\n }\n\n return flowDocuments.value[0]?.id ?? null;\n}\n\nfunction setActiveFlow(flowId: string) {\n if (flowId === activeFlowId.value) return;\n if (!flowDocuments.value.some((flow) => flow.id === flowId)) return;\n\n activeFlowId.value = flowId;\n void activateFlow(flowId);\n}\n\nasync function activateFlow(flowId: string) {\n const sourceIdAtStart = sourceRequestId;\n\n loading.value = true;\n loadError.value = null;\n\n try {\n await loadFlowSpec(flowId, sourceIdAtStart);\n } catch (error) {\n if (sourceIdAtStart !== sourceRequestId) return;\n\n const message = error instanceof Error ? error.message : `Failed to load flow \"${flowId}\".`;\n\n loadError.value = message;\n resolvedSpec.value = null;\n emit(\"load-error\", message);\n } finally {\n if (sourceIdAtStart === sourceRequestId) {\n loading.value = false;\n }\n }\n}\n\nasync function loadFlowSpec(flowId: string, sourceIdAtStart: number) {\n const requestId = ++flowRequestId;\n const flow = flowDocuments.value.find((item) => item.id === flowId);\n\n if (!flow) {\n throw new Error(`Flow \"${flowId}\" was not found in loaded manifest.`);\n }\n\n const incoming = await resolveSpecSource(flow.source);\n if (sourceIdAtStart !== sourceRequestId || requestId !== flowRequestId) {\n return;\n }\n\n const fixed = autoFixSpec(incoming as Spec);\n const validation = validateSpec(fixed.spec);\n\n if (!validation.valid) {\n console.warn(`[flaier] Invalid spec:\\n${formatSpecIssues(validation.issues)}`);\n }\n\n const nextSpec = applyThemeModeOverride(fixed.spec as FlaierSpec);\n resolvedSpec.value = nextSpec;\n specVersion.value += 1;\n\n patchFlowMetadata(flowId, nextSpec);\n emit(\"loaded\", nextSpec);\n}\n\nasync function resolveFlowDocuments(source: FlaierSource) {\n if (typeof source !== \"string\") {\n if (isFlaierManifest(source)) {\n return normalizeManifest(source);\n }\n\n if (isFlaierSpec(source)) {\n return normalizeSingleSpec(cloneSpec(source));\n }\n\n throw new Error(\"Invalid flaier source object.\");\n }\n\n const { payload, resolvedUrl } = await fetchJsonSource(source);\n\n if (isFlaierManifest(payload)) {\n return normalizeManifest(payload, resolvedUrl);\n }\n\n if (isFlaierSpec(payload)) {\n return normalizeSingleSpec(cloneSpec(payload));\n }\n\n throw new Error(`Fetched JSON from \"${source}\" is neither a flow spec nor a manifest.`);\n}\n\nasync function resolveSpecSource(source: FlaierSpec | string): Promise<FlaierSpec> {\n if (typeof source !== \"string\") {\n return cloneSpec(source);\n }\n\n const { payload } = await fetchJsonSource(source);\n if (!isFlaierSpec(payload)) {\n throw new Error(`Fetched JSON from \"${source}\" is not a valid flow spec.`);\n }\n\n return cloneSpec(payload);\n}\n\nfunction normalizeSingleSpec(spec: FlaierSpec) {\n const metadata = getSpecMetadata(spec);\n\n return {\n flows: [\n {\n id: metadata.id,\n title: metadata.title,\n description: metadata.description,\n source: spec,\n },\n ] satisfies ResolvedFlowDocument[],\n defaultFlowId: metadata.id,\n };\n}\n\nfunction normalizeManifest(manifest: FlaierManifest, baseUrl?: string) {\n const seenIds = new Set<string>();\n const flows: ResolvedFlowDocument[] = [];\n\n for (const entry of manifest.flows) {\n const normalized = normalizeManifestEntry(entry, baseUrl);\n if (!normalized) continue;\n\n if (seenIds.has(normalized.id)) {\n throw new Error(`Duplicate flow id \"${normalized.id}\" in manifest.`);\n }\n\n seenIds.add(normalized.id);\n flows.push(normalized);\n }\n\n if (flows.length === 0) {\n throw new Error(\"Manifest does not contain any valid flows.\");\n }\n\n const defaultFlowId =\n typeof manifest.defaultFlowId === \"string\" && seenIds.has(manifest.defaultFlowId)\n ? manifest.defaultFlowId\n : flows[0]?.id;\n\n return {\n flows,\n defaultFlowId,\n };\n}\n\nfunction normalizeManifestEntry(\n entry: FlaierManifestFlow,\n baseUrl?: string,\n): ResolvedFlowDocument | null {\n const id = typeof entry.id === \"string\" ? entry.id.trim() : \"\";\n if (!id) return null;\n\n const resolvedSource = normalizeFlowSource(entry.src, baseUrl);\n if (!resolvedSource) {\n throw new Error(`Flow \"${id}\" has an invalid src value.`);\n }\n\n return {\n id,\n title: toOptionalString(entry.title),\n description: toOptionalString(entry.description),\n tags: toStringArray(entry.tags),\n entrypoints: toStringArray(entry.entrypoints),\n source: resolvedSource,\n };\n}\n\nfunction normalizeFlowSource(value: unknown, baseUrl?: string): FlaierSpec | string | null {\n if (typeof value === \"string\") {\n return resolveRelativeSource(value, baseUrl);\n }\n\n if (isFlaierSpec(value)) {\n return cloneSpec(value);\n }\n\n return null;\n}\n\nfunction syncFlowOptions() {\n flowOptions.value = flowDocuments.value.map((flow) => ({\n id: flow.id,\n title: flow.title ?? flow.id,\n description: flow.description,\n tags: flow.tags,\n entrypoints: flow.entrypoints,\n }));\n}\n\nfunction patchFlowMetadata(flowId: string, spec: FlaierSpec) {\n const metadata = getSpecMetadata(spec);\n let changed = false;\n\n flowDocuments.value = flowDocuments.value.map((flow) => {\n if (flow.id !== flowId) return flow;\n\n const nextTitle = flow.title ?? metadata.title;\n const nextDescription = flow.description ?? metadata.description;\n\n if (nextTitle === flow.title && nextDescription === flow.description) {\n return flow;\n }\n\n changed = true;\n return {\n ...flow,\n title: nextTitle,\n description: nextDescription,\n };\n });\n\n if (changed) {\n syncFlowOptions();\n }\n}\n\nfunction getSpecMetadata(spec: FlaierSpec) {\n const rootElement = spec.elements[spec.root];\n const rootProps = isObject(rootElement?.props) ? rootElement.props : {};\n const title = toOptionalString(rootProps.title);\n const description = toOptionalString(rootProps.description);\n const fallbackId = toOptionalString(spec.root) ?? \"flow\";\n\n return {\n id: slugifyId(title ?? fallbackId),\n title,\n description,\n };\n}\n\nfunction applyThemeModeOverride(spec: FlaierSpec): FlaierSpec {\n const override = props.themeMode;\n if (!override) {\n return spec;\n }\n\n const rootElement = spec.elements[spec.root];\n if (!rootElement || rootElement.type !== \"FlowTimeline\" || !isObject(rootElement.props)) {\n return spec;\n }\n\n if (rootElement.props.themeMode === override) {\n return spec;\n }\n\n return {\n ...spec,\n elements: {\n ...spec.elements,\n [spec.root]: {\n ...rootElement,\n props: {\n ...rootElement.props,\n themeMode: override,\n },\n },\n },\n };\n}\n\nfunction slugifyId(value: string) {\n const slug = value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n return slug || \"flow\";\n}\n\nfunction resolveRelativeSource(value: string, baseUrl?: string) {\n if (!baseUrl) return value;\n\n try {\n return new URL(value, baseUrl).toString();\n } catch {\n return value;\n }\n}\n\nfunction createFetchCandidates(source: string) {\n const trimmed = source.trim();\n if (!trimmed) return [];\n\n const hasJsonSuffix = /\\.json(?:[?#].*)?$/i.test(trimmed);\n const candidates: string[] = [trimmed];\n\n if (!hasJsonSuffix && !isLikelyFlowSpecEndpoint(trimmed)) {\n candidates.push(appendManifestJsonPath(trimmed));\n }\n\n return Array.from(new Set(candidates));\n}\n\nfunction isLikelyFlowSpecEndpoint(value: string) {\n return /\\/api\\/flows\\/spec\\/[^/?#]+(?:[?#].*)?$/i.test(value);\n}\n\nfunction appendManifestJsonPath(value: string) {\n const hashSplit = value.split(\"#\", 2);\n const pathAndQuery = hashSplit[0] ?? \"\";\n const hash = hashSplit[1] ?? \"\";\n\n const querySplit = pathAndQuery.split(\"?\", 2);\n const path = querySplit[0] ?? \"\";\n const query = querySplit[1] ?? \"\";\n\n const normalizedPath = path.endsWith(\"/\") ? path : `${path}/`;\n const manifestPath = `${normalizedPath}manifest.json`;\n const withQuery = query ? `${manifestPath}?${query}` : manifestPath;\n\n return hash ? `${withQuery}#${hash}` : withQuery;\n}\n\nasync function fetchJsonSource(source: string) {\n const candidates = createFetchCandidates(source);\n\n if (candidates.length === 0) {\n throw new Error(\"Flow source path cannot be empty.\");\n }\n\n let lastError: Error | null = null;\n\n for (const candidate of candidates) {\n try {\n const response = await fetch(candidate);\n if (!response.ok) {\n lastError = new Error(\n `Failed to fetch \"${candidate}\" (${response.status} ${response.statusText})`,\n );\n continue;\n }\n\n const payload = (await response.json()) as unknown;\n\n return {\n payload,\n resolvedUrl: resolveRelativeSource(\n candidate,\n typeof window !== \"undefined\" ? window.location.href : undefined,\n ),\n };\n } catch (error) {\n lastError =\n error instanceof Error ? error : new Error(`Failed to load source \"${candidate}\".`);\n }\n }\n\n throw lastError ?? new Error(`Failed to load source \"${source}\".`);\n}\n\nfunction cloneSpec(spec: FlaierSpec): FlaierSpec {\n return JSON.parse(JSON.stringify(spec)) as FlaierSpec;\n}\n\nfunction isFlaierManifest(value: unknown): value is FlaierManifest {\n if (!isObject(value)) return false;\n return Array.isArray(value.flows);\n}\n\nfunction isFlaierSpec(value: unknown): value is FlaierSpec {\n if (!isObject(value)) return false;\n if (typeof value.root !== \"string\") return false;\n if (!isObject(value.elements)) return false;\n return true;\n}\n\nfunction toOptionalString(value: unknown) {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\nfunction toStringArray(value: unknown) {\n if (!Array.isArray(value)) return undefined;\n\n const result = value.filter(\n (entry): entry is string => typeof entry === \"string\" && entry.length > 0,\n );\n return result.length > 0 ? result : undefined;\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction handleStateChange(changes: Array<{ path: string; value: unknown }>) {\n emit(\"state-change\", changes);\n}\n</script>\n\n<template>\n <div class=\"flaier relative h-full w-full min-h-[320px]\">\n <div\n v-if=\"loading\"\n class=\"flex h-full w-full items-center justify-center text-sm text-muted-foreground\"\n >\n Loading flow spec...\n </div>\n\n <div\n v-else-if=\"loadError\"\n class=\"flex h-full w-full items-center justify-center px-6 text-center text-sm text-red-300\"\n >\n {{ loadError }}\n </div>\n\n <StateProvider\n v-else-if=\"resolvedSpec\"\n :key=\"providerKey\"\n :initial-state=\"initialState\"\n :on-state-change=\"handleStateChange\"\n >\n <ActionProvider>\n <VisibilityProvider>\n <Renderer :spec=\"resolvedSpec\" :registry=\"rendererRegistry\" />\n </VisibilityProvider>\n </ActionProvider>\n </StateProvider>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { ActionProvider, Renderer, StateProvider, VisibilityProvider } from \"@json-render/vue\";\nimport { autoFixSpec, formatSpecIssues, type Spec, validateSpec } from \"@json-render/core\";\nimport { computed, provide, ref, toRef, watch } from \"vue\";\nimport { flaierRuntimeKey } from \"../context\";\nimport { normalizeFlaierCustomNodes } from \"../custom-nodes\";\nimport { createFlaierRendererRegistry } from \"../registry\";\nimport type {\n FlaierFlowOption,\n FlaierManifest,\n FlaierManifestFlow,\n FlaierProps,\n FlaierSource,\n FlaierSpec,\n} from \"../types\";\n\nconst props = withDefaults(defineProps<FlaierProps>(), {\n autoPlay: false,\n interval: 3000,\n});\n\nconst emit = defineEmits<{\n loaded: [spec: FlaierSpec];\n \"load-error\": [message: string];\n \"state-change\": [changes: Array<{ path: string; value: unknown }>];\n}>();\n\ninterface ResolvedFlowDocument {\n id: string;\n title?: string;\n description?: string;\n tags?: string[];\n entrypoints?: string[];\n source: FlaierSpec | string;\n}\n\nconst resolvedSpec = ref<FlaierSpec | null>(null);\nconst loading = ref(false);\nconst loadError = ref<string | null>(null);\nconst specVersion = ref(0);\nconst flowDocuments = ref<ResolvedFlowDocument[]>([]);\nconst flowOptions = ref<FlaierFlowOption[]>([]);\nconst activeFlowId = ref<string | null>(null);\n\nlet sourceRequestId = 0;\nlet flowRequestId = 0;\n\nconst customNodes = computed(() => normalizeFlaierCustomNodes(props.nodes));\nconst viewportResetToken = computed(() => {\n return typeof props.viewportResetToken === \"number\" && Number.isFinite(props.viewportResetToken)\n ? Math.max(0, Math.floor(props.viewportResetToken))\n : 0;\n});\nconst rendererRegistry = computed(() => createFlaierRendererRegistry({ nodes: customNodes.value }));\n\nprovide(flaierRuntimeKey, {\n spec: resolvedSpec,\n interval: toRef(props, \"interval\"),\n nodes: customNodes,\n flowOptions,\n activeFlowId,\n viewportResetToken,\n setActiveFlow,\n});\n\nwatch(\n [() => props.src, () => props.themeMode],\n () => {\n void loadSourceCollection();\n },\n { immediate: true },\n);\n\nconst initialState = computed<Record<string, unknown>>(() => {\n const specState = (resolvedSpec.value?.state ?? {}) as Record<string, unknown>;\n const parsedCurrentStep = Number(specState.currentStep);\n\n return {\n ...specState,\n currentStep: Number.isFinite(parsedCurrentStep)\n ? Math.max(0, Math.floor(parsedCurrentStep))\n : 0,\n playing: props.autoPlay ? true : Boolean(specState.playing),\n };\n});\n\nconst providerKey = computed(() => {\n const spec = resolvedSpec.value;\n if (!spec) return \"flaier-empty\";\n return `${specVersion.value}-${spec.root}-${Object.keys(spec.elements).length}-${props.autoPlay ? \"auto\" : \"manual\"}-${props.themeMode ?? \"spec\"}`;\n});\n\nasync function loadSourceCollection() {\n const requestId = ++sourceRequestId;\n\n loading.value = true;\n loadError.value = null;\n resolvedSpec.value = null;\n\n try {\n const resolved = await resolveFlowDocuments(props.src);\n if (requestId !== sourceRequestId) return;\n\n if (resolved.flows.length === 0) {\n throw new Error(\"No flow specs were found in source.\");\n }\n\n flowDocuments.value = resolved.flows;\n syncFlowOptions();\n\n const nextActive = pickActiveFlowId(resolved.defaultFlowId);\n activeFlowId.value = nextActive;\n\n if (!nextActive) {\n resolvedSpec.value = null;\n return;\n }\n\n await loadFlowSpec(nextActive, requestId);\n } catch (error) {\n if (requestId !== sourceRequestId) return;\n\n const message = error instanceof Error ? error.message : \"Failed to load flaier source.\";\n\n loadError.value = message;\n resolvedSpec.value = null;\n flowDocuments.value = [];\n flowOptions.value = [];\n activeFlowId.value = null;\n emit(\"load-error\", message);\n } finally {\n if (requestId === sourceRequestId) {\n loading.value = false;\n }\n }\n}\n\nfunction pickActiveFlowId(defaultFlowId?: string) {\n if (defaultFlowId && flowDocuments.value.some((flow) => flow.id === defaultFlowId)) {\n return defaultFlowId;\n }\n\n const current = activeFlowId.value;\n if (current && flowDocuments.value.some((flow) => flow.id === current)) {\n return current;\n }\n\n return flowDocuments.value[0]?.id ?? null;\n}\n\nfunction setActiveFlow(flowId: string) {\n if (flowId === activeFlowId.value) return;\n if (!flowDocuments.value.some((flow) => flow.id === flowId)) return;\n\n activeFlowId.value = flowId;\n void activateFlow(flowId);\n}\n\nasync function activateFlow(flowId: string) {\n const sourceIdAtStart = sourceRequestId;\n\n loading.value = true;\n loadError.value = null;\n\n try {\n await loadFlowSpec(flowId, sourceIdAtStart);\n } catch (error) {\n if (sourceIdAtStart !== sourceRequestId) return;\n\n const message = error instanceof Error ? error.message : `Failed to load flow \"${flowId}\".`;\n\n loadError.value = message;\n resolvedSpec.value = null;\n emit(\"load-error\", message);\n } finally {\n if (sourceIdAtStart === sourceRequestId) {\n loading.value = false;\n }\n }\n}\n\nasync function loadFlowSpec(flowId: string, sourceIdAtStart: number) {\n const requestId = ++flowRequestId;\n const flow = flowDocuments.value.find((item) => item.id === flowId);\n\n if (!flow) {\n throw new Error(`Flow \"${flowId}\" was not found in loaded manifest.`);\n }\n\n const incoming = await resolveSpecSource(flow.source);\n if (sourceIdAtStart !== sourceRequestId || requestId !== flowRequestId) {\n return;\n }\n\n const fixed = autoFixSpec(incoming as Spec);\n const validation = validateSpec(fixed.spec);\n\n if (!validation.valid) {\n console.warn(`[flaier] Invalid spec:\\n${formatSpecIssues(validation.issues)}`);\n }\n\n const nextSpec = applyThemeModeOverride(fixed.spec as FlaierSpec);\n resolvedSpec.value = nextSpec;\n specVersion.value += 1;\n\n patchFlowMetadata(flowId, nextSpec);\n emit(\"loaded\", nextSpec);\n}\n\nasync function resolveFlowDocuments(source: FlaierSource) {\n if (typeof source !== \"string\") {\n if (isFlaierManifest(source)) {\n return normalizeManifest(source);\n }\n\n if (isFlaierSpec(source)) {\n return normalizeSingleSpec(cloneSpec(source));\n }\n\n throw new Error(\"Invalid flaier source object.\");\n }\n\n const { payload, resolvedUrl } = await fetchJsonSource(source);\n\n if (isFlaierManifest(payload)) {\n return normalizeManifest(payload, resolvedUrl);\n }\n\n if (isFlaierSpec(payload)) {\n return normalizeSingleSpec(cloneSpec(payload));\n }\n\n throw new Error(`Fetched JSON from \"${source}\" is neither a flow spec nor a manifest.`);\n}\n\nasync function resolveSpecSource(source: FlaierSpec | string): Promise<FlaierSpec> {\n if (typeof source !== \"string\") {\n return cloneSpec(source);\n }\n\n const { payload } = await fetchJsonSource(source);\n if (!isFlaierSpec(payload)) {\n throw new Error(`Fetched JSON from \"${source}\" is not a valid flow spec.`);\n }\n\n return cloneSpec(payload);\n}\n\nfunction normalizeSingleSpec(spec: FlaierSpec) {\n const metadata = getSpecMetadata(spec);\n\n return {\n flows: [\n {\n id: metadata.id,\n title: metadata.title,\n description: metadata.description,\n source: spec,\n },\n ] satisfies ResolvedFlowDocument[],\n defaultFlowId: metadata.id,\n };\n}\n\nfunction normalizeManifest(manifest: FlaierManifest, baseUrl?: string) {\n const seenIds = new Set<string>();\n const flows: ResolvedFlowDocument[] = [];\n\n for (const entry of manifest.flows) {\n const normalized = normalizeManifestEntry(entry, baseUrl);\n if (!normalized) continue;\n\n if (seenIds.has(normalized.id)) {\n throw new Error(`Duplicate flow id \"${normalized.id}\" in manifest.`);\n }\n\n seenIds.add(normalized.id);\n flows.push(normalized);\n }\n\n if (flows.length === 0) {\n throw new Error(\"Manifest does not contain any valid flows.\");\n }\n\n const defaultFlowId =\n typeof manifest.defaultFlowId === \"string\" && seenIds.has(manifest.defaultFlowId)\n ? manifest.defaultFlowId\n : flows[0]?.id;\n\n return {\n flows,\n defaultFlowId,\n };\n}\n\nfunction normalizeManifestEntry(\n entry: FlaierManifestFlow,\n baseUrl?: string,\n): ResolvedFlowDocument | null {\n const id = typeof entry.id === \"string\" ? entry.id.trim() : \"\";\n if (!id) return null;\n\n const resolvedSource = normalizeFlowSource(entry.src, baseUrl);\n if (!resolvedSource) {\n throw new Error(`Flow \"${id}\" has an invalid src value.`);\n }\n\n return {\n id,\n title: toOptionalString(entry.title),\n description: toOptionalString(entry.description),\n tags: toStringArray(entry.tags),\n entrypoints: toStringArray(entry.entrypoints),\n source: resolvedSource,\n };\n}\n\nfunction normalizeFlowSource(value: unknown, baseUrl?: string): FlaierSpec | string | null {\n if (typeof value === \"string\") {\n return resolveRelativeSource(value, baseUrl);\n }\n\n if (isFlaierSpec(value)) {\n return cloneSpec(value);\n }\n\n return null;\n}\n\nfunction syncFlowOptions() {\n flowOptions.value = flowDocuments.value.map((flow) => ({\n id: flow.id,\n title: flow.title ?? flow.id,\n description: flow.description,\n tags: flow.tags,\n entrypoints: flow.entrypoints,\n }));\n}\n\nfunction patchFlowMetadata(flowId: string, spec: FlaierSpec) {\n const metadata = getSpecMetadata(spec);\n let changed = false;\n\n flowDocuments.value = flowDocuments.value.map((flow) => {\n if (flow.id !== flowId) return flow;\n\n const nextTitle = flow.title ?? metadata.title;\n const nextDescription = flow.description ?? metadata.description;\n\n if (nextTitle === flow.title && nextDescription === flow.description) {\n return flow;\n }\n\n changed = true;\n return {\n ...flow,\n title: nextTitle,\n description: nextDescription,\n };\n });\n\n if (changed) {\n syncFlowOptions();\n }\n}\n\nfunction getSpecMetadata(spec: FlaierSpec) {\n const rootElement = spec.elements[spec.root];\n const rootProps = isObject(rootElement?.props) ? rootElement.props : {};\n const title = toOptionalString(rootProps.title);\n const description = toOptionalString(rootProps.description);\n const fallbackId = toOptionalString(spec.root) ?? \"flow\";\n\n return {\n id: slugifyId(title ?? fallbackId),\n title,\n description,\n };\n}\n\nfunction applyThemeModeOverride(spec: FlaierSpec): FlaierSpec {\n const override = props.themeMode;\n if (!override) {\n return spec;\n }\n\n const rootElement = spec.elements[spec.root];\n if (!rootElement || rootElement.type !== \"FlowTimeline\" || !isObject(rootElement.props)) {\n return spec;\n }\n\n if (rootElement.props.themeMode === override) {\n return spec;\n }\n\n return {\n ...spec,\n elements: {\n ...spec.elements,\n [spec.root]: {\n ...rootElement,\n props: {\n ...rootElement.props,\n themeMode: override,\n },\n },\n },\n };\n}\n\nfunction slugifyId(value: string) {\n const slug = value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n return slug || \"flow\";\n}\n\nfunction resolveRelativeSource(value: string, baseUrl?: string) {\n if (!baseUrl) return value;\n\n try {\n return new URL(value, baseUrl).toString();\n } catch {\n return value;\n }\n}\n\nfunction createFetchCandidates(source: string) {\n const trimmed = source.trim();\n if (!trimmed) return [];\n\n const hasJsonSuffix = /\\.json(?:[?#].*)?$/i.test(trimmed);\n const candidates: string[] = [trimmed];\n\n if (!hasJsonSuffix && !isLikelyFlowSpecEndpoint(trimmed)) {\n candidates.push(appendManifestJsonPath(trimmed));\n }\n\n return Array.from(new Set(candidates));\n}\n\nfunction isLikelyFlowSpecEndpoint(value: string) {\n return /\\/api\\/flows\\/spec\\/[^/?#]+(?:[?#].*)?$/i.test(value);\n}\n\nfunction appendManifestJsonPath(value: string) {\n const hashSplit = value.split(\"#\", 2);\n const pathAndQuery = hashSplit[0] ?? \"\";\n const hash = hashSplit[1] ?? \"\";\n\n const querySplit = pathAndQuery.split(\"?\", 2);\n const path = querySplit[0] ?? \"\";\n const query = querySplit[1] ?? \"\";\n\n const normalizedPath = path.endsWith(\"/\") ? path : `${path}/`;\n const manifestPath = `${normalizedPath}manifest.json`;\n const withQuery = query ? `${manifestPath}?${query}` : manifestPath;\n\n return hash ? `${withQuery}#${hash}` : withQuery;\n}\n\nasync function fetchJsonSource(source: string) {\n const candidates = createFetchCandidates(source);\n\n if (candidates.length === 0) {\n throw new Error(\"Flow source path cannot be empty.\");\n }\n\n let lastError: Error | null = null;\n\n for (const candidate of candidates) {\n try {\n const response = await fetch(candidate);\n if (!response.ok) {\n lastError = new Error(\n `Failed to fetch \"${candidate}\" (${response.status} ${response.statusText})`,\n );\n continue;\n }\n\n const payload = (await response.json()) as unknown;\n\n return {\n payload,\n resolvedUrl: resolveRelativeSource(\n candidate,\n typeof window !== \"undefined\" ? window.location.href : undefined,\n ),\n };\n } catch (error) {\n lastError =\n error instanceof Error ? error : new Error(`Failed to load source \"${candidate}\".`);\n }\n }\n\n throw lastError ?? new Error(`Failed to load source \"${source}\".`);\n}\n\nfunction cloneSpec(spec: FlaierSpec): FlaierSpec {\n return JSON.parse(JSON.stringify(spec)) as FlaierSpec;\n}\n\nfunction isFlaierManifest(value: unknown): value is FlaierManifest {\n if (!isObject(value)) return false;\n return Array.isArray(value.flows);\n}\n\nfunction isFlaierSpec(value: unknown): value is FlaierSpec {\n if (!isObject(value)) return false;\n if (typeof value.root !== \"string\") return false;\n if (!isObject(value.elements)) return false;\n return true;\n}\n\nfunction toOptionalString(value: unknown) {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\nfunction toStringArray(value: unknown) {\n if (!Array.isArray(value)) return undefined;\n\n const result = value.filter(\n (entry): entry is string => typeof entry === \"string\" && entry.length > 0,\n );\n return result.length > 0 ? result : undefined;\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction handleStateChange(changes: Array<{ path: string; value: unknown }>) {\n emit(\"state-change\", changes);\n}\n</script>\n\n<template>\n <div class=\"flaier relative h-full w-full min-h-[320px]\">\n <div\n v-if=\"loading\"\n class=\"flex h-full w-full items-center justify-center text-sm text-muted-foreground\"\n >\n Loading flow spec...\n </div>\n\n <div\n v-else-if=\"loadError\"\n class=\"flex h-full w-full items-center justify-center px-6 text-center text-sm text-red-300\"\n >\n {{ loadError }}\n </div>\n\n <StateProvider\n v-else-if=\"resolvedSpec\"\n :key=\"providerKey\"\n :initial-state=\"initialState\"\n :on-state-change=\"handleStateChange\"\n >\n <ActionProvider>\n <VisibilityProvider>\n <Renderer :spec=\"resolvedSpec\" :registry=\"rendererRegistry\" />\n </VisibilityProvider>\n </ActionProvider>\n </StateProvider>\n </div>\n</template>\n","import { onUnmounted, ref, watch } from \"vue\";\n\nexport function useFlaierFullscreen() {\n const fullscreen = ref(false);\n let previousBodyOverflow = \"\";\n\n function closeFullscreen() {\n fullscreen.value = false;\n }\n\n function toggleFullscreen() {\n fullscreen.value = !fullscreen.value;\n }\n\n function handleEscape(event: KeyboardEvent) {\n if (event.key !== \"Escape\") return;\n closeFullscreen();\n }\n\n watch(fullscreen, (active) => {\n if (typeof document === \"undefined\") return;\n\n if (active) {\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n document.addEventListener(\"keydown\", handleEscape);\n return;\n }\n\n document.body.style.overflow = previousBodyOverflow;\n document.removeEventListener(\"keydown\", handleEscape);\n });\n\n onUnmounted(() => {\n if (typeof document === \"undefined\") return;\n\n document.body.style.overflow = previousBodyOverflow;\n document.removeEventListener(\"keydown\", handleEscape);\n });\n\n return {\n fullscreen,\n closeFullscreen,\n toggleFullscreen,\n };\n}\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from \"vue\";\nimport Flaier from \"./Flaier.vue\";\nimport { useFlaierFullscreen } from \"../composables/useFlaierFullscreen\";\nimport type { FlaierPanelProps } from \"../types\";\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(defineProps<FlaierPanelProps>(), {\n autoPlay: false,\n interval: 3000,\n height: \"min(72vh, 760px)\",\n minHeight: 420,\n zIndex: 1400,\n fullscreenEnabled: true,\n});\n\nconst { fullscreen, closeFullscreen, toggleFullscreen } = useFlaierFullscreen();\n\nconst fullscreenActive = computed(() => props.fullscreenEnabled && fullscreen.value);\nconst viewportResetToken = ref(0);\n\nconst containerStyle = computed<Record<string, string>>(() => {\n const minHeight = Number.isFinite(props.minHeight)\n ? Math.max(280, Math.floor(props.minHeight))\n : 420;\n\n return {\n \"--fn-panel-height\":\n typeof props.height === \"number\"\n ? `${Math.max(280, Math.floor(props.height))}px`\n : props.height,\n \"--fn-panel-min-height\": `${minHeight}px`,\n \"--fn-panel-z-index\": String(props.zIndex),\n };\n});\n\nwatch(\n () => props.fullscreenEnabled,\n (enabled) => {\n if (!enabled && fullscreen.value) {\n closeFullscreen();\n }\n },\n);\n\nwatch(\n fullscreenActive,\n () => {\n viewportResetToken.value += 1;\n },\n { flush: \"post\" },\n);\n</script>\n\n<template>\n <Teleport to=\"body\" :disabled=\"!fullscreenActive\">\n <div\n class=\"fn-panel\"\n :class=\"{ 'fn-panel--fullscreen': fullscreenActive }\"\n :style=\"containerStyle\"\n v-bind=\"$attrs\"\n >\n <button\n v-if=\"fullscreenActive\"\n type=\"button\"\n class=\"fn-panel__backdrop\"\n aria-label=\"Exit fullscreen\"\n @click=\"closeFullscreen\"\n />\n\n <div class=\"fn-panel__surface\">\n <Flaier\n class=\"fn-panel__viewer\"\n :src=\"src\"\n :auto-play=\"autoPlay\"\n :interval=\"interval\"\n :theme-mode=\"themeMode\"\n :nodes=\"nodes\"\n :viewport-reset-token=\"viewportResetToken\"\n />\n\n <button\n v-if=\"fullscreenEnabled\"\n type=\"button\"\n class=\"fn-panel__toggle\"\n :aria-label=\"fullscreenActive ? 'Exit fullscreen' : 'Enter fullscreen'\"\n :title=\"fullscreenActive ? 'Exit fullscreen' : 'Enter fullscreen'\"\n @click=\"toggleFullscreen\"\n >\n <svg\n v-if=\"!fullscreenActive\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.8\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"15 3 21 3 21 9\" />\n <polyline points=\"9 21 3 21 3 15\" />\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n\n <svg\n v-else\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.8\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"14 10 21 3\" />\n <polyline points=\"10 14 3 21\" />\n <polyline points=\"3 9 3 3 9 3\" />\n <polyline points=\"15 21 21 21 21 15\" />\n </svg>\n </button>\n </div>\n </div>\n </Teleport>\n</template>\n\n<style scoped>\n.fn-panel {\n --fn-panel-height: min(72vh, 760px);\n --fn-panel-min-height: 420px;\n --fn-panel-z-index: 1400;\n --fn-panel-toggle-border: rgba(148, 163, 184, 0.5);\n --fn-panel-toggle-bg: rgba(15, 23, 42, 0.82);\n --fn-panel-toggle-color: rgba(226, 232, 240, 0.95);\n --fn-panel-toggle-shadow: 0 10px 26px rgba(15, 23, 42, 0.24);\n --fn-panel-toggle-hover-border: rgba(125, 211, 252, 0.7);\n --fn-panel-toggle-hover-bg: rgba(15, 23, 42, 0.96);\n --fn-panel-backdrop-bg: rgba(2, 6, 23, 0.72);\n position: relative;\n width: 100%;\n}\n\n.fn-panel__surface {\n position: relative;\n width: 100%;\n height: var(--fn-panel-height);\n min-height: var(--fn-panel-min-height);\n overflow: hidden;\n isolation: isolate;\n}\n\n.fn-panel__viewer {\n width: 100%;\n height: 100%;\n}\n\n.fn-panel__toggle {\n position: absolute;\n left: 0.95rem;\n bottom: 0.95rem;\n width: 2.3rem;\n height: 2.3rem;\n border: 1px solid var(--fn-panel-toggle-border);\n border-radius: 0.65rem;\n background: var(--fn-panel-toggle-bg);\n color: var(--fn-panel-toggle-color);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n z-index: 40;\n box-shadow: var(--fn-panel-toggle-shadow);\n transition:\n transform 0.18s ease,\n background-color 0.2s ease,\n border-color 0.2s ease;\n}\n\n.fn-panel__toggle:hover {\n transform: translateY(-1px);\n border-color: var(--fn-panel-toggle-hover-border);\n background: var(--fn-panel-toggle-hover-bg);\n}\n\n.fn-panel__toggle svg {\n width: 1rem;\n height: 1rem;\n}\n\n.fn-panel--fullscreen {\n position: fixed;\n inset: 0;\n z-index: var(--fn-panel-z-index);\n display: grid;\n place-items: center;\n padding: 1rem;\n}\n\n.fn-panel__backdrop {\n position: absolute;\n inset: 0;\n border: none;\n background: var(--fn-panel-backdrop-bg);\n cursor: default;\n}\n\n.fn-panel--fullscreen .fn-panel__surface {\n width: min(1480px, 100%);\n height: min(94vh, 1020px);\n max-height: 100%;\n z-index: 1;\n}\n\n@media (max-width: 900px) {\n .fn-panel--fullscreen {\n padding: 0.55rem;\n }\n\n .fn-panel--fullscreen .fn-panel__surface {\n width: 100%;\n height: 100%;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from \"vue\";\nimport Flaier from \"./Flaier.vue\";\nimport { useFlaierFullscreen } from \"../composables/useFlaierFullscreen\";\nimport type { FlaierPanelProps } from \"../types\";\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(defineProps<FlaierPanelProps>(), {\n autoPlay: false,\n interval: 3000,\n height: \"min(72vh, 760px)\",\n minHeight: 420,\n zIndex: 1400,\n fullscreenEnabled: true,\n});\n\nconst { fullscreen, closeFullscreen, toggleFullscreen } = useFlaierFullscreen();\n\nconst fullscreenActive = computed(() => props.fullscreenEnabled && fullscreen.value);\nconst viewportResetToken = ref(0);\n\nconst containerStyle = computed<Record<string, string>>(() => {\n const minHeight = Number.isFinite(props.minHeight)\n ? Math.max(280, Math.floor(props.minHeight))\n : 420;\n\n return {\n \"--fn-panel-height\":\n typeof props.height === \"number\"\n ? `${Math.max(280, Math.floor(props.height))}px`\n : props.height,\n \"--fn-panel-min-height\": `${minHeight}px`,\n \"--fn-panel-z-index\": String(props.zIndex),\n };\n});\n\nwatch(\n () => props.fullscreenEnabled,\n (enabled) => {\n if (!enabled && fullscreen.value) {\n closeFullscreen();\n }\n },\n);\n\nwatch(\n fullscreenActive,\n () => {\n viewportResetToken.value += 1;\n },\n { flush: \"post\" },\n);\n</script>\n\n<template>\n <Teleport to=\"body\" :disabled=\"!fullscreenActive\">\n <div\n class=\"fn-panel\"\n :class=\"{ 'fn-panel--fullscreen': fullscreenActive }\"\n :style=\"containerStyle\"\n v-bind=\"$attrs\"\n >\n <button\n v-if=\"fullscreenActive\"\n type=\"button\"\n class=\"fn-panel__backdrop\"\n aria-label=\"Exit fullscreen\"\n @click=\"closeFullscreen\"\n />\n\n <div class=\"fn-panel__surface\">\n <Flaier\n class=\"fn-panel__viewer\"\n :src=\"src\"\n :auto-play=\"autoPlay\"\n :interval=\"interval\"\n :theme-mode=\"themeMode\"\n :nodes=\"nodes\"\n :viewport-reset-token=\"viewportResetToken\"\n />\n\n <button\n v-if=\"fullscreenEnabled\"\n type=\"button\"\n class=\"fn-panel__toggle\"\n :aria-label=\"fullscreenActive ? 'Exit fullscreen' : 'Enter fullscreen'\"\n :title=\"fullscreenActive ? 'Exit fullscreen' : 'Enter fullscreen'\"\n @click=\"toggleFullscreen\"\n >\n <svg\n v-if=\"!fullscreenActive\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.8\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"15 3 21 3 21 9\" />\n <polyline points=\"9 21 3 21 3 15\" />\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n\n <svg\n v-else\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.8\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"14 10 21 3\" />\n <polyline points=\"10 14 3 21\" />\n <polyline points=\"3 9 3 3 9 3\" />\n <polyline points=\"15 21 21 21 21 15\" />\n </svg>\n </button>\n </div>\n </div>\n </Teleport>\n</template>\n\n<style scoped>\n.fn-panel {\n --fn-panel-height: min(72vh, 760px);\n --fn-panel-min-height: 420px;\n --fn-panel-z-index: 1400;\n --fn-panel-toggle-border: rgba(148, 163, 184, 0.5);\n --fn-panel-toggle-bg: rgba(15, 23, 42, 0.82);\n --fn-panel-toggle-color: rgba(226, 232, 240, 0.95);\n --fn-panel-toggle-shadow: 0 10px 26px rgba(15, 23, 42, 0.24);\n --fn-panel-toggle-hover-border: rgba(125, 211, 252, 0.7);\n --fn-panel-toggle-hover-bg: rgba(15, 23, 42, 0.96);\n --fn-panel-backdrop-bg: rgba(2, 6, 23, 0.72);\n position: relative;\n width: 100%;\n}\n\n.fn-panel__surface {\n position: relative;\n width: 100%;\n height: var(--fn-panel-height);\n min-height: var(--fn-panel-min-height);\n overflow: hidden;\n isolation: isolate;\n}\n\n.fn-panel__viewer {\n width: 100%;\n height: 100%;\n}\n\n.fn-panel__toggle {\n position: absolute;\n left: 0.95rem;\n bottom: 0.95rem;\n width: 2.3rem;\n height: 2.3rem;\n border: 1px solid var(--fn-panel-toggle-border);\n border-radius: 0.65rem;\n background: var(--fn-panel-toggle-bg);\n color: var(--fn-panel-toggle-color);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n z-index: 40;\n box-shadow: var(--fn-panel-toggle-shadow);\n transition:\n transform 0.18s ease,\n background-color 0.2s ease,\n border-color 0.2s ease;\n}\n\n.fn-panel__toggle:hover {\n transform: translateY(-1px);\n border-color: var(--fn-panel-toggle-hover-border);\n background: var(--fn-panel-toggle-hover-bg);\n}\n\n.fn-panel__toggle svg {\n width: 1rem;\n height: 1rem;\n}\n\n.fn-panel--fullscreen {\n position: fixed;\n inset: 0;\n z-index: var(--fn-panel-z-index);\n display: grid;\n place-items: center;\n padding: 1rem;\n}\n\n.fn-panel__backdrop {\n position: absolute;\n inset: 0;\n border: none;\n background: var(--fn-panel-backdrop-bg);\n cursor: default;\n}\n\n.fn-panel--fullscreen .fn-panel__surface {\n width: min(1480px, 100%);\n height: min(94vh, 1020px);\n max-height: 100%;\n z-index: 1;\n}\n\n@media (max-width: 900px) {\n .fn-panel--fullscreen {\n padding: 0.55rem;\n }\n\n .fn-panel--fullscreen .fn-panel__surface {\n width: 100%;\n height: 100%;\n }\n}\n</style>\n","import { computed, watch, onUnmounted, ref } from \"vue\";\nimport type { Ref } from \"vue\";\n\ninterface TimelineOptions {\n totalSteps: Ref<number>;\n interval?: number;\n}\n\n/**\n * Timeline playback controls.\n * Manages currentStep, playing state, and auto-advance logic.\n */\nexport function useTimeline(options: TimelineOptions) {\n const { totalSteps, interval = 3000 } = options;\n\n const currentStep = ref(0);\n const playing = ref(false);\n\n let timer: ReturnType<typeof setInterval> | null = null;\n\n function clearTimer() {\n if (timer !== null) {\n clearInterval(timer);\n timer = null;\n }\n }\n\n watch(playing, (isPlaying) => {\n clearTimer();\n if (isPlaying) {\n timer = setInterval(() => {\n if (currentStep.value < totalSteps.value - 1) {\n currentStep.value++;\n } else {\n playing.value = false;\n }\n }, interval);\n }\n });\n\n onUnmounted(clearTimer);\n\n const progress = computed(() =>\n totalSteps.value > 1 ? currentStep.value / (totalSteps.value - 1) : 0,\n );\n\n return {\n currentStep,\n playing,\n totalSteps,\n progress,\n\n next() {\n if (currentStep.value < totalSteps.value - 1) {\n currentStep.value++;\n }\n },\n prev() {\n if (currentStep.value > 0) {\n currentStep.value--;\n }\n },\n goTo(step: number) {\n currentStep.value = Math.max(0, Math.min(step, totalSteps.value - 1));\n },\n togglePlay() {\n playing.value = !playing.value;\n },\n };\n}\n"],"mappings":"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"}