@visualli/react 0.1.7 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +13 -5
  2. package/dist/index.cjs +1900 -2033
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +354 -97
  5. package/dist/index.d.ts +354 -97
  6. package/dist/index.js +2005 -2095
  7. package/dist/index.js.map +1 -1
  8. package/fonts/Caveat-Variable.ttf +0 -0
  9. package/licenses/visualli-design-system/LICENSE +9 -0
  10. package/licenses/visualli-design-system/NOTICE.md +6 -0
  11. package/package.json +9 -4
  12. package/src/VisualliCanvas.tsx +452 -409
  13. package/src/VisualliRenderer.tsx +90 -112
  14. package/src/components/A11yLayer.tsx +73 -0
  15. package/src/components/KonvaContainer.tsx +28 -237
  16. package/src/components/KonvaContainerLabelLayer.tsx +41 -0
  17. package/src/components/KonvaContainerLayer.tsx +34 -33
  18. package/src/components/KonvaEdge.tsx +25 -240
  19. package/src/components/KonvaEdgeLayer.tsx +69 -49
  20. package/src/components/KonvaNode.tsx +21 -156
  21. package/src/components/KonvaNodeLayer.tsx +102 -34
  22. package/src/components/KonvaStage.tsx +17 -3
  23. package/src/components/NavigationStack.tsx +16 -159
  24. package/src/components/Overlays.tsx +327 -0
  25. package/src/components/ZoomControls.tsx +3 -107
  26. package/src/components/useFrames.ts +30 -0
  27. package/src/context/VisualliContext.tsx +3 -3
  28. package/src/design/choreography.ts +157 -0
  29. package/src/design/containers.ts +150 -0
  30. package/src/design/design.ts +115 -0
  31. package/src/design/drawing.ts +303 -0
  32. package/src/design/measure.ts +34 -0
  33. package/src/design/runtime.ts +154 -0
  34. package/src/design/useDesign.ts +38 -0
  35. package/src/generated/specCss.ts +15 -0
  36. package/src/hooks/index.ts +0 -2
  37. package/src/hooks/useKonvaRenderer.ts +13 -18
  38. package/src/hooks/useLayerChoreography.ts +159 -0
  39. package/src/hooks/useViewportNodes.ts +0 -1
  40. package/src/index.ts +22 -22
  41. package/src/stores/stores.ts +2 -2
  42. package/src/stores/useViewportStore.ts +12 -2
  43. package/src/animations/index.ts +0 -2
  44. package/src/animations/konvaLayerTransition.ts +0 -223
  45. package/src/components/SketchyBoxKonva.tsx +0 -121
  46. package/src/config/blobShapes.ts +0 -204
  47. package/src/config/index.ts +0 -21
  48. package/src/config/textScaling.ts +0 -69
  49. package/src/hooks/useKonvaLayerTransition.ts +0 -221
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/VisualliRenderer.tsx","../src/VisualliCanvas.tsx","../src/stores/useNodeStore.ts","../src/stores/useViewportStore.ts","../src/stores/stores.ts","../src/hooks/useKonvaRenderer.ts","../src/hooks/useKonvaLayerTransition.ts","../src/animations/konvaLayerTransition.ts","../src/utils/layerNavigation.ts","../src/components/KonvaStage.tsx","../src/konvaCompat.ts","../src/components/KonvaNodeLayer.tsx","../src/hooks/useViewportNodes.ts","../src/components/KonvaNode.tsx","../src/config/index.ts","../src/config/blobShapes.ts","../src/components/KonvaEdgeLayer.tsx","../src/components/KonvaEdge.tsx","../src/components/KonvaContainerLayer.tsx","../src/components/KonvaContainer.tsx","../src/config/textScaling.ts","../src/components/NavigationStack.tsx","../src/components/ZoomControls.tsx","../src/components/SketchyBoxKonva.tsx","../src/context/VisualliContext.tsx"],"sourcesContent":["// ─── @visualli/react ─────────────────────────────────────────────────────────\n\n// ── Primary component (recommended for public use) ────────────────────────────────────────\nexport { default as VisualliRenderer } from './VisualliRenderer';\nexport type { VisualliRendererProps, VisualliTheme } from './VisualliRenderer';\n\n// ── Canvas component (for advanced integrations) ───────────────────────────────────────────\nexport { default as VisualliCanvas } from './VisualliCanvas';\nexport type { VisualliCanvasProps } from './VisualliCanvas';\n\n// ── Context and Provider ──────────────────────────────────────────────────────\nexport { VisualliProvider, useVisualli } from './context/VisualliContext';\nexport type { \n VisualliProviderProps, \n VisualliContextValue\n} from './context/VisualliContext';\n\n// Stores\nexport { useNodeStore } from './stores/useNodeStore';\nexport { useViewportStore } from './stores/useViewportStore';\nexport { useSelectionStore, useRenderConfigStore } from './stores/stores';\nexport type { INodeStore } from './stores/useNodeStore';\nexport type { IViewportStore } from './stores/useViewportStore';\n\n// Hooks\nexport { useKonvaRenderer } from './hooks/useKonvaRenderer';\nexport { useKonvaLayerTransition } from './hooks/useKonvaLayerTransition';\nexport { useViewportNodes } from './hooks/useViewportNodes';\nexport type { UseKonvaRendererOptions, UseKonvaRendererReturn } from './hooks/useKonvaRenderer';\nexport type { LayerTransitionHandlers } from './hooks/useKonvaLayerTransition';\n\n// Animations\nexport { KonvaLayerTransitionAnimator, konvaLayerTransitionAnimator } from './animations/konvaLayerTransition';\nexport type { AnimatorViewport, TransitionCallbacks } from './animations/konvaLayerTransition';\n\n// Config helpers\nexport {\n ALL_BLOB_SHAPES,\n ACTIVE_BLOB_TYPES,\n BLOB_LAYER_CONFIG,\n NODE_LAYER_CONFIG,\n getBlobTypeForLayer,\n BLOB_TEXT_OFFSETS,\n drawBlobPath,\n buildBlobPathData,\n NODE_TEXT_BASE_FONT_PX,\n DESCRIPTION_TEXT_BASE_FONT_PX,\n computeNodeTextWorldScale,\n computeNodeTextScreenScale,\n computeOverlayScale,\n computeEdgeLabelScale,\n} from './config';\n\n// Utils\nexport {\n getConnectionsForLayer,\n getChildLayerForNode,\n getLayerForNavigation,\n calculateFitZoom,\n calculateFitCenter,\n calculateFitView,\n} from './utils/layerNavigation';\nexport type { FitResult } from './utils/layerNavigation';\n\n// Sub-components (for advanced usage / composition)\nexport { default as KonvaStage } from './components/KonvaStage';\nexport { default as KonvaNode } from './components/KonvaNode';\nexport { default as KonvaEdge } from './components/KonvaEdge';\nexport { default as KonvaNodeLayer } from './components/KonvaNodeLayer';\nexport { default as KonvaEdgeLayer } from './components/KonvaEdgeLayer';\nexport { default as KonvaContainer } from './components/KonvaContainer';\nexport { default as KonvaContainerLayer } from './components/KonvaContainerLayer';\nexport { default as NavigationStack } from './components/NavigationStack';\nexport { default as ZoomControls } from './components/ZoomControls';\nexport { default as SketchyBoxKonva } from './components/SketchyBoxKonva';\nexport type { NavStackEntry } from './components/NavigationStack';\nexport type { KonvaNodeProps } from './components/KonvaNode';\nexport type { KonvaEdgeProps } from './components/KonvaEdge';\nexport type { KonvaStageProps } from './components/KonvaStage';\nexport type { ContainerGroup } from './components/KonvaContainerLayer';\n\n","// ─── VisualliRenderer ────────────────────────────────────────────────────────\n//\n// The single public-facing component for rendering a .visualli document.\n//\n// <VisualliRenderer visualliString={str} theme=\"dark\" width=\"100%\" height=\"600px\" />\n// <VisualliRenderer visualliFile={file} theme=\"auto\" width={800} height={600} />\n// <VisualliRenderer document={doc} theme=\"auto\" width={800} height={600} />\n//\n// Handles:\n// • theme: 'dark' | 'light' | 'auto' — auto follows prefers-color-scheme\n// • width / height as first-class props (CSS string or pixel number)\n// • Empty state — no data prop provided\n// • Loading state — while parsing a .visualli file/string\n// • Error state — parse failure with message\n// • useWorker — offload parsing to a Web Worker (default: false)\n// • Delegates all canvas/navigation/zoom logic to VisualliCanvas\n\nimport React, { useEffect, useRef, useState, useMemo } from 'react';\nimport type { VisualliDocument, VisualliLayer, FlatNode } from '@visualli/core';\nimport { parseVisualliFile } from '@visualli/core';\nimport VisualliCanvas from './VisualliCanvas';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type VisualliTheme = 'dark' | 'light' | 'auto';\n\nexport interface VisualliRendererProps {\n /**\n * Raw JSONL string — the content of a .visualli file.\n * Simply pass the string data directly, no preprocessing needed.\n * Example: visualliString=\"{\\\"type\\\":\\\"meta\\\"...}\\n{\\\"type\\\":\\\"layer\\\"...}\"\n */\n visualliString?: string;\n\n /**\n * A .visualli file — can be:\n * - File object (e.g. from <input type=\"file\">)\n * - String path to file (e.g. '/data/myfile.visualli' or './src/data/data.visualli')\n * The renderer automatically fetches, reads, and parses it.\n * No user code required for conversion or processing.\n */\n visualliFile?: File | string;\n\n /**\n * When true, parsing is offloaded to a Web Worker so the main thread never\n * blocks during JSON.parse. Recommended for large documents (>500 nodes).\n * Has no effect when `document` is supplied (already parsed).\n * @default true\n */\n useWorker?: boolean;\n\n /**\n * Colour theme.\n * - 'dark' → always dark background\n * - 'light' → always light background\n * - 'auto' → follows the OS/browser prefers-color-scheme\n * @default 'light'\n */\n theme?: VisualliTheme;\n\n /**\n * Enable chromatic immersion background effect.\n * When true:\n * - Root layer (level 0) shows base background color\n * - Child layers show parent node's color as semi-transparent background\n * @default false\n */\n chromaticImmersion?: boolean;\n\n /**\n * Width of the renderer. Accepts any CSS length string ('100%', '800px', '100vw')\n * or a plain number treated as pixels.\n * @default '100%'\n */\n width?: string | number;\n\n /**\n * Height of the renderer. Accepts any CSS length string ('100%', '600px', '100vh')\n * or a plain number treated as pixels.\n * @default '100%'\n */\n height?: string | number;\n\n /** Additional CSS class on the root element. */\n className?: string;\n\n /** Additional inline styles merged onto the root element. */\n style?: React.CSSProperties;\n}\n\n// ── System dark-mode hook ─────────────────────────────────────────────────────\n\nfunction useSystemDark(): boolean {\n const mq = typeof window !== 'undefined'\n ? window.matchMedia('(prefers-color-scheme: dark)')\n : null;\n\n const [dark, setDark] = useState<boolean>(mq?.matches ?? false);\n\n useEffect(() => {\n if (!mq) return;\n const handler = (e: MediaQueryListEvent) => setDark(e.matches);\n mq.addEventListener('change', handler);\n return () => mq.removeEventListener('change', handler);\n }, [mq]);\n\n return dark;\n}\n\n// ── Font Injection Hook ───────────────────────────────────────────────────────\n\nfunction useFontInjection() {\n useEffect(() => {\n if (typeof document === 'undefined') return;\n \n const links = [\n 'https://fonts.googleapis.com',\n 'https://fonts.gstatic.com',\n 'https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800&family=Nunito+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300&display=swap',\n 'https://fonts.googleapis.com/css2?family=Playpen+Sans:wght@300;400;600;800&family=Story+Script:wght@400&display=swap'\n ];\n\n links.forEach((href, i) => {\n const id = `visualli-font-${i}`;\n if (!document.getElementById(id)) {\n const link = document.createElement('link');\n link.id = id;\n link.rel = i < 2 ? 'preconnect' : 'stylesheet';\n link.href = href;\n if (i === 1) link.crossOrigin = 'anonymous';\n document.head.appendChild(link);\n }\n });\n }, []);\n}\n\n// ── Empty / Loading / Error states ───────────────────────────────────────────\n\n// ── UI State Components ───────────────────────────────────────────────────────\n\nfunction EmptyState({ isDark }: { isDark: boolean }) {\n const bg = isDark ? '#131311' : '#F5F3EF';\n const fg = isDark ? 'rgba(240,237,230,0.35)' : 'rgba(26,26,24,0.35)';\n const bd = isDark ? '#2A2A28' : '#DDD9D0';\n const code = { fontFamily: 'monospace', fontSize: 12, padding: '1px 4px', borderRadius: 4, background: isDark ? '#222220' : '#E8E4DC', border: `1px solid ${bd}` };\n return (\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', width: '100%', height: '100%', gap: 16, background: bg, color: fg, fontFamily: \"'Nunito', system-ui, sans-serif\" }}>\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\" fill=\"none\" stroke={fg} strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"10\" y=\"6\" width=\"28\" height=\"36\" rx=\"3\" />\n <line x1=\"16\" y1=\"16\" x2=\"32\" y2=\"16\" />\n <line x1=\"16\" y1=\"22\" x2=\"32\" y2=\"22\" />\n <line x1=\"16\" y1=\"28\" x2=\"26\" y2=\"28\" />\n </svg>\n <div style={{ textAlign: 'center', lineHeight: 1.7 }}>\n <p style={{ margin: 0, fontSize: 15, fontWeight: 600, color: isDark ? 'rgba(240,237,230,0.7)' : 'rgba(26,26,24,0.7)' }}>\n No .visualli file provided\n </p>\n <p style={{ margin: '4px 0 0', fontSize: 13 }}>\n Pass a <code style={code}>visualliFile</code> or <code style={code}>visualliString</code> prop.\n </p>\n </div>\n </div>\n );\n}\n\nfunction LoadingState({ isDark }: { isDark: boolean }) {\n const bg = isDark ? '#131311' : '#F5F3EF';\n const fg = isDark ? 'rgba(240,237,230,0.5)' : 'rgba(26,26,24,0.5)';\n const dot = isDark ? 'rgba(240,237,230,0.6)' : 'rgba(26,26,24,0.45)';\n return (\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', width: '100%', height: '100%', gap: 16, background: bg, color: fg, fontFamily: \"'Nunito', system-ui, sans-serif\" }}>\n <div style={{ display: 'flex', gap: 8 }}>\n {[0, 1, 2].map(i => (\n <div key={i} style={{ width: 8, height: 8, borderRadius: '50%', background: dot, animation: `vr-pulse 1.2s ease-in-out ${i * 0.2}s infinite` }} />\n ))}\n </div>\n <style>{`@keyframes vr-pulse{0%,80%,100%{opacity:.2;transform:scale(.9)}40%{opacity:1;transform:scale(1.1)}}`}</style>\n <p style={{ margin: 0, fontSize: 14 }}>Loading .visualli file…</p>\n </div>\n );\n}\n\nfunction ErrorState({ message, isDark }: { message: string; isDark: boolean }) {\n const bg = isDark ? '#131311' : '#F5F3EF';\n const bd = isDark ? '#3a1f1f' : '#F0CECE';\n const card = isDark ? '#1e1212' : '#FFF5F5';\n const head = isDark ? '#F87171' : '#DC2626';\n const body = isDark ? 'rgba(248,113,113,0.8)' : 'rgba(180,40,40,0.8)';\n return (\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', width: '100%', height: '100%', padding: '24px', background: bg, fontFamily: \"'Nunito', system-ui, sans-serif\" }}>\n <div style={{ maxWidth: 480, width: '100%', padding: '20px 24px', borderRadius: 12, border: `1px solid ${bd}`, background: card }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12 }}>\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke={head} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"/>\n </svg>\n <span style={{ fontSize: 15, fontWeight: 700, color: head }}>Failed to parse .visualli file</span>\n </div>\n <p style={{ margin: 0, fontSize: 13, color: body, lineHeight: 1.6, wordBreak: 'break-word', fontFamily: 'monospace' }}>{message}</p>\n </div>\n </div>\n );\n}\n\n// ── Inline worker script ──────────────────────────────────────────────────────\n// Self-contained JSONL parser that mirrors parseVisualliFile.\n// Runs in a Web Worker when useWorker=true; no external imports needed.\n\nconst WORKER_SCRIPT = `\nself.onmessage = function(e) {\n var content = e.data;\n try {\n var lines = content.trim().split('\\\\n');\n var doc = {\n meta: null,\n layers: new Map(),\n layersByLevel: new Map(),\n rootLayer: null,\n };\n for (var i = 0; i < lines.length; i++) {\n var line = lines[i].trim();\n if (!line) continue;\n var obj;\n try { obj = JSON.parse(line); }\n catch(err) { throw new Error('Failed to parse JSON at line ' + (i+1) + ': ' + err); }\n if (!obj.type) throw new Error(\"Missing 'type' field at line \" + (i+1));\n if (obj.type === 'meta') {\n doc.meta = obj;\n } else if (obj.type === 'layer') {\n doc.layers.set(obj.id, obj);\n if (!doc.layersByLevel.has(obj.level)) doc.layersByLevel.set(obj.level, []);\n doc.layersByLevel.get(obj.level).push(obj);\n if (obj.level === 0) doc.rootLayer = obj;\n }\n }\n if (!doc.meta) throw new Error('Missing required meta section');\n if (!doc.rootLayer) throw new Error('Missing root layer (level 0)');\n self.postMessage({ ok: true, doc: doc });\n } catch(err) {\n self.postMessage({ ok: false, message: err.message || String(err) });\n }\n};\n`;\n\n// Lazy-create worker URL once (module-level singleton).\nlet _workerUrl: string | null = null;\nfunction getWorkerUrl(): string {\n if (!_workerUrl) {\n _workerUrl = URL.createObjectURL(new Blob([WORKER_SCRIPT], { type: 'text/javascript' }));\n }\n return _workerUrl;\n}\n\n// ── Parse hook ────────────────────────────────────────────────────────────────\n\ntype ParseState =\n | { status: 'idle' }\n | { status: 'loading' }\n | { status: 'ready'; doc: VisualliDocument }\n | { status: 'error'; message: string };\n\n/**\n * Resolves a raw string + optional File into a ParseState.\n * When useWorker=true the JSON.parse work runs in a Web Worker so the main\n * thread is never blocked, even for very large documents.\n */\nfunction useAsyncParse(\n content: string | undefined,\n useWorker: boolean,\n): ParseState {\n const [state, setState] = useState<ParseState>({ status: 'idle' });\n const workerRef = useRef<Worker | null>(null);\n\n useEffect(() => {\n if (!content) { setState({ status: 'idle' }); return; }\n\n setState({ status: 'loading' });\n let cancelled = false;\n\n if (useWorker && typeof Worker !== 'undefined') {\n // Terminate any previous worker\n workerRef.current?.terminate();\n const w = new Worker(getWorkerUrl());\n workerRef.current = w;\n\n w.onmessage = (e: MessageEvent) => {\n if (cancelled) return;\n if (e.data.ok) {\n setState({ status: 'ready', doc: e.data.doc as VisualliDocument });\n } else {\n setState({ status: 'error', message: e.data.message });\n }\n };\n w.onerror = (e: ErrorEvent) => {\n if (!cancelled) setState({ status: 'error', message: e.message });\n };\n w.postMessage(content);\n\n return () => {\n cancelled = true;\n w.terminate();\n workerRef.current = null;\n };\n }\n\n // Main-thread path: defer via microtask so React paints the loading state first\n Promise.resolve().then(() => {\n if (cancelled) return;\n try {\n const doc = parseVisualliFile(content);\n if (!cancelled) setState({ status: 'ready', doc });\n } catch (err) {\n if (!cancelled) setState({ status: 'error', message: err instanceof Error ? err.message : String(err) });\n }\n });\n return () => { cancelled = true; };\n }, [content, useWorker]);\n\n // Terminate worker on unmount\n useEffect(() => () => { workerRef.current?.terminate(); }, []);\n\n return state;\n}\n\n// ── File → string hook ────────────────────────────────────────────────────────\n\nfunction useFileText(file: File | string | undefined): { text: string | undefined; error: string | undefined; loading: boolean } {\n const [text, setText] = useState<string | undefined>(undefined);\n const [error, setError] = useState<string | undefined>(undefined);\n const [loading, setLoading] = useState(false);\n\n useEffect(() => {\n if (!file) { setText(undefined); setError(undefined); setLoading(false); return; }\n setLoading(true); setText(undefined); setError(undefined);\n let cancelled = false;\n\n // Handle string path - fetch the file\n if (typeof file === 'string') {\n fetch(file)\n .then(response => {\n if (!response.ok) throw new Error(`Failed to fetch file: ${response.statusText}`);\n return response.text();\n })\n .then(t => {\n if (!cancelled) { setText(t); setLoading(false); }\n })\n .catch((err: unknown) => {\n if (!cancelled) { setError(err instanceof Error ? err.message : String(err)); setLoading(false); }\n });\n }\n // Handle File object - read as text\n else {\n file.text().then(t => {\n if (!cancelled) { setText(t); setLoading(false); }\n }).catch((err: unknown) => {\n if (!cancelled) { setError(err instanceof Error ? err.message : String(err)); setLoading(false); }\n });\n }\n \n return () => { cancelled = true; };\n }, [file]);\n\n return { text, error, loading };\n}\n\n// ── VisualliRenderer ──────────────────────────────────────────────────────────\n\nexport default function VisualliRenderer({\n visualliString,\n visualliFile,\n theme = 'light',\n width = '100%',\n height = '100%',\n useWorker = true,\n chromaticImmersion = false,\n className,\n style,\n}: VisualliRendererProps) {\n useFontInjection();\n const systemDark = useSystemDark();\n const isDark = theme === 'dark' ? true : theme === 'light' ? false : systemDark;\n\n const cssWidth = typeof width === 'number' ? `${width}px` : width;\n const cssHeight = typeof height === 'number' ? `${height}px` : height;\n\n // Read File → text (no-op if not provided)\n const { text: fileText, error: fileReadError, loading: fileReading } = useFileText(visualliFile);\n\n // The raw JSONL string to parse: file takes priority over string prop\n const rawContent = fileText ?? visualliString;\n\n const parseState = useAsyncParse(rawContent, useWorker);\n\n const resolvedDoc: VisualliDocument | null = useMemo(() => {\n if (parseState.status === 'ready') return parseState.doc;\n return null;\n }, [parseState]);\n\n const wrapperStyle: React.CSSProperties = { width: cssWidth, height: cssHeight, overflow: 'hidden', ...style };\n\n // ── Empty state ─────────────────────────────────────────────────────────────\n if (!visualliString && !visualliFile) {\n return <div className={className} style={wrapperStyle}><EmptyState isDark={isDark} /></div>;\n }\n\n // ── Loading state ───────────────────────────────────────────────────────────\n if (fileReading || parseState.status === 'loading') {\n return <div className={className} style={wrapperStyle}><LoadingState isDark={isDark} /></div>;\n }\n\n // ── Error state ─────────────────────────────────────────────────────────────\n if (fileReadError || parseState.status === 'error') {\n const msg = fileReadError ?? (parseState.status === 'error' ? parseState.message : 'Unknown error');\n return <div className={className} style={wrapperStyle}><ErrorState message={msg} isDark={isDark} /></div>;\n }\n\n // ── Canvas ──────────────────────────────────────────────────────────────────\n return (\n <div className={className} style={wrapperStyle}>\n <VisualliCanvas\n preParsedVisualli={resolvedDoc ?? undefined}\n isDark={isDark}\n chromaticImmersion={chromaticImmersion}\n style={{ width: '100%', height: '100%' }}\n />\n </div>\n );\n}\n","// ─── VisualliCanvas ───────────────────────────────────────────────────────────\n//\n// Main canvas component for rendering a VisualliDocument.\n// Matches the visualli.ai enhanced canvas implementation:\n// • Stage-level hit detection via RBush spatial index (no Konva hit-canvas)\n// • Node description tooltip (sketchy-box style)\n// • Chromatic immersion background (color from current node)\n// • Auto-zoom navigation (zoom in → child layer, zoom out → parent layer)\n// • Professional layer transitions (zoom in / zoom out animations)\n// • Vertical left-side navigation stack\n// • Zoom controls (icon-based, top-right)\n// • Context menu (right-click to go back)\n//\n// NOT included (SDK-only, no generation UI):\n// • Sidebar, search, generation\n// • Semantic anchor tooltips (special word meanings)\n// • Branding logo\n// • Help overlay / view-source panel\n\nimport React, { useRef, useState, useCallback, useEffect, useMemo, useLayoutEffect } from 'react';\nimport type Konva from 'konva';\nimport type { VisualliDocument, VisualliLayer, FlatNode, MindMapConnection } from '@visualli/core';\nimport {\n parseVisualliFile,\n getNodesForLayer,\n getThemeBackground,\n darkenHexColor,\n RBushSpatialIndex,\n NODE_HEIGHT,\n TEXT_LABEL_HIDE_BELOW_ZOOM,\n ZOOM_NAV_IN_THRESHOLD,\n ZOOM_NAV_OUT_THRESHOLD,\n ZOOM_MIN,\n} from '@visualli/core';\n\nimport { useNodeStore } from './stores/useNodeStore';\nimport { useViewportStore } from './stores/useViewportStore';\nimport { useSelectionStore } from './stores/stores';\n\nimport { useKonvaRenderer } from './hooks/useKonvaRenderer';\nimport { useKonvaLayerTransition } from './hooks/useKonvaLayerTransition';\n\nimport KonvaStage from './components/KonvaStage';\nimport KonvaNodeLayer from './components/KonvaNodeLayer';\nimport KonvaEdgeLayer from './components/KonvaEdgeLayer';\nimport KonvaContainerLayer from './components/KonvaContainerLayer';\nimport NavigationStack, { type NavStackEntry } from './components/NavigationStack';\nimport ZoomControls from './components/ZoomControls';\nimport SketchyBoxKonva from './components/SketchyBoxKonva';\n\nimport { getChildLayerForNode, calculateFitView, getConnectionsForLayer, getContainersForLayer } from './utils/layerNavigation';\nimport type { ContainerGroup } from './components/KonvaContainerLayer';\nimport type { AnimatorViewport } from './animations/konvaLayerTransition';\nimport { DESCRIPTION_TEXT_BASE_FONT_PX } from './config/textScaling';\nimport { useVisualli } from './context/VisualliContext';\n\n// Helper to convert hex color to rgba with transparency\nfunction hexToRgba(hex: string, alpha: number): string {\n // Remove # if present\n hex = hex.replace(/^#/, '');\n \n // Parse hex values\n let r: number, g: number, b: number;\n if (hex.length === 3) {\n r = parseInt(hex[0] + hex[0], 16);\n g = parseInt(hex[1] + hex[1], 16);\n b = parseInt(hex[2] + hex[2], 16);\n } else if (hex.length === 6) {\n r = parseInt(hex.substring(0, 2), 16);\n g = parseInt(hex.substring(2, 4), 16);\n b = parseInt(hex.substring(4, 6), 16);\n } else {\n return `rgba(240, 237, 230, ${alpha})`; // fallback\n }\n \n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction resolveDocument(props: VisualliCanvasProps, fileText?: string): VisualliDocument | null {\n if (props.preParsedVisualli) return props.preParsedVisualli;\n const rawContent = fileText ?? props.visualliString;\n if (rawContent) {\n try { return parseVisualliFile(rawContent); } catch { return null; }\n }\n return null;\n}\n\nfunction layerLabel(doc: VisualliDocument, layer: VisualliLayer, layerId: string): string {\n if (layer.parentNodeId) {\n // Find the parent node in the parent layer to get its title\n const parentLayer = layer.parentLayerId ? doc.layers.get(layer.parentLayerId) : null;\n if (parentLayer) {\n const parentNode = parentLayer.nodes.find(n => n.id === layer.parentNodeId);\n if (parentNode) {\n return Array.isArray(parentNode.data.label)\n ? (parentNode.data.label as string[]).join(' ')\n : (parentNode.data.label || 'Untitled');\n }\n }\n }\n return layer.description ?? layerId;\n}\n\nfunction getRootLayerId(doc: VisualliDocument): string | null {\n for (const [id, layer] of doc.layers) {\n if (!layer.parentLayerId) return id;\n }\n return doc.layers.keys().next().value ?? null;\n}\n\n// ── Props ─────────────────────────────────────────────────────────────────────\n\nexport interface VisualliCanvasProps {\n preParsedVisualli?: VisualliDocument;\n /**\n * Raw JSONL string — just pass the string data directly.\n * No preprocessing needed by user.\n */\n visualliString?: string;\n /**\n * A .visualli file — can be:\n * - File object (from file input)\n * - String path to file (e.g. '/data/file.visualli')\n * Component handles all fetching and parsing automatically.\n */\n visualliFile?: File | string;\n isDark?: boolean;\n chromaticImmersion?: boolean;\n onNodeClick?: (node: FlatNode) => void;\n onLayerChange?: (layerId: string, layer: VisualliLayer) => void;\n onNodeHover?: (nodeId: string | null) => void;\n \n // Extension points for private features (implement in consuming app)\n renderOverlay?: (params: { isDark: boolean; containerWidth: number; containerHeight: number }) => React.ReactNode;\n renderNodeContent?: (params: { \n summary: string; \n nodeId: string; \n nodeColor?: string;\n zoom: number;\n }) => React.ReactNode;\n navigationStackTop?: string;\n navigationStackLeft?: string;\n \n className?: string;\n style?: React.CSSProperties;\n}\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport default function VisualliCanvas(props: VisualliCanvasProps) {\n const { isDark = false, chromaticImmersion = false, onNodeClick, onLayerChange, onNodeHover, renderOverlay, renderNodeContent, navigationStackTop = '16px', navigationStackLeft = '16px', className = '', style } = props;\n\n // Read file if provided (handles both File objects and string paths)\n const [fileText, setFileText] = useState<string | undefined>(undefined);\n useEffect(() => {\n if (!props.visualliFile) { setFileText(undefined); return; }\n let cancelled = false;\n \n // Handle string path - fetch the file\n if (typeof props.visualliFile === 'string') {\n fetch(props.visualliFile)\n .then(response => {\n if (!response.ok) throw new Error(`Failed to fetch: ${response.statusText}`);\n return response.text();\n })\n .then(t => {\n if (!cancelled) setFileText(t);\n })\n .catch(() => {\n if (!cancelled) setFileText(undefined);\n });\n }\n // Handle File object - read as text\n else {\n props.visualliFile.text().then(t => {\n if (!cancelled) setFileText(t);\n }).catch(() => {\n if (!cancelled) setFileText(undefined);\n });\n }\n \n return () => { cancelled = true; };\n }, [props.visualliFile]);\n\n const doc = useMemo(() => resolveDocument(props, fileText), [props.preParsedVisualli, props.visualliString, props.visualliFile, fileText]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // ── Navigation ────────────────────────────────────────────────────────────\n const [navStack, setNavStack] = useState<NavStackEntry[]>([]);\n const [currentLayerId, setCurrentLayerId] = useState<string | null>(null);\n const parentViewports = useRef<AnimatorViewport[]>([]);\n const [isTransitioning, setIsTransitioning] = useState(false);\n const isTransitioningRef = useRef(false);\n\n useEffect(() => {\n if (!doc) return;\n const rootId = getRootLayerId(doc);\n if (!rootId) return;\n const rootLayer = doc.layers.get(rootId)!;\n setCurrentLayerId(rootId);\n setNavStack([{ layerId: rootId, layer: rootLayer, label: 'Home' }]);\n parentViewports.current = [];\n }, [doc]);\n\n // ── Active layer → FlatNodes ──────────────────────────────────────────────\n const { flatNodes, connections, containers } = useMemo(() => {\n if (!doc || !currentLayerId) return { flatNodes: [] as FlatNode[], connections: [] as MindMapConnection[], containers: [] as ContainerGroup[] };\n try {\n return {\n flatNodes: getNodesForLayer(doc, currentLayerId),\n connections: getConnectionsForLayer(doc, currentLayerId),\n containers: getContainersForLayer(doc, currentLayerId) as ContainerGroup[],\n };\n } catch { return { flatNodes: [] as FlatNode[], connections: [] as MindMapConnection[], containers: [] as ContainerGroup[] }; }\n }, [doc, currentLayerId]);\n const viewport = useViewportStore(s => ({\n centerX: s.centerX, centerY: s.centerY, zoomLevel: s.zoomLevel,\n canvasWidth: s.canvasWidth, canvasHeight: s.canvasHeight,\n }));\n const setCenter = useViewportStore(s => s.setCenter);\n const setZoom = useViewportStore(s => s.setZoom);\n\n const nodes = useNodeStore(s => s.nodes);\n const setNodes = useNodeStore(s => s.setNodes);\n const updateNodePosition = useNodeStore(s => s.updateNodePosition);\n\n const clearSel = useSelectionStore(s => s.clear);\n const select = useSelectionStore(s => s.select);\n\n // Sync nodes → store\n useEffect(() => {\n const map = new Map(flatNodes.map(n => [n.id, n]));\n setNodes(map);\n clearSel();\n }, [flatNodes, setNodes, clearSel]);\n\n // ── Canvas refs ───────────────────────────────────────────────────────────\n const containerRef = useRef<HTMLDivElement | null>(null);\n const stageRef = useRef<Konva.Stage | null>(null);\n const canvasWrapperRef = useRef<HTMLDivElement>(null);\n\n // ── GPU CSS-transform transition refs (matches visualli.ai) ───────────────\n // During animations we express viewport deltas as CSS transforms on Konva's\n // container div — zero canvas redraws, handled entirely by the GPU compositor.\n const baselineTransformRef = useRef<{ x: number; y: number; scaleX: number; scaleY: number } | null>(null);\n const konvaContentDivRef = useRef<HTMLDivElement | null>(null);\n const lastAnimViewportRef = useRef<{ centerX: number; centerY: number; zoomLevel: number } | null>(null);\n const zoomOutTargetRef = useRef<{ centerX: number; centerY: number; zoomLevel: number } | null>(null);\n // canvasSizeRef is kept in sync with the measured container size (not window).\n // Initialise to 0 — it will be updated synchronously before the first frame.\n const canvasSizeRef = useRef({ width: 0, height: 0 });\n\n // ── Node drag refs (RAF-throttled, matches visualli.ai) ───────────────────\n const dragMoveRafRef = useRef<number | null>(null);\n const dragMoveLatestRef = useRef<{ nodeId: string; x: number; y: number } | null>(null);\n const dragStartPosRef = useRef<Map<string, { x: number; y: number }>>(new Map());\n\n // ── Background color (with chromatic immersion support) ──────────────────\n const baseBgColor = isDark ? '#141412' : '#F0EDE6';\n \n // For chromatic immersion: get the parent node color for child layers\n const chromaticBgColor = useMemo(() => {\n if (!chromaticImmersion || !doc || !currentLayerId) return baseBgColor;\n \n const currentLayer = doc.layers.get(currentLayerId);\n if (!currentLayer) return baseBgColor;\n \n // Root layer always uses base background\n if (currentLayer.level === 0 || !currentLayer.parentNodeId) return baseBgColor;\n \n // For child layers, find the parent node's color\n const parentLayer = currentLayer.parentLayerId ? doc.layers.get(currentLayer.parentLayerId) : null;\n if (parentLayer) {\n const parentNode = parentLayer.nodes.find(n => n.id === currentLayer.parentNodeId);\n if (parentNode) {\n const nodeColor = parentNode.data.color || baseBgColor;\n // Add transparency to the parent node color for subtle effect\n return hexToRgba(nodeColor, 0.15);\n }\n }\n \n return baseBgColor;\n }, [chromaticImmersion, doc, currentLayerId, baseBgColor]);\n \n const bgColor = chromaticImmersion ? chromaticBgColor : baseBgColor;\n\n // ── Spatial index (for stage-level hit detection) ─────────────────────────\n const spatialIndexRef = useRef<RBushSpatialIndex | null>(null);\n useEffect(() => {\n if (flatNodes.length === 0) { spatialIndexRef.current?.clear(); return; }\n const idx = new RBushSpatialIndex();\n idx.bulkLoad(flatNodes.map(n => {\n const blobHalfH = Math.max((NODE_HEIGHT * 1.6) / 2, (n.width / 2) * 0.74);\n return {\n nodeId: n.id,\n bounds: {\n minX: n.x - n.width / 2, minY: n.y - blobHalfH,\n maxX: n.x + n.width / 2, maxY: n.y + blobHalfH,\n },\n };\n }));\n spatialIndexRef.current = idx;\n return () => { spatialIndexRef.current?.clear(); };\n }, [flatNodes]);\n\n // ── Konva renderer (resize + FPS) ─────────────────────────────────────────\n const {\n handleWheel: rendererHandleWheel,\n handleMouseDown: rendererHandleMouseDown,\n handleMouseMove: rendererHandleMouseMove,\n handleMouseUp: rendererHandleMouseUp,\n canvasWidth,\n canvasHeight,\n } = useKonvaRenderer({ containerRef, stageRef });\n\n // Keep canvasSizeRef in sync with the measured container size.\n // The fallback to containerRef.getBoundingClientRect covers the period before\n // the first ResizeObserver callback fires.\n const _cw = canvasWidth || containerRef.current?.getBoundingClientRect().width || 800;\n const _ch = canvasHeight || containerRef.current?.getBoundingClientRect().height || 600;\n canvasSizeRef.current = { width: _cw, height: _ch };\n\n // ── Individual node drag (RAF-throttled, matches visualli.ai) ────────────\n const handleDragStart = useCallback((nodeId: string) => {\n isDraggingRef.current = true;\n setIsDraggingState(true);\n setHoveredNode(null);\n const node = nodes.get(nodeId);\n if (node) dragStartPosRef.current.set(nodeId, { x: node.x, y: node.y });\n }, [nodes]);\n\n const handleDragMove = useCallback((nodeId: string, x: number, y: number) => {\n dragMoveLatestRef.current = { nodeId, x, y };\n if (dragMoveRafRef.current !== null) return;\n dragMoveRafRef.current = requestAnimationFrame(() => {\n dragMoveRafRef.current = null;\n const latest = dragMoveLatestRef.current;\n if (latest) { dragMoveLatestRef.current = null; updateNodePosition(latest.nodeId, latest.x, latest.y); }\n });\n }, [updateNodePosition]);\n\n const handleDragEnd = useCallback((nodeId: string, x: number, y: number) => {\n if (dragMoveRafRef.current !== null) { cancelAnimationFrame(dragMoveRafRef.current); dragMoveRafRef.current = null; }\n dragMoveLatestRef.current = null;\n isDraggingRef.current = false;\n setIsDraggingState(false);\n updateNodePosition(nodeId, x, y);\n // Update spatial index entry\n if (spatialIndexRef.current) {\n const node = nodes.get(nodeId);\n if (node) {\n const oldPos = dragStartPosRef.current.get(nodeId);\n if (oldPos) {\n const oldHalfH = Math.max((NODE_HEIGHT * 1.6) / 2, (node.width / 2) * 0.74);\n spatialIndexRef.current.remove(nodeId, {\n minX: oldPos.x - node.width / 2, minY: oldPos.y - oldHalfH,\n maxX: oldPos.x + node.width / 2, maxY: oldPos.y + oldHalfH,\n });\n }\n const newHalfH = Math.max((NODE_HEIGHT * 1.6) / 2, (node.width / 2) * 0.74);\n spatialIndexRef.current.insert(nodeId, {\n minX: x - node.width / 2, minY: y - newHalfH,\n maxX: x + node.width / 2, maxY: y + newHalfH,\n });\n }\n }\n dragStartPosRef.current.delete(nodeId);\n }, [updateNodePosition, nodes]);\n // Keep a ref to the latest fitToScreen so async callbacks (onComplete) always\n // call the most current version without re-creating the animation pipeline.\n const fitToScreenRef = useRef<() => void>(() => {});\n\n const fitToScreen = useCallback(() => {\n if (flatNodes.length === 0) return;\n if (isTransitioningRef.current) return; // animation is controlling viewport\n // Use the container's measured size (not window) so the fit is always\n // relative to the renderer's actual bounding box.\n const cw = canvasSizeRef.current.width || containerRef.current?.getBoundingClientRect().width || 800;\n const ch = canvasSizeRef.current.height || containerRef.current?.getBoundingClientRect().height || 600;\n const { centerX, centerY } = calculateFitView(flatNodes, cw, ch);\n // Root layer: always use 1.0 zoom to match visualli.ai reference behaviour.\n // calculateFitZoom for a single node or dense layout on a 1920-default canvas\n // produces zoom > 2 which triggers the auto-zoom-in threshold immediately.\n const isRootLayer = navStack.length <= 1;\n // Root layer: use 1.0 zoom to match visualli.ai reference behaviour.\n // Child layers use the bounding-box fit zoom (already clamped to [0.4, 5]).\n const zoomLevel = isRootLayer ? 1.0 : calculateFitView(flatNodes, cw, ch).zoomLevel;\n setCenter(centerX, centerY);\n setZoom(zoomLevel);\n }, [flatNodes, navStack.length, setCenter, setZoom]);\n\n // Keep ref in sync after every render so async callbacks always use latest closure\n fitToScreenRef.current = fitToScreen;\n\n useEffect(() => { fitToScreen(); }, [currentLayerId]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Re-fit when the canvas is properly measured for the first time (the RAF in\n // useKonvaRenderer updates canvasWidth from 0 → container width asynchronously).\n const didFitAfterMeasureRef = useRef(false);\n useEffect(() => {\n if (!canvasWidth || didFitAfterMeasureRef.current) return;\n didFitAfterMeasureRef.current = true;\n fitToScreen();\n }, [canvasWidth, fitToScreen]);\n\n // ── Layer transitions ─────────────────────────────────────────────────────\n\n // Stores the target nav-back index so onSwapBack can read it\n const navBackTargetRef = useRef<number>(-1);\n\n const { zoomIntoLayer, zoomOutToParent, isTransitioning: isAnimating } = useKonvaLayerTransition({\n stageRef,\n canvasWrapperRef,\n onSwapLayer: (childLayerId) => {\n const childLayer = doc?.layers.get(childLayerId);\n if (!childLayer || !doc) return;\n setCurrentLayerId(childLayerId);\n setNavStack(prev => [...prev, { layerId: childLayerId, layer: childLayer, label: layerLabel(doc, childLayer, childLayerId) }]);\n onLayerChange?.(childLayerId, childLayer);\n },\n onSwapBack: () => {\n const targetIndex = navBackTargetRef.current;\n setNavStack(prev => {\n const newStack = prev.slice(0, targetIndex + 1);\n parentViewports.current = parentViewports.current.slice(0, targetIndex);\n const newLayerId = newStack[newStack.length - 1].layerId;\n setCurrentLayerId(newLayerId);\n onLayerChange?.(newLayerId, newStack[newStack.length - 1].layer);\n return newStack;\n });\n },\n onComplete: () => {\n setIsTransitioning(false);\n isTransitioningRef.current = false;\n // After every layer switch, snap to the fit view so zoom is always clean.\n // rAF ensures React has committed new node data before we compute the fit.\n requestAnimationFrame(() => { fitToScreenRef.current(); });\n },\n // GPU CSS-transform callbacks (matching visualli.ai exactly):\n onViewportFrame: (vp) => {\n lastAnimViewportRef.current = vp;\n const baseline = baselineTransformRef.current;\n const contentDiv = konvaContentDivRef.current;\n const { width, height } = canvasSizeRef.current;\n if (baseline && contentDiv) {\n const targetX = width / 2 - vp.centerX * vp.zoomLevel;\n const targetY = height / 2 - vp.centerY * vp.zoomLevel;\n const ratio = vp.zoomLevel / baseline.scaleX;\n const tx = targetX - baseline.x * ratio;\n const ty = targetY - baseline.y * ratio;\n contentDiv.style.transform = `translate(${tx}px, ${ty}px) scale(${ratio})`;\n } else {\n const stage = stageRef.current;\n if (stage) {\n stage.x(width / 2 - vp.centerX * vp.zoomLevel);\n stage.y(height / 2 - vp.centerY * vp.zoomLevel);\n stage.scaleX(vp.zoomLevel); stage.scaleY(vp.zoomLevel);\n stage.batchDraw();\n }\n }\n },\n onViewportFinal: (vp) => {\n if (konvaContentDivRef.current) konvaContentDivRef.current.style.transform = '';\n const stage = stageRef.current;\n if (stage) {\n const { width, height } = canvasSizeRef.current;\n stage.x(width / 2 - vp.centerX * vp.zoomLevel);\n stage.y(height / 2 - vp.centerY * vp.zoomLevel);\n stage.scaleX(vp.zoomLevel); stage.scaleY(vp.zoomLevel);\n stage.getLayers().forEach(l => l.drawScene());\n }\n setCenter(vp.centerX, vp.centerY);\n setZoom(vp.zoomLevel);\n },\n onPhaseChange: (phase) => {\n const stage = stageRef.current;\n const contentDiv = konvaContentDivRef.current;\n if (stage && contentDiv && (phase === 'swap' || phase === 'zoom-back')) {\n contentDiv.style.transform = '';\n const vp = phase === 'zoom-back' ? zoomOutTargetRef.current : lastAnimViewportRef.current;\n if (vp) {\n const { width, height } = canvasSizeRef.current;\n const nx = width / 2 - vp.centerX * vp.zoomLevel;\n const ny = height / 2 - vp.centerY * vp.zoomLevel;\n stage.x(nx); stage.y(ny);\n stage.scaleX(vp.zoomLevel); stage.scaleY(vp.zoomLevel);\n stage.getLayers().forEach(l => l.drawScene());\n baselineTransformRef.current = { x: nx, y: ny, scaleX: vp.zoomLevel, scaleY: vp.zoomLevel };\n }\n }\n },\n onTransitionLifecycle: (phase) => {\n const stage = stageRef.current;\n if (phase === 'start') {\n if (canvasWrapperRef.current) canvasWrapperRef.current.style.willChange = 'opacity, transform';\n if (stage) {\n baselineTransformRef.current = { x: stage.x(), y: stage.y(), scaleX: stage.scaleX(), scaleY: stage.scaleY() };\n const container = stage.container();\n const cd = container?.querySelector('.konvajs-content') as HTMLDivElement | null;\n if (cd) {\n konvaContentDivRef.current = cd;\n cd.style.transformOrigin = '0 0';\n cd.style.willChange = 'transform';\n }\n stage.getLayers().forEach(l => { l.listening(false); });\n }\n } else {\n if (canvasWrapperRef.current) canvasWrapperRef.current.style.willChange = 'auto';\n if (konvaContentDivRef.current) { konvaContentDivRef.current.style.willChange = 'auto'; konvaContentDivRef.current = null; }\n baselineTransformRef.current = null;\n zoomOutTargetRef.current = null;\n if (stage) {\n stage.getLayers().forEach(l => { l.listening(true); });\n stage.batchDraw();\n }\n }\n },\n });\n\n const handleNavigate = useCallback((nodeId: string) => {\n if (!doc || !currentLayerId) {\n return;\n }\n if (isTransitioningRef.current || isAnimating()) {\n return;\n }\n\n const childLayer = getChildLayerForNode(doc, nodeId, currentLayerId);\n if (!childLayer) {\n return;\n }\n const childLayerId = [...doc.layers.entries()].find(([, l]) => l === childLayer)?.[0];\n if (!childLayerId) {\n return;\n }\n const childNodes = (() => { try { return getNodesForLayer(doc, childLayerId); } catch { return []; } })();\n if (childNodes.length === 0) {\n return;\n }\n\n const node = nodes.get(nodeId);\n if (!node) return;\n\n // Save the FIT viewport for this layer (not the current scroll position).\n // This ensures navigating back always returns to a clean, properly-zoomed view\n // rather than the arbitrary zoom that happened to trigger the navigation.\n const cw = canvasSizeRef.current.width || 800;\n const ch = canvasSizeRef.current.height || 600;\n const fitVp = calculateFitView(flatNodes, cw, ch);\n const isRootNow = navStack.length <= 1;\n parentViewports.current.push({ centerX: fitVp.centerX, centerY: fitVp.centerY, zoomLevel: isRootNow ? 0.85 : fitVp.zoomLevel });\n\n setIsTransitioning(true);\n isTransitioningRef.current = true;\n\n zoomIntoLayer(\n doc, node, childLayerId, childNodes,\n node.color ?? getThemeBackground(isDark, 'secondary'),\n node.color ?? getThemeBackground(isDark, 'primary'),\n );\n }, [doc, currentLayerId, nodes, isDark, isAnimating, zoomIntoLayer]);\n\n const handleNavigateBack = useCallback((targetIndex: number) => {\n if (targetIndex >= navStack.length - 1) return;\n if (isTransitioningRef.current || isAnimating()) return;\n const savedVp = parentViewports.current[targetIndex];\n if (!savedVp) return;\n navBackTargetRef.current = targetIndex;\n setIsTransitioning(true);\n isTransitioningRef.current = true;\n zoomOutToParent(savedVp, getThemeBackground(isDark, 'primary'), getThemeBackground(isDark, 'secondary'));\n }, [navStack.length, isDark, isAnimating, zoomOutToParent]);\n\n // ── Auto-zoom navigation (Google Maps style) ──────────────────────────────\n const baseZoomRef = useRef(1.0);\n const lastZoomTransitionRef = useRef(0);\n const ZOOM_COOLDOWN = 1000;\n\n useEffect(() => { baseZoomRef.current = 1.0; }, [currentLayerId]);\n\n useEffect(() => {\n if (isTransitioningRef.current || isAnimating()) return;\n const now = Date.now();\n if (now - lastZoomTransitionRef.current < ZOOM_COOLDOWN) return;\n const relative = viewport.zoomLevel / baseZoomRef.current;\n\n if (relative >= ZOOM_NAV_IN_THRESHOLD) {\n // Zoom in threshold — drill into closest node\n let closest: FlatNode | null = null;\n let minDist = Infinity;\n for (const node of nodes.values()) {\n const dx = node.x - viewport.centerX;\n const dy = node.y - viewport.centerY;\n const d = dx * dx + dy * dy;\n if (d < minDist) { minDist = d; closest = node; }\n }\n if (closest) {\n const childLayer = doc ? getChildLayerForNode(doc, closest.id, currentLayerId ?? '') : null;\n if (childLayer) {\n lastZoomTransitionRef.current = now;\n handleNavigate(closest.id);\n baseZoomRef.current = 1.0;\n }\n }\n } else if (relative < ZOOM_NAV_OUT_THRESHOLD && navStack.length > 1) {\n // Zoom out threshold — go back to parent\n lastZoomTransitionRef.current = now;\n handleNavigateBack(navStack.length - 2);\n baseZoomRef.current = 1.0;\n }\n }, [viewport.zoomLevel, viewport.centerX, viewport.centerY, nodes, doc, currentLayerId, navStack, isAnimating, handleNavigate, handleNavigateBack]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // ── Stage-level hit detection ─────────────────────────────────────────────\n const toWorldCoords = useCallback((stage: Konva.Stage, pointer: { x: number; y: number }) => {\n const sp = stage.position();\n const sc = stage.scaleX();\n return { worldX: (pointer.x - sp.x) / sc, worldY: (pointer.y - sp.y) / sc };\n }, []);\n\n const hitTestNode = useCallback((worldX: number, worldY: number): string | null => {\n if (!spatialIndexRef.current) return null;\n const hits = spatialIndexRef.current.query({ minX: worldX, minY: worldY, maxX: worldX, maxY: worldY });\n if (!hits.length) return null;\n let targetId: string | null = null, minDist = Infinity;\n for (const nodeId of hits) {\n const node = nodes.get(nodeId);\n if (!node) continue;\n const d = (worldX - node.x) ** 2 + (worldY - node.y) ** 2;\n if (d < minDist) { minDist = d; targetId = nodeId; }\n }\n return targetId;\n }, [nodes]);\n\n // Stage pointer interaction state\n const stageActiveNodeIdRef = useRef<string | null>(null);\n const stageDragNodeOffsetRef = useRef({ x: 0, y: 0 });\n const stageMouseDownPosRef = useRef<{ x: number; y: number } | null>(null);\n const stageDragCommittedRef = useRef(false);\n const stageLastPointerCheckRef = useRef<number>(0);\n const pointerNodeIdRef = useRef<string | null>(null);\n const isCanvasPanningRef = useRef(false);\n const isDraggingRef = useRef(false);\n\n const [pointerNodeId, setPointerNodeId] = useState<string | null>(null);\n const [pressedNodeId, setPressedNodeId] = useState<string | null>(null);\n const [isDraggingState, setIsDraggingState] = useState(false);\n\n // ── Node hover tooltip ────────────────────────────────────────────────────\n const [hoveredNode, setHoveredNode] = useState<{\n nodeId: string; summary: string; screenX: number; screenY: number;\n } | null>(null);\n\n const tooltipHoverRef = useRef(false);\n const keepTooltipOpenRef = useRef(false); // External request to keep tooltip open (e.g., from extensions)\n const clearTooltipTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const hoveredNodePosition = useMemo(() => {\n if (!hoveredNode) return null;\n const node = nodes.get(hoveredNode.nodeId);\n if (!node) return null;\n const cw = viewport.canvasWidth || canvasSizeRef.current.width;\n const ch = viewport.canvasHeight || canvasSizeRef.current.height;\n return {\n screenX: (node.x - viewport.centerX) * viewport.zoomLevel + cw / 2,\n screenY: (node.y - viewport.centerY) * viewport.zoomLevel + ch / 2,\n zoom: viewport.zoomLevel,\n };\n }, [hoveredNode, nodes, viewport]);\n\n // ── Context menu ──────────────────────────────────────────────────────────\n const [canvasContextMenu, setCanvasContextMenu] = useState<{ x: number; y: number } | null>(null);\n\n useEffect(() => {\n if (!canvasContextMenu) return;\n const close = () => setCanvasContextMenu(null);\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') close(); };\n window.addEventListener('pointerdown', close);\n window.addEventListener('keydown', onKey);\n return () => { window.removeEventListener('pointerdown', close); window.removeEventListener('keydown', onKey); };\n }, [canvasContextMenu]);\n\n // ── Stage event handlers ──────────────────────────────────────────────────\n const handleStageMouseDown = useCallback((e: Konva.KonvaEventObject<MouseEvent>) => {\n if (e.evt.button !== 0) { rendererHandleMouseDown(e); return; }\n const stage = e.target.getStage();\n if (!stage) { rendererHandleMouseDown(e); return; }\n const pointer = stage.getPointerPosition();\n if (!pointer) { rendererHandleMouseDown(e); return; }\n const { worldX, worldY } = toWorldCoords(stage, pointer);\n const nodeId = hitTestNode(worldX, worldY);\n if (nodeId) {\n const node = nodes.get(nodeId);\n if (node) {\n select(nodeId);\n stageActiveNodeIdRef.current = nodeId;\n stageDragNodeOffsetRef.current = { x: worldX - node.x, y: worldY - node.y };\n stageMouseDownPosRef.current = { x: e.evt.clientX, y: e.evt.clientY };\n stageDragCommittedRef.current = false;\n setPressedNodeId(nodeId);\n setHoveredNode(null);\n return;\n }\n }\n setHoveredNode(null);\n isCanvasPanningRef.current = true;\n rendererHandleMouseDown(e);\n }, [hitTestNode, toWorldCoords, nodes, select, rendererHandleMouseDown]);\n\n const handleStageMouseMove = useCallback((e: Konva.KonvaEventObject<MouseEvent>) => {\n const stage = e.target.getStage();\n if (!stage) { rendererHandleMouseMove(e); return; }\n const pointer = stage.getPointerPosition();\n if (!pointer) { rendererHandleMouseMove(e); return; }\n const { worldX, worldY } = toWorldCoords(stage, pointer);\n\n if (stageActiveNodeIdRef.current && stageMouseDownPosRef.current) {\n const moved = Math.hypot(e.evt.clientX - stageMouseDownPosRef.current.x, e.evt.clientY - stageMouseDownPosRef.current.y);\n if (!stageDragCommittedRef.current && moved >= 5) {\n stageDragCommittedRef.current = true;\n isDraggingRef.current = true;\n setIsDraggingState(true);\n pointerNodeIdRef.current = null;\n setPointerNodeId(null);\n handleDragStart(stageActiveNodeIdRef.current);\n }\n if (stageDragCommittedRef.current) {\n const offset = stageDragNodeOffsetRef.current;\n handleDragMove(stageActiveNodeIdRef.current, worldX - offset.x, worldY - offset.y);\n stage.container().style.cursor = 'grabbing';\n return;\n }\n return;\n }\n\n // During canvas pan — just apply the pan, skip hover detection to avoid re-renders\n if (isCanvasPanningRef.current) {\n rendererHandleMouseMove(e);\n return;\n }\n\n // Throttled hover detection (only when not panning or dragging)\n const now = performance.now();\n if (now - stageLastPointerCheckRef.current >= 50) {\n stageLastPointerCheckRef.current = now;\n const hovered = hitTestNode(worldX, worldY);\n if (hovered !== pointerNodeIdRef.current) {\n pointerNodeIdRef.current = hovered;\n setPointerNodeId(hovered);\n onNodeHover?.(hovered);\n }\n if (hovered) {\n stage.container().style.cursor = 'pointer';\n } else {\n stage.container().style.cursor = 'grab';\n }\n }\n\n rendererHandleMouseMove(e);\n }, [toWorldCoords, hitTestNode, handleDragStart, handleDragMove, rendererHandleMouseMove]);\n\n const handleStageMouseUp = useCallback((e: Konva.KonvaEventObject<MouseEvent>) => {\n setPressedNodeId(null);\n if (stageActiveNodeIdRef.current) {\n const nodeId = stageActiveNodeIdRef.current;\n if (stageDragCommittedRef.current) {\n // End drag — flush final world position\n const stage = e.target.getStage();\n if (stage) {\n const pointer = stage.getPointerPosition();\n if (pointer) {\n const { worldX, worldY } = toWorldCoords(stage, pointer);\n const offset = stageDragNodeOffsetRef.current;\n handleDragEnd(nodeId, worldX - offset.x, worldY - offset.y);\n }\n }\n } else {\n // Click — check if node has child layer (regardless of branchCount)\n const node = nodes.get(nodeId);\n if (node) {\n const childLayer = doc ? getChildLayerForNode(doc, nodeId, currentLayerId ?? '') : null;\n if (childLayer) {\n handleNavigate(nodeId);\n }\n onNodeClick?.(node);\n }\n }\n isDraggingRef.current = false;\n setIsDraggingState(false);\n stageActiveNodeIdRef.current = null;\n stageMouseDownPosRef.current = null;\n stageDragCommittedRef.current = false;\n return;\n }\n isCanvasPanningRef.current = false;\n rendererHandleMouseUp(e);\n }, [toWorldCoords, handleDragEnd, nodes, handleNavigate, onNodeClick, rendererHandleMouseUp]);\n\n const handleStageContextMenu = useCallback((e: Konva.KonvaEventObject<MouseEvent>) => {\n e.evt.preventDefault();\n if (navStack.length <= 1) { setCanvasContextMenu(null); return; }\n const rect = containerRef.current?.getBoundingClientRect();\n const localX = rect ? e.evt.clientX - rect.left : e.evt.clientX;\n const localY = rect ? e.evt.clientY - rect.top : e.evt.clientY;\n setCanvasContextMenu({ x: localX, y: localY });\n }, [navStack.length]);\n\n // Touch passthrough\n const handleStageTouchStart = useCallback((e: Konva.KonvaEventObject<TouchEvent>) =>\n handleStageMouseDown(e as unknown as Konva.KonvaEventObject<MouseEvent>), [handleStageMouseDown]);\n const handleStageTouchMove = useCallback((e: Konva.KonvaEventObject<TouchEvent>) =>\n handleStageMouseMove(e as unknown as Konva.KonvaEventObject<MouseEvent>), [handleStageMouseMove]);\n const handleStageTouchEnd = useCallback((e: Konva.KonvaEventObject<TouchEvent>) =>\n handleStageMouseUp(e as unknown as Konva.KonvaEventObject<MouseEvent>), [handleStageMouseUp]);\n\n // Wheel with auto-nav guard on non-root layers\n const handleWheel = useCallback((e: Konva.KonvaEventObject<WheelEvent>) => {\n const isZoomOut = e.evt.deltaY > 0;\n if (!isZoomOut) { rendererHandleWheel(e); return; }\n\n const liveZoom = useViewportStore.getState().zoomLevel;\n const projected = Math.max(ZOOM_MIN, liveZoom * (1 - e.evt.deltaY / 1000));\n\n // Root layer: no parent to navigate to — let the user zoom freely down to ZOOM_MIN\n // (do NOT clamp at ZOOM_NAV_OUT_THRESHOLD; content may require lower zoom to fit)\n\n if (navStack.length > 1 && projected <= ZOOM_NAV_OUT_THRESHOLD && !isTransitioningRef.current && !isAnimating()) {\n e.evt.preventDefault();\n const now = Date.now();\n if (now - lastZoomTransitionRef.current >= ZOOM_COOLDOWN) {\n lastZoomTransitionRef.current = now;\n handleNavigateBack(navStack.length - 2);\n baseZoomRef.current = 1.0;\n }\n return;\n }\n rendererHandleWheel(e);\n }, [rendererHandleWheel, navStack, setZoom, isAnimating, handleNavigateBack]);\n\n // Canvas mouse move for description tooltip\n const lastHoverCheckRef = useRef(0);\n const handleCanvasMouseMove = useCallback((e: React.MouseEvent<HTMLDivElement>) => {\n if (!containerRef.current || isDraggingRef.current || isCanvasPanningRef.current) {\n setHoveredNode(null);\n return;\n }\n const now = Date.now();\n if (now - lastHoverCheckRef.current < 50) return;\n lastHoverCheckRef.current = now;\n\n // Check if mouse is over a tooltip - if so, don't change hovered node\n const target = e.target as HTMLElement;\n const isOverTooltip = target.closest('[data-node-tooltip=\"true\"]') || target.closest('[data-semantic-tooltip=\"true\"]');\n \n // If tooltip is open and we're hovering it or keeping it open, don't detect new nodes\n if (tooltipHoverRef.current || keepTooltipOpenRef.current || isOverTooltip) {\n return;\n }\n\n const cw = viewport.canvasWidth || canvasSizeRef.current.width;\n const ch = viewport.canvasHeight || canvasSizeRef.current.height;\n // e.clientX is viewport-relative; subtract the container's left/top offset\n // so world-coordinate conversion is correct when the renderer isn't full-screen.\n const rect = containerRef.current?.getBoundingClientRect();\n const localX = rect ? e.clientX - rect.left : e.clientX;\n const localY = rect ? e.clientY - rect.top : e.clientY;\n const worldX = (localX - cw / 2) / viewport.zoomLevel + viewport.centerX;\n const worldY = (localY - ch / 2) / viewport.zoomLevel + viewport.centerY;\n\n // Use RBush spatial index for O(log n) hit detection\n let found = false;\n if (spatialIndexRef.current) {\n const hits = spatialIndexRef.current.query({ minX: worldX, minY: worldY, maxX: worldX, maxY: worldY });\n for (const nodeId of hits) {\n const node = nodes.get(nodeId);\n if (node?.description) {\n setHoveredNode({ nodeId: node.id, summary: node.description, screenX: e.clientX, screenY: e.clientY });\n found = true;\n break;\n }\n }\n }\n if (!found) {\n if (clearTooltipTimerRef.current) clearTimeout(clearTooltipTimerRef.current);\n clearTooltipTimerRef.current = setTimeout(() => {\n if (!tooltipHoverRef.current && !keepTooltipOpenRef.current) setHoveredNode(null);\n }, 150);\n } else {\n if (clearTooltipTimerRef.current) { clearTimeout(clearTooltipTimerRef.current); clearTooltipTimerRef.current = null; }\n }\n }, [nodes, viewport, spatialIndexRef]);\n\n // Listen for external requests to keep tooltip open (e.g., from extensions)\n useEffect(() => {\n const handleKeepTooltipOpen = (event: CustomEvent) => {\n keepTooltipOpenRef.current = event.detail.keep;\n };\n \n // @ts-ignore - custom event\n window.addEventListener('keepNodeTooltipOpen', handleKeepTooltipOpen);\n \n return () => {\n // @ts-ignore - custom event\n window.removeEventListener('keepNodeTooltipOpen', handleKeepTooltipOpen);\n };\n }, []);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n if (clearTooltipTimerRef.current) clearTimeout(clearTooltipTimerRef.current);\n spatialIndexRef.current?.clear();\n if (dragMoveRafRef.current !== null) cancelAnimationFrame(dragMoveRafRef.current);\n };\n }, []);\n\n // ── Zoom controls ─────────────────────────────────────────────────────────\n const handleZoomIn = useCallback(() => setZoom(Math.min(viewport.zoomLevel * 1.2, 5)), [viewport.zoomLevel, setZoom]);\n const handleZoomOut = useCallback(() => {\n // Non-root: allow zoom to ZOOM_MIN so the wheel-driven ZOOM_NAV_OUT_THRESHOLD\n // transition can still trigger via scroll; button just navigates zoom value.\n // Root: also ZOOM_MIN (no parent layer to navigate to, allow full zoom-out).\n setZoom(Math.max(viewport.zoomLevel / 1.2, ZOOM_MIN));\n }, [viewport.zoomLevel, setZoom]);\n\n // Extension rendering removed - not part of open spec\n\n // ── Render ────────────────────────────────────────────────────────────────\n if (!doc) {\n return (\n <div className={className} style={{ position: 'relative', display: 'flex', alignItems: 'center', justifyContent: 'center', background: bgColor, ...style }}>\n <span style={{ color: isDark ? 'rgba(255,255,255,0.4)' : 'rgba(0,0,0,0.3)', fontSize: 14 }}>No document</span>\n </div>\n );\n }\n\n const hasBackOption = navStack.length > 1;\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={{ \n position: 'relative', \n overflow: 'hidden', \n userSelect: 'none', \n background: bgColor, \n width: '100%', \n height: '100%', \n ...style \n }}\n onMouseMove={handleCanvasMouseMove}\n onMouseLeave={() => {\n // Only close tooltip on mouse leave if not keeping it open\n if (!tooltipHoverRef.current && !keepTooltipOpenRef.current) {\n setHoveredNode(null);\n }\n }}\n >\n {/* Konva canvas — opacity driven imperatively during transitions */}\n <div ref={canvasWrapperRef} style={{ position: 'relative', zIndex: 1, pointerEvents: 'auto' }}>\n <KonvaStage\n ref={stageRef}\n onWheel={handleWheel}\n onMouseDown={handleStageMouseDown}\n onMouseMove={handleStageMouseMove}\n onMouseUp={handleStageMouseUp}\n onContextMenu={handleStageContextMenu}\n onTouchStart={handleStageTouchStart}\n onTouchMove={handleStageTouchMove}\n onTouchEnd={handleStageTouchEnd}\n >\n <KonvaContainerLayer nodes={flatNodes} containers={containers} isDark={isDark} />\n <KonvaEdgeLayer \n nodes={flatNodes} \n connections={connections} \n isDark={isDark} \n isDragging={isDraggingState} \n />\n <KonvaNodeLayer\n isTransitioning={isTransitioning}\n isDragging={isDraggingState}\n hoveredNodeId={pointerNodeId}\n pressedNodeId={pressedNodeId}\n />\n </KonvaStage>\n </div>\n\n {/* Context menu (right-click to go back) */}\n {canvasContextMenu && hasBackOption && (\n <div\n role=\"menu\"\n aria-label=\"Canvas options\"\n style={{\n position: 'absolute',\n zIndex: 60,\n pointerEvents: 'auto',\n left: `${Math.min(canvasContextMenu.x, Math.max(8, (canvasSizeRef.current.width || 800) - 152))}px`,\n top: `${Math.min(canvasContextMenu.y, Math.max(8, (canvasSizeRef.current.height || 600) - 72))}px`,\n }}\n onContextMenu={e => e.preventDefault()}\n onPointerDown={e => e.stopPropagation()}\n >\n <button\n type=\"button\"\n style={{\n padding: '6px 16px',\n borderRadius: '10px',\n border: `1px solid ${isDark ? '#333330' : '#DDD9D0'}`,\n background: isDark ? '#1C1C1A' : '#FAF8F4',\n color: isDark ? '#F0EDE6' : '#1A1A18',\n cursor: 'pointer',\n fontSize: 13,\n boxShadow: '0 4px 12px rgba(0,0,0,0.15)',\n }}\n onClick={() => { setCanvasContextMenu(null); handleNavigateBack(navStack.length - 2); }}\n >\n Back\n </button>\n </div>\n )}\n\n {/* Navigation stack (left, matches reference) */}\n <NavigationStack stack={navStack} onNavigateBack={handleNavigateBack} isDark={isDark} top={navigationStackTop} left={navigationStackLeft} />\n\n {/* Zoom controls (top-right) */}\n <div data-help=\"zoom-controls\" style={{ position: 'absolute', top: '24px', right: '16px', zIndex: 50, pointerEvents: 'auto' }}>\n <ZoomControls isDark={isDark} />\n </div>\n\n {/* Custom overlay from consuming app (for private features like help button, chromatic bg, etc.) */}\n {renderOverlay?.({ isDark, containerWidth: canvasSizeRef.current.width || 0, containerHeight: canvasSizeRef.current.height || 0 })}\n\n {/* Node description tooltip (sketchy-box, above node) - rendered before extensions so extensions appear on top */}\n {hoveredNode && hoveredNodePosition && viewport.zoomLevel < 3 && viewport.zoomLevel >= TEXT_LABEL_HIDE_BELOW_ZOOM && (() => {\n const nodeData = nodes.get(hoveredNode.nodeId);\n const borderColor = nodeData?.color ? darkenHexColor(nodeData.color, 0.13) : '#5BA8D4';\n const VP_PAD = 8;\n const HALF_W = 160;\n const APPROX_H = 90;\n const containerW = canvasSizeRef.current.width || 800;\n const safeLeft = Math.max(HALF_W + VP_PAD, Math.min(hoveredNodePosition.screenX, containerW - HALF_W - VP_PAD));\n const rawTop = hoveredNodePosition.screenY - 60 * hoveredNodePosition.zoom;\n const safeTop = Math.max(VP_PAD + APPROX_H, rawTop);\n return (\n <div\n data-node-tooltip=\"true\"\n style={{\n position: 'absolute',\n zIndex: 50,\n left: safeLeft,\n top: safeTop,\n transform: 'translate(-50%, -100%)',\n transformOrigin: 'bottom center',\n pointerEvents: 'auto',\n }}\n onMouseEnter={() => { tooltipHoverRef.current = true; if (clearTooltipTimerRef.current) { clearTimeout(clearTooltipTimerRef.current); clearTooltipTimerRef.current = null; } }}\n onMouseLeave={() => { \n tooltipHoverRef.current = false; \n // Delay clearing to allow external extensions to request keeping tooltip open\n if (clearTooltipTimerRef.current) clearTimeout(clearTooltipTimerRef.current);\n clearTooltipTimerRef.current = setTimeout(() => {\n if (!keepTooltipOpenRef.current) setHoveredNode(null);\n }, 100);\n }}\n >\n <div style={{ maxWidth: '20rem', minWidth: '12rem', maxHeight: '15rem', overflowY: 'auto' }}>\n <SketchyBoxKonva fill=\"#ffffff\" stroke={borderColor} backStroke={borderColor} padding=\"1rem 1.25rem\">\n <p style={{\n fontFamily: \"'Playpen Sans', cursive\",\n fontSize: `${DESCRIPTION_TEXT_BASE_FONT_PX}px`,\n fontWeight: 300,\n color: '#000000',\n textAlign: 'center',\n lineHeight: 1.6,\n margin: 0,\n }}>\n {renderNodeContent ? renderNodeContent({ \n summary: hoveredNode.summary, \n nodeId: hoveredNode.nodeId,\n nodeColor: nodeData?.color,\n zoom: viewport.zoomLevel,\n }) : hoveredNode.summary}\n </p>\n </SketchyBoxKonva>\n </div>\n </div>\n );\n })()}\n </div>\n );\n}\n","// ─── Node Store ───────────────────────────────────────────────────────────────\n\nimport { create } from 'zustand';\nimport type { FlatNode, NodeMap } from '@visualli/core';\n\nexport interface INodeStore {\n nodes: NodeMap;\n childrenIndex: Map<string | null, Set<string>>;\n\n setNodes: (nodes: NodeMap) => void;\n updateNode: (nodeId: string, updates: Partial<FlatNode>) => void;\n updateNodePosition: (nodeId: string, x: number, y: number) => void;\n addNode: (node: FlatNode) => void;\n removeNode: (nodeId: string) => void;\n setNodeExpanded: (nodeId: string, expanded: boolean) => void;\n\n getNode: (nodeId: string) => FlatNode | undefined;\n getChildren: (parentId: string | null) => FlatNode[];\n getChildrenIds: (parentId: string | null) => Set<string>;\n getAllNodes: () => FlatNode[];\n}\n\nfunction buildChildrenIndex(nodes: NodeMap): Map<string | null, Set<string>> {\n const index = new Map<string | null, Set<string>>();\n for (const node of nodes.values()) {\n const pid = node.parentId ?? null;\n if (!index.has(pid)) index.set(pid, new Set());\n index.get(pid)!.add(node.id);\n }\n return index;\n}\n\nexport const useNodeStore = create<INodeStore>((set, get) => ({\n nodes: new Map(),\n childrenIndex: new Map(),\n\n setNodes: (nodes) =>\n set({ nodes, childrenIndex: buildChildrenIndex(nodes) }),\n\n updateNode: (nodeId, updates) =>\n set((s) => {\n const node = s.nodes.get(nodeId);\n if (!node) return s;\n const next = new Map(s.nodes);\n next.set(nodeId, { ...node, ...updates, updatedAt: new Date() });\n return { nodes: next };\n }),\n\n updateNodePosition: (nodeId, x, y) =>\n set((s) => {\n const node = s.nodes.get(nodeId);\n if (!node || (node.x === x && node.y === y)) return s;\n const next = new Map(s.nodes);\n next.set(nodeId, { ...node, x, y });\n return { nodes: next };\n }),\n\n addNode: (node) =>\n set((s) => {\n const next = new Map(s.nodes);\n next.set(node.id, node);\n const idx = new Map(s.childrenIndex);\n const pid = node.parentId ?? null;\n if (!idx.has(pid)) idx.set(pid, new Set());\n idx.get(pid)!.add(node.id);\n return { nodes: next, childrenIndex: idx };\n }),\n\n removeNode: (nodeId) =>\n set((s) => {\n const node = s.nodes.get(nodeId);\n if (!node) return s;\n const next = new Map(s.nodes);\n next.delete(nodeId);\n const idx = new Map(s.childrenIndex);\n const pid = node.parentId ?? null;\n if (idx.has(pid)) {\n const set = new Set(idx.get(pid)!);\n set.delete(nodeId);\n if (set.size === 0) idx.delete(pid); else idx.set(pid, set);\n }\n return { nodes: next, childrenIndex: idx };\n }),\n\n setNodeExpanded: (nodeId, expanded) =>\n set((s) => {\n const node = s.nodes.get(nodeId);\n if (!node) return s;\n const next = new Map(s.nodes);\n next.set(nodeId, { ...node, isExpanded: expanded, updatedAt: new Date() });\n return { nodes: next };\n }),\n\n getNode: (nodeId) => get().nodes.get(nodeId),\n getChildren: (pid) => {\n const { nodes, childrenIndex } = get();\n return Array.from(childrenIndex.get(pid) ?? []).map(id => nodes.get(id)!).filter(Boolean);\n },\n getChildrenIds: (pid) => get().childrenIndex.get(pid) ?? new Set(),\n getAllNodes: () => Array.from(get().nodes.values()),\n}));\n","// ─── Viewport Store ───────────────────────────────────────────────────────────\n\nimport { create } from 'zustand';\nimport type { ViewportState } from '@visualli/core';\nimport {\n panViewport,\n zoomViewport,\n setViewportCenter,\n recalculateViewportBounds,\n clampZoom,\n DEFAULT_CANVAS_WIDTH,\n DEFAULT_CANVAS_HEIGHT,\n worldToScreen,\n screenToWorld,\n ZOOM_DEFAULT,\n} from '@visualli/core';\n\nexport interface IViewportStore extends ViewportState {\n canvasWidth: number;\n canvasHeight: number;\n\n pan: (deltaX: number, deltaY: number) => void;\n zoom: (delta: number, pivotX?: number, pivotY?: number) => void;\n setCenter: (x: number, y: number) => void;\n setZoom: (level: number) => void;\n updateCanvasSize: (width: number, height: number) => void;\n\n getVisibleBounds: () => ViewportState['visibleBounds'];\n worldToScreen: (x: number, y: number) => { x: number; y: number };\n screenToWorld: (x: number, y: number) => { x: number; y: number };\n}\n\nfunction makeInitial(w: number, h: number): ViewportState {\n const vp: ViewportState = {\n centerX: 0, centerY: 0,\n zoomLevel: ZOOM_DEFAULT,\n rotation: 0,\n visibleBounds: { minX: 0, minY: 0, maxX: 0, maxY: 0 },\n };\n return recalculateViewportBounds(vp, w, h);\n}\n\nconst getVP = (s: IViewportStore): ViewportState => ({\n centerX: s.centerX, centerY: s.centerY,\n zoomLevel: s.zoomLevel, rotation: s.rotation,\n visibleBounds: s.visibleBounds,\n});\n\nexport const useViewportStore = create<IViewportStore>((set, get) => {\n const init = makeInitial(DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT);\n return {\n ...init,\n canvasWidth: DEFAULT_CANVAS_WIDTH,\n canvasHeight: DEFAULT_CANVAS_HEIGHT,\n\n pan: (dx, dy) => set((s) => {\n const updated = recalculateViewportBounds(panViewport(dx, dy, getVP(s)), s.canvasWidth, s.canvasHeight);\n return { centerX: updated.centerX, centerY: updated.centerY, visibleBounds: updated.visibleBounds };\n }),\n\n zoom: (delta, pivotX, pivotY) => set((s) => {\n const updated = recalculateViewportBounds(\n zoomViewport(delta, getVP(s), pivotX, pivotY, s.canvasWidth, s.canvasHeight),\n s.canvasWidth, s.canvasHeight,\n );\n return { centerX: updated.centerX, centerY: updated.centerY, zoomLevel: updated.zoomLevel, visibleBounds: updated.visibleBounds };\n }),\n\n setCenter: (x, y) => set((s) => {\n const updated = recalculateViewportBounds(setViewportCenter(x, y, getVP(s)), s.canvasWidth, s.canvasHeight);\n return { centerX: updated.centerX, centerY: updated.centerY, visibleBounds: updated.visibleBounds };\n }),\n\n setZoom: (level) => set((s) => {\n const clamped = clampZoom(level);\n const updated = recalculateViewportBounds({ ...getVP(s), zoomLevel: clamped }, s.canvasWidth, s.canvasHeight);\n return { zoomLevel: updated.zoomLevel, visibleBounds: updated.visibleBounds };\n }),\n\n updateCanvasSize: (w, h) => set((s) => {\n const updated = recalculateViewportBounds(getVP(s), w, h);\n return { canvasWidth: w, canvasHeight: h, visibleBounds: updated.visibleBounds };\n }),\n\n getVisibleBounds: () => get().visibleBounds,\n worldToScreen: (x, y) => {\n const s = get();\n return worldToScreen(x, y, getVP(s), s.canvasWidth, s.canvasHeight);\n },\n screenToWorld: (x, y) => {\n const s = get();\n return screenToWorld(x, y, getVP(s), s.canvasWidth, s.canvasHeight);\n },\n };\n});\n","// ─── Selection Store ──────────────────────────────────────────────────────────\n\nimport { create } from 'zustand';\nimport { selectionStore, renderConfigStore } from '@visualli/core';\nimport type { ISelectionStore, IRenderConfigStore } from '@visualli/core';\n\nexport const useSelectionStore = create<ISelectionStore>((set, get, store) => {\n selectionStore.subscribe((state) => set(state));\n return selectionStore.getState();\n});\n\n// ─── Render Config Store ──────────────────────────────────────────────────────\n\nexport const useRenderConfigStore = create<IRenderConfigStore>((set, get, store) => {\n renderConfigStore.subscribe((state) => set(state));\n return renderConfigStore.getState();\n});\n","// ─── useKonvaRenderer ─────────────────────────────────────────────────────────\n//\n// Manages Konva rendering lifecycle: resize, pan, zoom, and FPS monitoring.\n// Returns Konva-level event handlers to be wired onto KonvaStage.\n//\n// Design matches visualli.ai's useKonvaRenderer:\n// - handleWheel / handleMouseDown / handleMouseMove / handleMouseUp are\n// Konva.KonvaEventObject handlers (not DOM-level)\n// - Pan is applied directly to the stage during drag for 60 fps, flushed to\n// Zustand store on mouseUp (no per-frame state updates)\n// - Zoom targets the cursor position (same math as visualli.ai)\n\nimport { useEffect, useCallback, useRef, useState } from 'react';\nimport type Konva from 'konva';\nimport { ZOOM_MIN, ZOOM_MAX } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\nimport { useRenderConfigStore } from '../stores/stores';\n\nexport interface UseKonvaRendererOptions {\n containerRef: React.RefObject<HTMLDivElement | null>;\n stageRef?: React.RefObject<Konva.Stage | null>;\n enabled?: boolean;\n}\n\nexport interface UseKonvaRendererReturn {\n handleWheel: (e: Konva.KonvaEventObject<WheelEvent>) => void;\n handleMouseDown:(e: Konva.KonvaEventObject<MouseEvent>) => void;\n handleMouseMove:(e: Konva.KonvaEventObject<MouseEvent>) => void;\n handleMouseUp: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n canvasWidth: number;\n canvasHeight: number;\n}\n\nexport function useKonvaRenderer({\n containerRef,\n stageRef,\n enabled = true,\n}: UseKonvaRendererOptions): UseKonvaRendererReturn {\n const pan = useViewportStore(s => s.pan);\n const zoom = useViewportStore(s => s.zoom);\n const setZoom = useViewportStore(s => s.setZoom);\n const setCenter = useViewportStore(s => s.setCenter);\n const updateCanvasSize = useViewportStore(s => s.updateCanvasSize);\n const autoAdjust = useRenderConfigStore(s => s.autoAdjustQuality);\n\n const [canvasWidth, setCanvasWidth] = useState(0);\n const [canvasHeight, setCanvasHeight] = useState(0);\n const cachedSizeRef = useRef({ width: 0, height: 0 });\n\n const isPanningRef = useRef(false);\n const lastPanPointRef = useRef({ x: 0, y: 0 });\n const panAccumRef = useRef({ x: 0, y: 0 });\n\n // ── FPS monitor ──────────────────────────────────────────────────────────────\n const fpsRef = useRef({ frames: 0, last: performance.now() });\n const fpsRafId = useRef<number | null>(null);\n\n useEffect(() => {\n if (!enabled) return;\n const tick = (now: number): void => {\n fpsRef.current.frames++;\n if (now - fpsRef.current.last >= 2000) {\n const fps = (fpsRef.current.frames / ((now - fpsRef.current.last) / 1000)) | 0;\n autoAdjust(fps);\n fpsRef.current = { frames: 0, last: now };\n }\n fpsRafId.current = requestAnimationFrame(tick);\n };\n fpsRafId.current = requestAnimationFrame(tick);\n return () => { if (fpsRafId.current !== null) cancelAnimationFrame(fpsRafId.current); };\n }, [enabled, autoAdjust]);\n\n // ── Resize ────────────────────────────────────────────────────────────────────\n // Observes the container element (not window) so the canvas always fills\n // its parent, regardless of how the renderer is sized by the consuming app.\n useEffect(() => {\n if (!enabled) return;\n\n let rafId: number | null = null;\n\n const measure = () => {\n const el = containerRef.current;\n const w = el ? Math.round(el.getBoundingClientRect().width) : 800;\n const h = el ? Math.round(el.getBoundingClientRect().height) : 600;\n return { w, h };\n };\n\n const updateSize = () => {\n if (rafId) cancelAnimationFrame(rafId);\n rafId = requestAnimationFrame(() => {\n rafId = null;\n const { w, h } = measure();\n if (w > 0 && h > 0 &&\n (cachedSizeRef.current.width !== w || cachedSizeRef.current.height !== h)) {\n cachedSizeRef.current = { width: w, height: h };\n setCanvasWidth(w);\n setCanvasHeight(h);\n updateCanvasSize(w, h);\n }\n });\n };\n\n // Initial measurement\n updateSize();\n\n // ResizeObserver tracks the container itself (handles % / flex / grid sizing)\n let ro: ResizeObserver | null = null;\n if (typeof ResizeObserver !== 'undefined' && containerRef.current) {\n ro = new ResizeObserver(updateSize);\n ro.observe(containerRef.current);\n } else {\n // Fallback: window resize only\n window.addEventListener('resize', updateSize);\n }\n\n return () => {\n ro ? ro.disconnect() : window.removeEventListener('resize', updateSize);\n if (rafId) cancelAnimationFrame(rafId);\n };\n }, [enabled, containerRef, updateCanvasSize]);\n\n // ── Wheel zoom ────────────────────────────────────────────────────────────────\n const handleWheel = useCallback((e: Konva.KonvaEventObject<WheelEvent>): void => {\n e.evt.preventDefault();\n const stage = e.target.getStage();\n if (!stage) return;\n const pointer = stage.getPointerPosition();\n if (!pointer) return;\n const delta = -e.evt.deltaY / 1000;\n zoom(delta, pointer.x, pointer.y);\n }, [zoom]);\n\n // ── Mouse pan ─────────────────────────────────────────────────────────────────\n const handleMouseDown = useCallback((e: Konva.KonvaEventObject<MouseEvent>): void => {\n const clickedOnEmpty = e.target === e.target.getStage();\n if (clickedOnEmpty && e.evt.button === 0) {\n e.evt.preventDefault();\n isPanningRef.current = true;\n lastPanPointRef.current = { x: e.evt.clientX, y: e.evt.clientY };\n panAccumRef.current = { x: 0, y: 0 };\n const stage = e.target.getStage();\n if (stage) stage.container().style.cursor = 'grabbing';\n }\n }, []);\n\n const handleMouseMove = useCallback((e: Konva.KonvaEventObject<MouseEvent>): void => {\n if (!isPanningRef.current) {\n // Update cursor on empty canvas\n const isOverEmpty = e.target === e.target.getStage();\n const stage = e.target.getStage();\n if (stage) stage.container().style.cursor = isOverEmpty ? 'grab' : 'default';\n return;\n }\n e.evt.preventDefault();\n const deltaX = e.evt.clientX - lastPanPointRef.current.x;\n const deltaY = e.evt.clientY - lastPanPointRef.current.y;\n\n // Apply pan directly to stage (no Zustand overhead per-frame)\n const stage = e.target.getStage();\n if (stage) {\n stage.x(stage.x() + deltaX);\n stage.y(stage.y() + deltaY);\n stage.batchDraw();\n }\n\n panAccumRef.current.x += deltaX;\n panAccumRef.current.y += deltaY;\n lastPanPointRef.current = { x: e.evt.clientX, y: e.evt.clientY };\n }, []); // No Zustand dep — pan flushed on mouseUp\n\n const handleMouseUp = useCallback((e: Konva.KonvaEventObject<MouseEvent>): void => {\n if (isPanningRef.current) {\n isPanningRef.current = false;\n const { x, y } = panAccumRef.current;\n if (x !== 0 || y !== 0) {\n pan(x, y);\n panAccumRef.current = { x: 0, y: 0 };\n }\n const stage = e.target.getStage();\n if (stage) stage.container().style.cursor = 'grab';\n }\n }, [pan]);\n\n return { handleWheel, handleMouseDown, handleMouseMove, handleMouseUp, canvasWidth, canvasHeight };\n}\n","// ─── useKonvaLayerTransition ──────────────────────────────────────────────────\n//\n// Manages layer navigation animations (zoom into child layer, zoom back to\n// parent). Uses the same callback-driven pattern as the visualli.ai reference:\n// - onViewportChange: imperatively updates the Konva stage each rAF frame\n// - onOpacityChange: writes directly to canvasWrapperRef DOM (no React state)\n// - onBackgroundColorChange: writes directly to bgRef DOM\n// - onPhaseChange('swap'|'zoom-back'): triggers React layer content swap\n// - onComplete: syncs final viewport to Zustand and ends transition\n\nimport { useCallback, useRef, useEffect } from 'react';\nimport type Konva from 'konva';\nimport type { VisualliDocument, FlatNode } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\nimport { konvaLayerTransitionAnimator } from '../animations/konvaLayerTransition';\nimport type { AnimatorViewport } from '../animations/konvaLayerTransition';\nimport { calculateFitView } from '../utils/layerNavigation';\n\nexport interface LayerTransitionOptions {\n /** Ref to the Konva Stage for imperative position/scale updates each frame. */\n stageRef: React.RefObject<Konva.Stage | null>;\n /** Ref to the wrapping div whose CSS `opacity` is driven during transitions. */\n canvasWrapperRef: React.RefObject<HTMLDivElement | null>;\n /** Ref to the background color div. */\n bgRef?: React.RefObject<HTMLDivElement | null>;\n /** Called at the content-swap point — use to switch the displayed layer. */\n onSwapLayer: (newLayerId: string) => void;\n /** Called when a zoom-out swap happens — use to update the nav stack. */\n onSwapBack: () => void;\n /** Called after the transition fully completes. */\n onComplete: () => void;\n /**\n * GPU CSS-transform mode: called each rAF frame instead of applyViewport.\n * When provided, the caller is responsible for moving the canvas content.\n */\n onViewportFrame?: (vp: AnimatorViewport) => void;\n /**\n * Called once when the animation reaches its final viewport.\n * When provided, replaces the default applyViewport call at completion.\n */\n onViewportFinal?: (vp: AnimatorViewport) => void;\n /**\n * Called at phase-change points ('swap', 'zoom-back') in addition to the\n * internal content-swap logic. Use to reset CSS transforms before Konva redraws.\n */\n onPhaseChange?: (phase: string) => void;\n /**\n * Called with 'start' before the animator fires its first frame and with\n * 'end' after onComplete. Use to set up / tear down GPU hints (willChange, etc.).\n */\n onTransitionLifecycle?: (phase: 'start' | 'end') => void;\n}\n\nexport interface LayerTransitionHandlers {\n zoomIntoLayer: (\n doc: VisualliDocument,\n targetNode: FlatNode,\n childLayerId: string,\n childNodes: FlatNode[],\n fromColor: string,\n toColor: string,\n ) => void;\n zoomOutToParent: (\n parentViewport: AnimatorViewport,\n fromColor: string,\n toColor: string,\n ) => void;\n isTransitioning: () => boolean;\n}\n\nexport function useKonvaLayerTransition(opts: LayerTransitionOptions): LayerTransitionHandlers {\n const {\n stageRef, canvasWrapperRef, bgRef,\n onSwapLayer, onSwapBack, onComplete,\n onViewportFrame, onViewportFinal, onPhaseChange: onPhaseChangeExt,\n onTransitionLifecycle,\n } = opts;\n const setZoom = useViewportStore(s => s.setZoom);\n const setCenter = useViewportStore(s => s.setCenter);\n const getState = useViewportStore.getState;\n\n const swappedRef = useRef(false);\n const canvasSizeRef = useRef({ width: 800, height: 600 });\n\n // Keep canvas size ref fresh from viewport store (updated by ResizeObserver in useKonvaRenderer)\n useEffect(() => {\n const update = () => {\n const vp = useViewportStore.getState();\n canvasSizeRef.current = { width: vp.canvasWidth || 800, height: vp.canvasHeight || 600 };\n };\n update();\n // Subscribe to viewport store changes instead of window resize\n const unsubscribe = useViewportStore.subscribe(update);\n return unsubscribe;\n }, []);\n\n // Apply viewport to Konva stage imperatively (no React re-render per frame)\n const applyViewport = useCallback((vp: AnimatorViewport) => {\n const stage = stageRef.current;\n if (!stage) return;\n const { width, height } = canvasSizeRef.current;\n stage.x(width / 2 - vp.centerX * vp.zoomLevel);\n stage.y(height / 2 - vp.centerY * vp.zoomLevel);\n stage.scaleX(vp.zoomLevel);\n stage.scaleY(vp.zoomLevel);\n stage.getLayers().forEach(l => l.drawScene());\n // Sync to Zustand so viewport store reflects reality\n setCenter(vp.centerX, vp.centerY);\n setZoom(vp.zoomLevel);\n }, [stageRef, setCenter, setZoom]);\n\n const applyOpacity = useCallback((opacity: number) => {\n if (canvasWrapperRef.current) {\n canvasWrapperRef.current.style.opacity = String(opacity);\n }\n }, [canvasWrapperRef]);\n\n const applyBgColor = useCallback((color: string) => {\n if (bgRef?.current) {\n bgRef.current.style.backgroundColor = color;\n }\n }, [bgRef]);\n\n const zoomIntoLayer = useCallback((\n _doc: VisualliDocument,\n targetNode: FlatNode,\n childLayerId: string,\n childNodes: FlatNode[],\n fromColor: string,\n toColor: string,\n ): void => {\n if (konvaLayerTransitionAnimator.active) return;\n\n const vp = getState();\n const stage = stageRef.current;\n const w = stage?.width() ?? 800;\n const h = stage?.height() ?? 600;\n const fit = calculateFitView(childNodes, w, h);\n\n swappedRef.current = false;\n\n onTransitionLifecycle?.('start');\n konvaLayerTransitionAnimator.animateZoomIntoLayer(\n { centerX: vp.centerX, centerY: vp.centerY, zoomLevel: vp.zoomLevel },\n { x: targetNode.x, y: targetNode.y, width: targetNode.width, height: targetNode.height },\n { x: fit.centerX, y: fit.centerY },\n fromColor,\n toColor,\n {\n onUpdate: ({ viewport, opacity, backgroundColor }) => {\n if (onViewportFrame) { onViewportFrame(viewport); } else { applyViewport(viewport); }\n applyOpacity(opacity);\n applyBgColor(backgroundColor);\n },\n onComplete: () => {\n const finalVp = { centerX: fit.centerX, centerY: fit.centerY, zoomLevel: fit.zoomLevel };\n if (onViewportFinal) { onViewportFinal(finalVp); } else { applyViewport(finalVp); }\n applyOpacity(1);\n onComplete();\n onTransitionLifecycle?.('end');\n },\n onPhaseChange: (phase) => {\n onPhaseChangeExt?.(phase);\n if (phase === 'swap' && !swappedRef.current) {\n swappedRef.current = true;\n onSwapLayer(childLayerId);\n }\n },\n },\n fit.zoomLevel,\n w,\n h,\n );\n }, [stageRef, getState, applyViewport, applyOpacity, applyBgColor, onSwapLayer, onComplete, onViewportFrame, onViewportFinal, onPhaseChangeExt, onTransitionLifecycle]);\n\n const zoomOutToParent = useCallback((\n parentViewport: AnimatorViewport,\n fromColor: string,\n toColor: string,\n ): void => {\n if (konvaLayerTransitionAnimator.active) return;\n\n const vp = getState();\n swappedRef.current = false;\n\n onTransitionLifecycle?.('start');\n konvaLayerTransitionAnimator.animateZoomOutToParent(\n { centerX: vp.centerX, centerY: vp.centerY, zoomLevel: vp.zoomLevel },\n parentViewport,\n fromColor,\n toColor,\n {\n onUpdate: ({ viewport, opacity, backgroundColor }) => {\n if (onViewportFrame) { onViewportFrame(viewport); } else { applyViewport(viewport); }\n applyOpacity(opacity);\n applyBgColor(backgroundColor);\n },\n onComplete: () => {\n if (onViewportFinal) { onViewportFinal(parentViewport); } else { applyViewport(parentViewport); }\n applyOpacity(1);\n onComplete();\n onTransitionLifecycle?.('end');\n },\n onPhaseChange: (phase) => {\n onPhaseChangeExt?.(phase);\n if (phase === 'zoom-back' && !swappedRef.current) {\n swappedRef.current = true;\n onSwapBack();\n }\n },\n },\n );\n }, [getState, applyViewport, applyOpacity, applyBgColor, onSwapBack, onComplete, onViewportFrame, onViewportFinal, onPhaseChangeExt, onTransitionLifecycle]);\n\n const isTransitioning = useCallback(() => konvaLayerTransitionAnimator.active, []);\n\n // Cancel on unmount\n useEffect(() => () => { konvaLayerTransitionAnimator.cancel(); }, []);\n\n return { zoomIntoLayer, zoomOutToParent, isTransitioning };\n}\n","// ─── Konva Layer Transition Animator ─────────────────────────────────────────\n//\n// rAF-driven animation engine for layer navigation:\n// animateZoomIntoLayer — camera-dive into child layer\n// animateZoomOutToParent — pull back to parent layer\n// animateCrossFade — simple cross-fade between two viewports\n//\n// No React dependencies — can be instantiated once and reused.\n\nimport { easeInOutSine, easeOutCubic, easeZoomTransition } from '@visualli/core';\nimport { ANIMATION_PHASES } from '@visualli/core';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport interface AnimatorViewport {\n centerX: number;\n centerY: number;\n zoomLevel: number;\n}\n\nexport interface NodeBounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface TransitionCallbacks {\n onUpdate: (state: { viewport: AnimatorViewport; opacity: number; backgroundColor: string }) => void;\n onComplete: () => void;\n onPhaseChange?: (phase: string) => void;\n}\n\n// ── Color helpers ─────────────────────────────────────────────────────────────\n\ninterface RGB { r: number; g: number; b: number }\n\nfunction parseColor(color: string): RGB {\n if (color.startsWith('#')) {\n const h = color.slice(1);\n return { r: parseInt(h.slice(0, 2), 16), g: parseInt(h.slice(2, 4), 16), b: parseInt(h.slice(4, 6), 16) };\n }\n const m = color.match(/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/);\n return m ? { r: +m[1], g: +m[2], b: +m[3] } : { r: 255, g: 255, b: 255 };\n}\n\nfunction interpolateRgb(a: RGB, b: RGB, t: number): string {\n const e = easeInOutSine(t);\n return `rgb(${(a.r + (b.r - a.r) * e + 0.5) | 0},${(a.g + (b.g - a.g) * e + 0.5) | 0},${(a.b + (b.b - a.b) * e + 0.5) | 0})`;\n}\n\n// (easeZoomTransition is imported from @visualli/core — createCubicBezier(0.2, 0.8, 0.2, 1))\n\nfunction lerp(a: number, b: number, t: number): number { return a + (b - a) * t; }\n\n// ── Animator class ────────────────────────────────────────────────────────────\n\nexport class KonvaLayerTransitionAnimator {\n private rafId: number | null = null;\n private timers: ReturnType<typeof setTimeout>[] = [];\n private _active = false;\n\n get active(): boolean { return this._active; }\n\n cancel(): void {\n if (this.rafId !== null) { cancelAnimationFrame(this.rafId); this.rafId = null; }\n this.timers.forEach(clearTimeout);\n this.timers = [];\n this._active = false;\n }\n\n // ── Zoom into child layer ──────────────────────────────────────────────────\n\n animateZoomIntoLayer(\n current: AnimatorViewport,\n targetNode: NodeBounds,\n childCenter: { x: number; y: number },\n fromColor: string,\n toColor: string,\n cb: TransitionCallbacks,\n targetZoom = 1.0,\n canvasWidth = 800,\n canvasHeight = 600,\n ): void {\n if (this._active) return;\n this._active = true;\n\n // Timing constants pulled from ANIMATION_PHASES (single source of truth)\n const ZOOM_DURATION = ANIMATION_PHASES.ZOOM_IN.ZOOM_TO_TARGET; // 500 ms\n const FADE_OUT_DELAY = ANIMATION_PHASES.ZOOM_IN.FADE_OUT_START; // 120 ms\n const FADE_OUT_DURATION = ANIMATION_PHASES.ZOOM_IN.FADE_OUT; // 280 ms — completes at 400 ms\n const SWAP_AT_MS = ANIMATION_PHASES.ZOOM_IN.CONTENT_SWAP; // 310 ms\n const FADE_IN_DURATION = ANIMATION_PHASES.ZOOM_IN.FADE_IN; // 200 ms\n const SETTLE_FACTOR = 0.94;\n\n const z0 = current.zoomLevel;\n const dx = targetNode.x - current.centerX;\n const dy = targetNode.y - current.centerY;\n const vmin = Math.min(canvasWidth, canvasHeight);\n const fillZoom = Math.max(4.0, (vmin * 1.5) / Math.max(targetNode.width, 100));\n\n const fromRgb = parseColor(fromColor);\n const toRgb = parseColor(toColor);\n const state = { viewport: { centerX: 0, centerY: 0, zoomLevel: 0 }, opacity: 1, backgroundColor: fromColor };\n\n const start = performance.now();\n let swapped = false;\n let fadeInStart = 0;\n\n cb.onPhaseChange?.('zoom');\n\n const tick = (now: number): void => {\n if (!this._active) return;\n const elapsed = now - start;\n\n if (!swapped) {\n if (elapsed >= SWAP_AT_MS) {\n swapped = true;\n fadeInStart = now;\n state.viewport = { centerX: childCenter.x, centerY: childCenter.y, zoomLevel: targetZoom * SETTLE_FACTOR };\n state.opacity = 0;\n state.backgroundColor = toColor;\n cb.onUpdate(state);\n cb.onPhaseChange?.('swap');\n this.rafId = requestAnimationFrame(tick);\n return;\n }\n const rawT = Math.min(elapsed / ZOOM_DURATION, 1);\n const zoomT = easeZoomTransition(rawT);\n const zl = lerp(z0, fillZoom, zoomT);\n state.viewport = {\n centerX: targetNode.x - dx * z0 * (1 - zoomT) / zl,\n centerY: targetNode.y - dy * z0 * (1 - zoomT) / zl,\n zoomLevel: zl,\n };\n state.opacity = elapsed > FADE_OUT_DELAY\n ? Math.max(0, 1 - easeOutCubic(Math.min((elapsed - FADE_OUT_DELAY) / FADE_OUT_DURATION, 1)))\n : 1;\n state.backgroundColor = interpolateRgb(fromRgb, toRgb, rawT);\n cb.onUpdate(state);\n } else {\n const fi = now - fadeInStart;\n const ft = Math.min(fi / FADE_IN_DURATION, 1);\n const eased = easeOutCubic(ft);\n state.viewport = { centerX: childCenter.x, centerY: childCenter.y, zoomLevel: lerp(targetZoom * SETTLE_FACTOR, targetZoom, eased) };\n state.opacity = eased;\n state.backgroundColor = toColor;\n cb.onUpdate(state);\n if (ft >= 1) { cb.onPhaseChange?.('fade-in'); this.rafId = null; this._complete(cb.onComplete); return; }\n }\n this.rafId = requestAnimationFrame(tick);\n };\n this.rafId = requestAnimationFrame(tick);\n }\n\n // ── Zoom out to parent layer ───────────────────────────────────────────────\n\n animateZoomOutToParent(\n current: AnimatorViewport,\n parent: AnimatorViewport,\n fromColor: string,\n toColor: string,\n cb: TransitionCallbacks,\n ): void {\n if (this._active) return;\n this._active = true;\n\n const FADE_OUT = ANIMATION_PHASES.ZOOM_OUT.FADE_OUT;\n const FADE_IN = ANIMATION_PHASES.ZOOM_OUT.FADE_IN;\n const OPACITY_SETTLE = 66;\n\n const fromRgb = parseColor(fromColor);\n const toRgb = parseColor(toColor);\n const state = { viewport: { centerX: 0, centerY: 0, zoomLevel: 0 }, opacity: 1, backgroundColor: fromColor };\n\n const start = performance.now();\n let swapped = false;\n let fadeInStart = 0;\n\n cb.onPhaseChange?.('fade-out');\n\n const tick = (now: number): void => {\n if (!this._active) return;\n const elapsed = now - start;\n\n if (!swapped) {\n if (elapsed >= FADE_OUT) {\n swapped = true; fadeInStart = now;\n state.viewport = { centerX: parent.centerX, centerY: parent.centerY, zoomLevel: parent.zoomLevel * 5 };\n state.opacity = 0;\n state.backgroundColor = toColor;\n cb.onUpdate(state); cb.onPhaseChange?.('zoom-back');\n this.rafId = requestAnimationFrame(tick); return;\n }\n const rawT = Math.min(elapsed / FADE_OUT, 1);\n const t = easeOutCubic(rawT);\n state.viewport = { centerX: current.centerX, centerY: current.centerY, zoomLevel: lerp(current.zoomLevel, current.zoomLevel * 0.6, t) };\n state.opacity = 1 - t;\n state.backgroundColor = interpolateRgb(fromRgb, toRgb, rawT);\n cb.onUpdate(state);\n } else {\n const fi = now - fadeInStart;\n const rawT = Math.min(fi / FADE_IN, 1);\n const t = easeZoomTransition(rawT);\n state.viewport = { centerX: parent.centerX, centerY: parent.centerY, zoomLevel: lerp(parent.zoomLevel * 5, parent.zoomLevel, t) };\n state.opacity = fi < OPACITY_SETTLE ? 0 : easeZoomTransition(Math.min((fi - OPACITY_SETTLE) / (FADE_IN - OPACITY_SETTLE), 1));\n state.backgroundColor = toColor;\n cb.onUpdate(state);\n if (rawT >= 1) { cb.onPhaseChange?.('fade-in'); this.rafId = null; this._complete(cb.onComplete); return; }\n }\n this.rafId = requestAnimationFrame(tick);\n };\n this.rafId = requestAnimationFrame(tick);\n }\n\n private _complete(onComplete: () => void): void {\n this.timers.forEach(clearTimeout); this.timers = [];\n this._active = false;\n onComplete();\n }\n}\n\nexport const konvaLayerTransitionAnimator = new KonvaLayerTransitionAnimator();\n","// ─── Layer Navigation Utilities ──────────────────────────────────────────────\n//\n// React-specific re-exports or wrappers of core navigation logic.\n\nexport {\n getConnectionsForLayer,\n getChildLayerForNode,\n getLayerForNavigation,\n calculateFitZoom,\n calculateFitCenter,\n getContainersForLayer,\n calculateFitView,\n} from '@visualli/core';\n\nexport type { FitResult, ContainerGroupInfo } from '@visualli/core';\n","// ─── KonvaStage ───────────────────────────────────────────────────────────────\n//\n// Thin wrapper around react-konva <Stage> that:\n// • Binds canvas position/scale from the viewport store\n// • Accepts optional event handlers (wheel, mouse, touch, context-menu)\n// • Calls stage.destroy() on unmount (memory hygiene)\n\nimport React, { useRef, useEffect, forwardRef } from 'react';\nimport { KStage as Stage } from '../konvaCompat';\nimport type Konva from 'konva';\nimport { useViewportStore } from '../stores/useViewportStore';\n\nexport interface KonvaStageProps {\n children: React.ReactNode;\n onWheel?: (e: Konva.KonvaEventObject<WheelEvent>) => void;\n onMouseDown?: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n onMouseMove?: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n onMouseUp?: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n onContextMenu?: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n onTouchStart?: (e: Konva.KonvaEventObject<TouchEvent>) => void;\n onTouchMove?: (e: Konva.KonvaEventObject<TouchEvent>) => void;\n onTouchEnd?: (e: Konva.KonvaEventObject<TouchEvent>) => void;\n onStageReady?: (stage: Konva.Stage) => void;\n}\n\nconst KonvaStage = forwardRef<Konva.Stage, KonvaStageProps>(function KonvaStage(\n {\n children,\n onWheel, onMouseDown, onMouseMove, onMouseUp, onContextMenu,\n onTouchStart, onTouchMove, onTouchEnd,\n onStageReady,\n },\n ref,\n) {\n const internalRef = useRef<Konva.Stage | null>(null);\n const { centerX, centerY, zoomLevel, canvasWidth, canvasHeight } = useViewportStore();\n\n useEffect(() => {\n if (internalRef.current) {\n if (typeof ref === 'function') ref(internalRef.current);\n else if (ref) (ref as React.MutableRefObject<Konva.Stage | null>).current = internalRef.current;\n onStageReady?.(internalRef.current);\n }\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n return () => { internalRef.current?.destroy(); };\n }, []);\n\n const w = canvasWidth || 800;\n const h = canvasHeight || 600;\n const stageX = w / 2 - centerX * zoomLevel;\n const stageY = h / 2 - centerY * zoomLevel;\n\n return (\n <Stage\n ref={internalRef}\n width={w}\n height={h}\n x={stageX}\n y={stageY}\n scaleX={zoomLevel}\n scaleY={zoomLevel}\n onWheel={onWheel}\n onMouseDown={onMouseDown}\n onMouseMove={onMouseMove}\n onMouseUp={onMouseUp}\n onContextMenu={onContextMenu}\n onTouchStart={onTouchStart}\n onTouchMove={onTouchMove}\n onTouchEnd={onTouchEnd}\n draggable={false}\n pixelRatio={1}\n >\n {children}\n </Stage>\n );\n});\n\nexport default KonvaStage;\n","// ─── konvaCompat ──────────────────────────────────────────────────────────────\n//\n// react-konva@18.x defines KonvaNodeComponent with return type\n// `ReactNode | Promise<ReactNode>`. @types/react v19 tightened the JSX checker\n// so that signature no longer satisfies `(props: any) => ReactNode`, causing\n// TS2786 errors everywhere a Konva primitive is used as JSX.\n//\n// The fix: re-export every Konva primitive cast to React.ComponentType<any>.\n// This is purely a type-level shim — no runtime behaviour changes.\n\nimport {\n Stage, Layer, Group, Shape, Path, Rect, Text, Arrow, Line, Circle, TextPath,\n} from 'react-konva';\nimport type React from 'react';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype C = React.ComponentType<any>;\n\nexport const KStage = Stage as unknown as C;\nexport const KLayer = Layer as unknown as C;\nexport const KGroup = Group as unknown as C;\nexport const KShape = Shape as unknown as C;\nexport const KPath = Path as unknown as C;\nexport const KRect = Rect as unknown as C;\nexport const KText = Text as unknown as C;\nexport const KArrow = Arrow as unknown as C;\nexport const KLine = Line as unknown as C;\nexport const KCircle = Circle as unknown as C;\nexport const KTextPath = TextPath as unknown as C;\n","// ─── KonvaNodeLayer ───────────────────────────────────────────────────────────\n//\n// Konva <Layer> that renders all visible FlatNodes.\n// Uses viewport culling and passes external hover/pressed state to each node.\n\nimport React, { useRef, useLayoutEffect, useEffect, useMemo } from 'react';\nimport { KLayer as Layer } from '../konvaCompat';\nimport type Konva from 'konva';\nimport type { FlatNode } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\nimport { useNodeStore } from '../stores/useNodeStore';\nimport { useViewportNodes } from '../hooks/useViewportNodes';\nimport KonvaNode from './KonvaNode';\n\nexport interface KonvaNodeLayerProps {\n nodes?: FlatNode[];\n isTransitioning?: boolean;\n isDragging?: boolean;\n hoveredNodeId?: string | null;\n pressedNodeId?: string | null;\n}\n\nexport default function KonvaNodeLayer({\n nodes: propNodes,\n isTransitioning = false,\n isDragging = false,\n hoveredNodeId = null,\n pressedNodeId = null,\n}: KonvaNodeLayerProps) {\n const layerRef = useRef<Konva.Layer | null>(null);\n const zoomLevel = useViewportStore(s => s.zoomLevel);\n const storeNodes = useNodeStore(s => s.nodes);\n const allNodes: FlatNode[] = useMemo(\n () => propNodes ?? Array.from(storeNodes.values()),\n [propNodes, storeNodes],\n );\n const visibleNodes = useViewportNodes(allNodes, undefined, isTransitioning, isDragging);\n\n // Redraw synchronously before paint whenever visible content changes.\n // Tied to data deps so it does not fire on every parent re-render.\n useLayoutEffect(() => { layerRef.current?.batchDraw(); }, [visibleNodes, hoveredNodeId, pressedNodeId, isDragging, zoomLevel]);\n\n // Redraw when transition state toggles (opacity wrapper controls visibility,\n // but the canvas still needs to be current when it fades back in).\n useEffect(() => { layerRef.current?.batchDraw(); }, [isTransitioning]);\n\n return (\n <Layer ref={layerRef} name=\"nodes\">\n {visibleNodes.map(n => (\n <KonvaNode\n key={n.id}\n node={n}\n zoomLevel={zoomLevel}\n isExternallyHovered={hoveredNodeId === n.id}\n isExternallyPressed={pressedNodeId === n.id}\n isDragging={isDragging}\n />\n ))}\n </Layer>\n );\n}\n","// ─── useViewportNodes ─────────────────────────────────────────────────────────\n//\n// Returns the subset of nodes currently visible in the viewport.\n// Signature: useViewportNodes(nodes, levelFilter?, skipCulling?)\n//\n// When skipCulling=true (e.g. during layer transitions) all nodes are returned\n// so the full layer is rendered when opacity ramps in.\n\nimport { useMemo, useRef } from 'react';\nimport type { FlatNode } from '@visualli/core';\nimport { RBushSpatialIndex, getViewportVisibleNodes } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\n\nconst SPATIAL_INDEX_THRESHOLD = 200;\n\nexport function useViewportNodes(\n nodes: FlatNode[],\n levelFilter?: number,\n skipCulling = false,\n /** When true, skip culling so dragged nodes are always visible and the\n * spatial index (keyed on layout positions) is not consulted. */\n isDragging = false,\n): FlatNode[] {\n const { centerX, centerY, zoomLevel, canvasWidth, canvasHeight } = useViewportStore();\n\n const indexRef = useRef<RBushSpatialIndex | null>(null);\n const nodesHashRef = useRef<number>(0);\n const nodesHash = nodes.length;\n\n if (nodesHash !== nodesHashRef.current) {\n nodesHashRef.current = nodesHash;\n indexRef.current = null; // rebuild below\n }\n\n return useMemo(() => {\n if (nodes.length === 0) return [];\n\n if (!indexRef.current && nodes.length >= SPATIAL_INDEX_THRESHOLD && !skipCulling && !isDragging) {\n indexRef.current = new RBushSpatialIndex();\n indexRef.current.bulkLoad(nodes.map(n => ({\n nodeId: n.id,\n bounds: { minX: n.x, minY: n.y, maxX: n.x + n.width, maxY: n.y + n.height },\n })));\n }\n\n return getViewportVisibleNodes({\n nodes,\n viewport: { centerX, centerY, zoomLevel, rotation: 0, visibleBounds: { minX: 0, minY: 0, maxX: 0, maxY: 0 } },\n canvasWidth,\n canvasHeight,\n levelFilter,\n skipCulling,\n isDragging,\n spatialIndex: indexRef.current,\n spatialIndexThreshold: SPATIAL_INDEX_THRESHOLD,\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [nodes, levelFilter, skipCulling, isDragging, centerX, centerY, zoomLevel, canvasWidth, canvasHeight]);\n}\n","// ─── KonvaNode ────────────────────────────────────────────────────────────────\n//\n// Renders a single FlatNode as a single organic blob shape with Konva.\n// Matches the visualli.ai rendering:\n// - Centered blob at node (x, y) with radiusX / radiusY scaling\n// - Single blob shape (no background depth layers)\n// - HSL-based border darkening\n// - 'Story Script' cursive font, text clipped to blob silhouette\n// - External hover / pressed state (no Konva hit-canvas dependency)\n// - All shapes are listening=false; hit detection uses spatial index\n\nimport React, { useMemo } from 'react';\nimport { KGroup as Group, KShape as Shape, KText as Text } from '../konvaCompat';\nimport type { FlatNode } from '@visualli/core';\nimport { CANVAS_COLORS, NODE_HEIGHT, TEXT_LABEL_HIDE_BELOW_ZOOM, darkenHexColor } from '@visualli/core';\nimport { getBlobTypeForLayer, BLOB_TEXT_OFFSETS, BLOB_LAYER_CONFIG, NODE_LAYER_CONFIG, drawBlobPath, computeNodeTextWorldScale } from '../config';\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport interface KonvaNodeProps {\n node: FlatNode;\n zoomLevel: number;\n /** True when the pointer is currently over this node (stage-level hit test). */\n isExternallyHovered?: boolean;\n /** True while this node is being pressed/dragged. */\n isExternallyPressed?: boolean;\n /** True while any node is being dragged — disables expensive shadows. */\n isDragging?: boolean;\n}\n\nconst KonvaNode = React.memo(function KonvaNode({\n node,\n zoomLevel,\n isExternallyHovered = false,\n isExternallyPressed = false,\n isDragging = false,\n}: KonvaNodeProps) {\n // Border: monochromatic HSL-darkened version of the fill color\n const borderColor = useMemo(() => darkenHexColor(node.color, 0.13), [node.color]);\n\n // Number of background layers (capped at 3), driven by branchCount\n const layerCount = useMemo(() => {\n const count = node.branchCount ?? 0;\n return Math.min(count, 3);\n }, [node.branchCount]);\n\n // Base blob radii (same math as visualli.ai KonvaNode)\n const baseRadiusX = node.width / 2;\n const baseRadiusY = Math.max((NODE_HEIGHT * 1.6) / 2, baseRadiusX * 0.74);\n\n // Larger, consistent font size for better readability\n // Text will wrap to multiple lines if needed\n const calculateFontSize = useMemo(() => {\n // Use a larger base font size for better visibility\n return 30;\n }, [node.title]);\n\n // Text scale and layout\n const textNaturalWidth = node.width - 40;\n // Increase text height to allow 2-3 lines of wrapped text\n const textNaturalHeight = NODE_HEIGHT * 1.2;\n const maxScale = computeNodeTextWorldScale(node.width, zoomLevel);\n\n // Blob type and text offset\n const blobType = getBlobTypeForLayer(node.level);\n const textOffsetX = (BLOB_TEXT_OFFSETS[blobType] ?? 0) * baseRadiusX;\n\n // Interaction state (purely driven from stage-level delegation)\n const effectiveHover = isExternallyHovered;\n const isPressed = isExternallyPressed;\n\n // Blob fill/stroke:\n // default → fill=node.color, stroke=borderColor\n // hover → fill=borderColor, stroke=borderColor\n // pressed → fill=borderColor, stroke=node.color\n const topFill = effectiveHover || isPressed ? borderColor : node.color;\n const topStroke = isPressed ? node.color : borderColor;\n\n // Build the background layers config (outermost first for correct z-order)\n const backgroundLayers = useMemo(() => {\n if (layerCount === 0) return [];\n const startIdx = BLOB_LAYER_CONFIG.length - layerCount;\n const layers = [];\n for (let i = startIdx; i < BLOB_LAYER_CONFIG.length; i++) {\n const config = BLOB_LAYER_CONFIG[i];\n layers.push({\n ...config,\n radiusX: baseRadiusX * config.scaleUp,\n radiusY: baseRadiusY * config.scaleUp,\n });\n }\n return layers;\n }, [layerCount, baseRadiusX, baseRadiusY]);\n\n return (\n <Group x={node.x} y={node.y} listening={false}>\n {/* Background blob layers (outermost rendered first, behind the node) */}\n {backgroundLayers.map((layer, idx) => (\n <Shape\n key={`blob-layer-${idx}`}\n rotation={layer.rotation}\n opacity={layer.opacity}\n sceneFunc={(ctx: any, shape: any) => {\n drawBlobPath(ctx, layer.radiusX, layer.radiusY, blobType);\n ctx.fillStrokeShape(shape);\n }}\n fill={node.color}\n stroke={borderColor}\n strokeWidth={layer.strokeWidth}\n dash={layer.dash ? [...layer.dash] : undefined}\n listening={false}\n perfectDrawEnabled={false}\n />\n ))}\n\n {/* Node (top layer) - main interactive blob */}\n <Shape\n rotation={NODE_LAYER_CONFIG.rotation}\n opacity={NODE_LAYER_CONFIG.opacity}\n sceneFunc={(ctx: any, shape: any) => {\n drawBlobPath(ctx, baseRadiusX, baseRadiusY, blobType);\n ctx.fillStrokeShape(shape);\n }}\n hitFunc={(ctx: any, shape: any) => {\n drawBlobPath(ctx, baseRadiusX, baseRadiusY, blobType);\n ctx.fillStrokeShape(shape);\n }}\n fill={topFill}\n stroke={topStroke}\n strokeWidth={NODE_LAYER_CONFIG.strokeWidth}\n shadowEnabled={!isDragging}\n shadowColor=\"rgba(255,255,255,1)\"\n shadowBlur={effectiveHover || isPressed ? 40 : 15}\n shadowOpacity={effectiveHover || isPressed ? 0.4 : 0.15}\n shadowOffsetX={0}\n shadowOffsetY={0}\n perfectDrawEnabled={false}\n />\n\n {/* Node Title — inverse-scaled so it stays legible at a constant screen size.\n Clipped to the blob silhouette via clipFunc so the growing text never visually\n bleeds outside the first layer boundary at low zoom levels. */}\n <Group\n clipFunc={(ctx: any) => {\n drawBlobPath(ctx, baseRadiusX, baseRadiusY, blobType);\n }}\n visible={zoomLevel >= TEXT_LABEL_HIDE_BELOW_ZOOM}\n listening={false}\n >\n <Text\n x={textOffsetX}\n y={0}\n offsetX={textNaturalWidth / 2}\n offsetY={textNaturalHeight / 2}\n width={textNaturalWidth}\n height={textNaturalHeight}\n scaleX={maxScale}\n scaleY={maxScale}\n text={node.title}\n fontSize={calculateFontSize}\n fontFamily=\"'Story Script', cursive\"\n fontStyle=\"normal\"\n fill={CANVAS_COLORS.node.titleColor}\n align=\"center\"\n verticalAlign=\"middle\"\n wrap=\"word\"\n ellipsis={false}\n listening={false}\n perfectDrawEnabled={false}\n />\n </Group>\n </Group>\n );\n});\n\nexport default KonvaNode;\n\n","export {\n ALL_BLOB_SHAPES,\n ACTIVE_BLOB_TYPES,\n BLOB_LAYER_CONFIG,\n NODE_LAYER_CONFIG,\n getBlobTypeForLayer,\n BLOB_TEXT_OFFSETS,\n drawBlobPath,\n NODE_TEXT_BASE_FONT_PX,\n DESCRIPTION_TEXT_BASE_FONT_PX,\n CONTAINER_LABEL_BASE_FONT_PX,\n EDGE_LABEL_BASE_FONT_PX,\n OVERLAY_FONT_UPPER_BOOST_PX,\n computeNodeTextWorldScale,\n computeNodeTextScreenScale,\n computeOverlayScale,\n computeEdgeLabelScale,\n} from '@visualli/core';\n\nexport { buildBlobPathData } from './blobShapes';\nexport type { BlobPoint, BlobShape } from '@visualli/core';\n","// ─── Blob Shapes Configuration ───────────────────────────────────────────────\n//\n// Blob shapes are centered at (0, 0). Coordinates are relative — multiply by\n// (radiusX, radiusY) to get world coords. Drawing uses closed quadratic bezier\n// curves through midpoints of consecutive control points (same as visualli.ai).\n//\n// Shapes match the visualli.ai reference designs exactly.\n\nexport interface BlobPoint { x: number; y: number }\nexport type BlobShape = ReadonlyArray<BlobPoint>;\n\n// ── Blob background layer depth config ────────────────────────────────────────\n// Index 0 = outermost layer (rendered first, behind the top blob).\n\nexport const BLOB_LAYER_CONFIG = [\n { opacity: 0.3, rotation: -15, scaleUp: 1.30, strokeWidth: 3, dash: [6, 4] as [number, number] },\n { opacity: 0.4, rotation: -10, scaleUp: 1.20, strokeWidth: 1, dash: undefined },\n { opacity: 0.5, rotation: -5, scaleUp: 1.10, strokeWidth: 2, dash: undefined },\n] as const;\n\nexport const NODE_LAYER_CONFIG = { opacity: 1, rotation: 0, strokeWidth: 3 } as const;\n\n// ── Six organic blob variants ─────────────────────────────────────────────────\nexport const ALL_BLOB_SHAPES: ReadonlyArray<BlobShape> = [\n // Shape 0 · Blob 1 (root / L0)\n [\n { x: 1.12, y: 0.00 }, { x: 0.86, y: 0.56 }, { x: 0.46, y: 0.94 },\n { x: -0.08, y: 1.06 }, { x: -0.68, y: 0.82 }, { x: -0.96, y: 0.08 },\n { x: -0.55, y: -0.82 }, { x: 0.04, y: -1.02 }, { x: 0.72, y: -0.80 },\n { x: 1.08, y: -0.38 },\n ],\n // Shape 1 · Blob 2\n [\n { x: -0.489, y: -0.625 }, { x: -0.384, y: -0.716 }, { x: -0.285, y: -0.792 },\n { x: -0.189, y: -0.855 }, { x: -0.090, y: -0.903 }, { x: 0.014, y: -0.932 },\n { x: 0.129, y: -0.940 }, { x: 0.255, y: -0.924 }, { x: 0.412, y: -0.876 },\n { x: 0.516, y: -0.832 }, { x: 0.612, y: -0.780 }, { x: 0.695, y: -0.725 },\n { x: 0.767, y: -0.666 }, { x: 0.830, y: -0.606 }, { x: 0.885, y: -0.546 },\n { x: 0.933, y: -0.486 }, { x: 0.979, y: -0.425 }, { x: 1.006, y: -0.385 },\n { x: 1.034, y: -0.334 }, { x: 1.058, y: -0.276 }, { x: 1.078, y: -0.209 },\n { x: 1.092, y: -0.133 }, { x: 1.101, y: -0.046 }, { x: 1.102, y: 0.052 },\n { x: 1.094, y: 0.173 }, { x: 1.083, y: 0.244 }, { x: 1.063, y: 0.324 },\n { x: 1.034, y: 0.401 }, { x: 0.996, y: 0.477 }, { x: 0.948, y: 0.549 },\n { x: 0.889, y: 0.617 }, { x: 0.820, y: 0.681 }, { x: 0.735, y: 0.741 },\n { x: 0.658, y: 0.783 }, { x: 0.569, y: 0.822 }, { x: 0.474, y: 0.855 },\n { x: 0.372, y: 0.882 }, { x: 0.265, y: 0.904 }, { x: 0.156, y: 0.920 },\n { x: 0.046, y: 0.931 }, { x: -0.069, y: 0.938 }, { x: -0.155, y: 0.935 },\n { x: -0.250, y: 0.919 }, { x: -0.346, y: 0.890 }, { x: -0.443, y: 0.851 },\n { x: -0.539, y: 0.800 }, { x: -0.633, y: 0.738 }, { x: -0.723, y: 0.667 },\n { x: -0.808, y: 0.585 }, { x: -0.882, y: 0.501 }, { x: -0.944, y: 0.421 },\n { x: -0.994, y: 0.343 }, { x: -1.034, y: 0.267 }, { x: -1.064, y: 0.192 },\n { x: -1.085, y: 0.120 }, { x: -1.097, y: 0.042 }, { x: -1.102, y: 0.001 },\n { x: -1.090, y: -0.243 }, { x: -1.050, y: -0.365 }, { x: -0.990, y: -0.441 },\n { x: -0.911, y: -0.479 }, { x: -0.819, y: -0.499 }, { x: -0.715, y: -0.517 },\n { x: -0.605, y: -0.551 },\n ],\n // Shape 2 · Blob 3\n [\n { x: 0.003, y: -0.970 }, { x: 0.163, y: -0.984 }, { x: 0.286, y: -1.028 },\n { x: 0.389, y: -1.096 }, { x: 0.488, y: -1.174 }, { x: 0.597, y: -1.210 },\n { x: 0.728, y: -1.165 }, { x: 0.867, y: -1.036 }, { x: 0.996, y: -0.839 },\n { x: 1.098, y: -0.590 }, { x: 1.158, y: -0.304 }, { x: 1.153, y: 0.012 },\n { x: 1.080, y: 0.336 }, { x: 0.944, y: 0.639 }, { x: 0.756, y: 0.889 },\n { x: 0.484, y: 1.072 }, { x: 0.339, y: 1.079 }, { x: 0.219, y: 1.051 },\n { x: 0.131, y: 0.994 }, { x: 0.059, y: 0.939 }, { x: 0.008, y: 0.915 },\n { x: -0.105, y: 0.931 }, { x: -0.176, y: 0.965 }, { x: -0.249, y: 1.005 },\n { x: -0.345, y: 1.039 }, { x: -0.497, y: 1.055 }, { x: -0.672, y: 1.032 },\n { x: -0.817, y: 0.952 }, { x: -0.945, y: 0.810 }, { x: -1.054, y: 0.600 },\n { x: -1.160, y: 0.302 }, { x: -1.187, y: -0.011 }, { x: -1.165, y: -0.326 },\n { x: -1.097, y: -0.599 }, { x: -0.991, y: -0.838 }, { x: -0.852, y: -0.912 },\n { x: -0.695, y: -0.958 }, { x: -0.530, y: -0.988 }, { x: -0.357, y: -0.992 },\n { x: -0.180, y: -0.983 },\n ],\n // Shape 3 · Blob 4\n [\n { x: -0.734, y: -1.127 }, { x: -0.656, y: -1.146 }, { x: -0.567, y: -1.142 },\n { x: -0.468, y: -1.115 }, { x: -0.358, y: -1.079 }, { x: -0.238, y: -1.034 },\n { x: -0.107, y: -0.989 }, { x: 0.035, y: -0.953 }, { x: 0.188, y: -0.929 },\n { x: 0.325, y: -0.916 }, { x: 0.484, y: -0.896 }, { x: 0.650, y: -0.854 },\n { x: 0.811, y: -0.770 }, { x: 0.955, y: -0.631 }, { x: 1.068, y: -0.422 },\n { x: 1.138, y: -0.126 }, { x: 1.152, y: 0.272 }, { x: 1.121, y: 0.451 },\n { x: 1.046, y: 0.602 }, { x: 0.928, y: 0.727 }, { x: 0.767, y: 0.833 },\n { x: 0.565, y: 0.925 }, { x: 0.323, y: 1.001 }, { x: 0.042, y: 1.075 },\n { x: -0.277, y: 1.142 }, { x: -0.368, y: 1.147 }, { x: -0.475, y: 1.136 },\n { x: -0.589, y: 1.104 }, { x: -0.704, y: 1.050 }, { x: -0.815, y: 0.973 },\n { x: -0.913, y: 0.871 }, { x: -0.993, y: 0.746 }, { x: -1.048, y: 0.593 },\n { x: -1.109, y: 0.298 }, { x: -1.145, y: 0.018 }, { x: -1.154, y: -0.243 },\n { x: -1.135, y: -0.482 }, { x: -1.085, y: -0.695 }, { x: -1.003, y: -0.874 },\n { x: -0.886, y: -1.020 },\n ],\n // Shape 4 · Blob 5 (inverted Blob 4)\n [\n { x: -0.734, y: 1.127 }, { x: -0.656, y: 1.146 }, { x: -0.567, y: 1.142 },\n { x: -0.468, y: 1.115 }, { x: -0.358, y: 1.079 }, { x: -0.238, y: 1.034 },\n { x: -0.107, y: 0.989 }, { x: 0.035, y: 0.953 }, { x: 0.188, y: 0.929 },\n { x: 0.325, y: 0.916 }, { x: 0.484, y: 0.896 }, { x: 0.650, y: 0.854 },\n { x: 0.811, y: 0.770 }, { x: 0.955, y: 0.631 }, { x: 1.068, y: 0.422 },\n { x: 1.138, y: 0.126 }, { x: 1.152, y: -0.272 }, { x: 1.121, y: -0.451 },\n { x: 1.046, y: -0.602 }, { x: 0.928, y: -0.727 }, { x: 0.767, y: -0.833 },\n { x: 0.565, y: -0.925 }, { x: 0.323, y: -1.001 }, { x: 0.042, y: -1.075 },\n { x: -0.277, y: -1.142 }, { x: -0.368, y: -1.147 }, { x: -0.475, y: -1.136 },\n { x: -0.589, y: -1.104 }, { x: -0.704, y: -1.050 }, { x: -0.815, y: -0.973 },\n { x: -0.913, y: -0.871 }, { x: -0.993, y: -0.746 }, { x: -1.048, y: -0.593 },\n { x: -1.109, y: -0.298 }, { x: -1.145, y: -0.018 }, { x: -1.154, y: 0.243 },\n { x: -1.135, y: 0.482 }, { x: -1.085, y: 0.695 }, { x: -1.003, y: 0.874 },\n { x: -0.886, y: 1.020 },\n ],\n // Shape 5 · Blob 6\n [\n { x: 0.001, y: -1.006 }, { x: 0.134, y: -1.001 }, { x: 0.262, y: -1.024 },\n { x: 0.382, y: -1.073 }, { x: 0.498, y: -1.107 }, { x: 0.614, y: -1.105 },\n { x: 0.733, y: -1.049 }, { x: 0.850, y: -0.932 }, { x: 0.953, y: -0.755 },\n { x: 1.030, y: -0.529 }, { x: 1.067, y: -0.265 }, { x: 1.054, y: 0.018 },\n { x: 0.986, y: 0.300 }, { x: 0.868, y: 0.557 }, { x: 0.715, y: 0.766 },\n { x: 0.550, y: 0.909 }, { x: 0.396, y: 0.984 }, { x: 0.262, y: 1.005 },\n { x: 0.148, y: 1.003 }, { x: 0.037, y: 1.008 }, { x: -0.083, y: 1.040 },\n { x: -0.220, y: 1.118 }, { x: -0.360, y: 1.192 }, { x: -0.500, y: 1.234 },\n { x: -0.650, y: 1.175 }, { x: -0.810, y: 1.045 }, { x: -0.990, y: 0.855 },\n { x: -1.140, y: 0.610 }, { x: -1.240, y: 0.330 }, { x: -1.270, y: 0.040 },\n { x: -1.275, y: -0.250 }, { x: -1.225, y: -0.500 }, { x: -1.080, y: -0.720 },\n { x: -0.890, y: -0.920 }, { x: -0.734, y: -1.053 }, { x: -0.614, y: -1.112 },\n { x: -0.498, y: -1.127 }, { x: -0.381, y: -1.110 }, { x: -0.261, y: -1.095 },\n { x: -0.133, y: -1.058 }, { x: 0.001, y: -1.010 }, { x: 0.134, y: -1.001 },\n ],\n];\n\nexport const ACTIVE_BLOB_TYPES: ReadonlyArray<number> = [0, 1, 2, 3, 4, 5];\n\n/**\n * Per-shape text x-offset as a fraction of baseRadiusX.\n * Compensates for visually asymmetric blobs. Positive = right, negative = left.\n */\nexport const BLOB_TEXT_OFFSETS: ReadonlyArray<number> = [0, 0, 0, 0, 0, -0.10];\n\n/**\n * Deterministic pseudo-random blob-type selector per tree level.\n * Root level (0) always uses shape 0; consecutive levels use different shapes.\n */\nexport function getBlobTypeForLayer(level: number): number {\n const numTypes = ACTIVE_BLOB_TYPES.length;\n if (numTypes <= 1) return ACTIVE_BLOB_TYPES[0] ?? 0;\n let currentType = 0;\n for (let i = 1; i <= level; i++) {\n const pseudoRandom = Math.floor(Math.abs(Math.sin((i + 1) * 12.9898) * 43758.5453));\n const stepOffset = (pseudoRandom % (numTypes - 1)) + 1;\n currentType = (currentType + stepOffset) % numTypes;\n }\n return ACTIVE_BLOB_TYPES[currentType];\n}\n\n/**\n * Draw the blob path onto a Konva canvas context (centered at 0,0).\n * Uses closed quadratic bezier curves through midpoints of control points.\n * Call this inside a Konva Shape's sceneFunc / hitFunc.\n */\nexport function drawBlobPath(\n ctx: { beginPath(): void; moveTo(x: number, y: number): void; quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void; closePath(): void },\n radiusX: number,\n radiusY: number,\n blobType: number,\n): void {\n const srcPts = ALL_BLOB_SHAPES[blobType] ?? ALL_BLOB_SHAPES[0];\n const pts = srcPts.map(p => ({ x: p.x * radiusX, y: p.y * radiusY }));\n ctx.beginPath();\n const last = pts[pts.length - 1];\n const first = pts[0];\n ctx.moveTo((last.x + first.x) / 2, (last.y + first.y) / 2);\n for (let i = 0; i < pts.length; i++) {\n const curr = pts[i];\n const next = pts[(i + 1) % pts.length];\n ctx.quadraticCurveTo(curr.x, curr.y, (curr.x + next.x) / 2, (curr.y + next.y) / 2);\n }\n ctx.closePath();\n}\n\n// Legacy export kept for consumers that may import buildBlobPathData.\n// Generates an SVG path string (less accurate than the sceneFunc approach).\nexport function buildBlobPathData(\n _shape: BlobShape,\n cx: number,\n cy: number,\n width: number,\n height: number,\n): string {\n const rx = width / 2;\n const ry = height / 2;\n const blobType = 0;\n const srcPts = ALL_BLOB_SHAPES[blobType];\n const pts = srcPts.map(p => ({ x: cx + p.x * rx, y: cy + p.y * ry }));\n const mid = (a: { x: number; y: number }, b: { x: number; y: number }) =>\n ({ x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 });\n const last = pts[pts.length - 1];\n const first = pts[0];\n const s = mid(last, first);\n let d = `M ${s.x} ${s.y}`;\n for (let i = 0; i < pts.length; i++) {\n const curr = pts[i];\n const next = pts[(i + 1) % pts.length];\n const m = mid(curr, next);\n d += ` Q ${curr.x} ${curr.y} ${m.x} ${m.y}`;\n }\n d += ' Z';\n return d;\n}\n","// ─── KonvaEdgeLayer ───────────────────────────────────────────────────────────\n//\n// Renders all edges for visible nodes. An edge is only drawn when BOTH its\n// source and target node are currently in the visible set.\n//\n// NOTE: Node positions are read from useNodeStore (live) so edges always follow\n// dragged nodes. The `nodes` prop is used only for initial viewport culling.\n\nimport React, { useRef, useLayoutEffect, useMemo } from 'react';\nimport { KLayer as Layer } from '../konvaCompat';\nimport type Konva from 'konva';\nimport type { FlatNode, MindMapConnection } from '@visualli/core';\nimport { useNodeStore } from '../stores/useNodeStore';\nimport { useViewportStore } from '../stores/useViewportStore';\nimport { useViewportNodes } from '../hooks/useViewportNodes';\nimport KonvaEdge from './KonvaEdge';\n\nexport interface KonvaEdgeLayerProps {\n nodes: FlatNode[];\n connections: MindMapConnection[];\n currentLevel?: number;\n isDark?: boolean;\n /** Pass true while a node is being dragged to skip viewport culling. */\n isDragging?: boolean;\n}\n\nexport default function KonvaEdgeLayer({\n nodes,\n connections,\n currentLevel,\n isDark = false,\n isDragging = false,\n}: KonvaEdgeLayerProps) {\n const layerRef = useRef<Konva.Layer | null>(null);\n const zoomLevel = useViewportStore(s => s.zoomLevel);\n // Live node positions from the store — updated every RAF during drag\n const storeNodes = useNodeStore(s => s.nodes);\n // Viewport culling still uses the layout snapshot for performance;\n // during drag, culling is skipped so newly-moved nodes are always visible.\n const visibleNodes = useViewportNodes(nodes, currentLevel, false, isDragging);\n\n // Set of visible node IDs for O(1) culling\n const visibleSet = useMemo(() => new Set(visibleNodes.map(n => n.id)), [visibleNodes]);\n\n // Redraw before paint whenever visible edges change.\n // storeNodes must be included: edge endpoints read live positions from the store,\n // so when a node is dragged, the edge must redraw even though visibleSet is unchanged.\n useLayoutEffect(() => { layerRef.current?.batchDraw(); }, [connections, isDark, isDragging, visibleSet, storeNodes]);\n\n return (\n <Layer ref={layerRef} listening={false}>\n {connections.map((conn, idx) => {\n // Use live store positions so edges move with dragged nodes\n const src = storeNodes.get(conn.from);\n const tgt = storeNodes.get(conn.to);\n if (!src || !tgt) return null;\n if (!isDragging && !visibleSet.has(src.id) && !visibleSet.has(tgt.id)) return null;\n\n return (\n <KonvaEdge\n key={`${conn.from}-${conn.to}-${idx}`}\n sourceNode={src}\n targetNode={tgt}\n connection={conn}\n isDark={isDark}\n zoomLevel={zoomLevel}\n />\n );\n })}\n </Layer>\n );\n}\n","// ─── KonvaEdge ────────────────────────────────────────────────────────────────\n//\n// Renders a connection arrow between two FlatNodes.\n// Matches the visualli.ai KonvaEdge exactly:\n// - Cubic bezier multi-point polyline (20 segments) through ellipse boundaries\n// - Adaptive arc height (smaller for long connections)\n// - Open V arrowhead at target\n// - TextPath label following the curve (above the line)\n// - Always black stroke for maximum visibility\n\nimport React, { useMemo, memo } from 'react';\nimport { KGroup as Group, KLine as Line, KTextPath as TextPath } from '../konvaCompat';\nimport type { FlatNode, MindMapConnection } from '@visualli/core';\nimport { NODE_HEIGHT } from '@visualli/core';\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\n// Returns the outermost visible blob scale for a node.\n// Mirrors BLOB_LAYER_CONFIG in KonvaNode: scaleUps are [1.30, 1.20, 1.10] (outermost→inner).\nconst getOutermostScaleUp = (branchCount: number | undefined): number => {\n const layerCount = Math.min(branchCount ?? 0, 3);\n if (layerCount === 0) return 1.0;\n const scaleUps = [1.30, 1.20, 1.10] as const;\n return scaleUps[scaleUps.length - layerCount];\n};\n\nfunction getEllipseIntersection(\n cx: number, cy: number, rx: number, ry: number, angle: number,\n): { x: number; y: number } {\n return {\n x: cx + rx * Math.cos(angle),\n y: cy + ry * Math.sin(angle),\n };\n}\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport interface KonvaEdgeProps {\n sourceNode: FlatNode;\n targetNode: FlatNode;\n connection?: MindMapConnection;\n isDark?: boolean;\n colorOverride?: string;\n zoomLevel?: number;\n}\n\nconst EDGE_SPACING = 25; // Increased spacing to ensure arrow head stays out of organic shapes\nconst STROKE_COLOR = '#000000';\nconst STROKE_COLOR_DARK = '#ffffff';\nconst STROKE_WIDTH = 2.5;\n\nconst KonvaEdge = memo(function KonvaEdge({\n sourceNode: from,\n targetNode: to,\n connection,\n isDark = false,\n zoomLevel = 1.0,\n}: KonvaEdgeProps) {\n const label = (connection as { label?: string } | undefined)?.label;\n\n // ── Build multi-point bezier curve ─────────────────────────────────────────\n const points = useMemo(() => {\n const fromBaseX = from.width / 2;\n const fromBaseY = Math.max((NODE_HEIGHT * 1.6) / 2, fromBaseX * 0.74);\n const fromScale = getOutermostScaleUp(from.branchCount);\n const fromRadiusX = fromBaseX * fromScale;\n const fromRadiusY = fromBaseY * fromScale;\n\n const toBaseX = to.width / 2;\n const toBaseY = Math.max((NODE_HEIGHT * 1.6) / 2, toBaseX * 0.74);\n const toScale = getOutermostScaleUp(to.branchCount);\n const toRadiusX = toBaseX * toScale;\n const toRadiusY = toBaseY * toScale;\n\n const angle = Math.atan2(to.y - from.y, to.x - from.x);\n const fromEdge = getEllipseIntersection(from.x, from.y, fromRadiusX, fromRadiusY, angle);\n const toEdge = getEllipseIntersection(to.x, to.y, toRadiusX, toRadiusY, angle + Math.PI);\n\n // Apply spacing from edges (increased to 25 to avoid leaking into organic shapes)\n const fromX = fromEdge.x + EDGE_SPACING * Math.cos(angle);\n const fromY = fromEdge.y + EDGE_SPACING * Math.sin(angle);\n const toX = toEdge.x - EDGE_SPACING * Math.cos(angle);\n const toY = toEdge.y - EDGE_SPACING * Math.sin(angle);\n\n const midX = (fromX + toX) / 2;\n const midY = (fromY + toY) / 2;\n\n const distance = Math.sqrt((toX - fromX) ** 2 + (toY - fromY) ** 2);\n const arcHeight = Math.min(45, 45 / (1 + Math.max(0, (distance - 200) / 400)));\n\n const perpX = -(toY - fromY) / distance;\n const perpY = (toX - fromX) / distance;\n\n const offsetMidX = midX + perpX * arcHeight;\n const offsetMidY = midY + perpY * arcHeight;\n\n const ctrl1X = fromX + (offsetMidX - fromX) * 0.66;\n const ctrl1Y = fromY + (offsetMidY - fromY) * 0.66;\n const ctrl2X = toX + (offsetMidX - toX) * 0.66;\n const ctrl2Y = toY + (offsetMidY - toY) * 0.66;\n\n const NUM_SEGMENTS = 20;\n const pts: number[] = [];\n for (let i = 0; i <= NUM_SEGMENTS; i++) {\n const t = i / NUM_SEGMENTS;\n const mt = 1 - t;\n const mt2 = mt * mt; const mt3 = mt2 * mt;\n const t2 = t * t; const t3 = t2 * t;\n pts.push(\n mt3 * fromX + 3 * mt2 * t * ctrl1X + 3 * mt * t2 * ctrl2X + t3 * toX,\n mt3 * fromY + 3 * mt2 * t * ctrl1Y + 3 * mt * t2 * ctrl2Y + t3 * toY,\n );\n }\n return pts;\n }, [from.x, from.y, from.width, from.branchCount, to.x, to.y, to.width, to.branchCount]);\n\n // ── Arrowhead ─────────────────────────────────────────────────────────────\n const arrowHeadPoints = useMemo(() => {\n const len = points.length;\n const tipX = points[len - 2];\n const tipY = points[len - 1];\n const prevX = points[len - 4];\n const prevY = points[len - 3];\n const angle = Math.atan2(tipY - prevY, tipX - prevX);\n const armLength = 11;\n const armAngle = Math.PI / 5.5; // ~33°\n return [\n tipX - armLength * Math.cos(angle - armAngle),\n tipY - armLength * Math.sin(angle - armAngle),\n tipX, tipY,\n tipX - armLength * Math.cos(angle + armAngle),\n tipY - armLength * Math.sin(angle + armAngle),\n ];\n }, [points]);\n\n // ── TextPath data (optional label) ────────────────────────────────────────\n const { pathData, fontSize } = useMemo(() => {\n if (!label) return { pathData: null, fontSize: 12 };\n\n const fromBaseX = from.width / 2;\n const fromBaseY = Math.max((NODE_HEIGHT * 1.6) / 2, fromBaseX * 0.74);\n const fromScale = getOutermostScaleUp(from.branchCount);\n const fromRadiusX = fromBaseX * fromScale;\n const fromRadiusY = fromBaseY * fromScale;\n\n const toBaseX = to.width / 2;\n const toBaseY = Math.max((NODE_HEIGHT * 1.6) / 2, toBaseX * 0.74);\n const toScale = getOutermostScaleUp(to.branchCount);\n const toRadiusX = toBaseX * toScale;\n const toRadiusY = toBaseY * toScale;\n\n const angle = Math.atan2(to.y - from.y, to.x - from.x);\n const fromEdge = getEllipseIntersection(from.x, from.y, fromRadiusX, fromRadiusY, angle);\n const toEdge = getEllipseIntersection(to.x, to.y, toRadiusX, toRadiusY, angle + Math.PI);\n\n const fromX = fromEdge.x + EDGE_SPACING * Math.cos(angle);\n const fromY = fromEdge.y + EDGE_SPACING * Math.sin(angle);\n const toX = toEdge.x - EDGE_SPACING * Math.cos(angle);\n const toY = toEdge.y - EDGE_SPACING * Math.sin(angle);\n\n const midX = (fromX + toX) / 2;\n const midY = (fromY + toY) / 2;\n const distance = Math.sqrt((toX - fromX) ** 2 + (toY - fromY) ** 2);\n const arcHeight = Math.min(45, 45 / (1 + Math.max(0, (distance - 200) / 400)));\n\n const perpX = -(toY - fromY) / distance;\n const perpY = (toX - fromX) / distance;\n\n const offsetMidX = midX + perpX * arcHeight;\n const offsetMidY = midY + perpY * arcHeight;\n\n const ctrl1X = fromX + (offsetMidX - fromX) * 0.66;\n const ctrl1Y = fromY + (offsetMidY - fromY) * 0.66;\n const ctrl2X = toX + (offsetMidX - toX) * 0.66;\n const ctrl2Y = toY + (offsetMidY - toY) * 0.66;\n\n const TEXT_OFFSET = 15;\n const fxo = fromX + perpX * TEXT_OFFSET; const fyo = fromY + perpY * TEXT_OFFSET;\n const txo = toX + perpX * TEXT_OFFSET; const tyo = toY + perpY * TEXT_OFFSET;\n const c1xo = ctrl1X + perpX * TEXT_OFFSET; const c1yo = ctrl1Y + perpY * TEXT_OFFSET;\n const c2xo = ctrl2X + perpX * TEXT_OFFSET; const c2yo = ctrl2Y + perpY * TEXT_OFFSET;\n\n // Variable font size: scales with zoom level to remain visible when zoomed out\n // and also scales with node width.\n const baseFontSize = 14;\n const zoomFactor = Math.max(1, 1 / zoomLevel); // Increase font size as we zoom out\n const scaledFontSize = Math.max(12, Math.min(24, baseFontSize * (from.width / 180) * zoomFactor));\n\n let d = '';\n if (fromX > toX) {\n d = `M ${txo},${tyo} C ${c2xo},${c2yo} ${c1xo},${c1yo} ${fxo},${fyo}`;\n } else {\n d = `M ${fxo},${fyo} C ${c1xo},${c1yo} ${c2xo},${c2yo} ${txo},${tyo}`;\n }\n return { pathData: d, fontSize: scaledFontSize };\n }, [from.x, from.y, from.width, from.branchCount, to.x, to.y, to.width, to.branchCount, label, zoomLevel]);\n\n // ── Render ────────────────────────────────────────────────────────────────\n const strokeColor = isDark ? STROKE_COLOR_DARK : STROKE_COLOR;\n \n return (\n <Group>\n <Line\n points={points}\n stroke={strokeColor}\n strokeWidth={STROKE_WIDTH}\n tension={0}\n opacity={0.9}\n lineCap=\"round\"\n lineJoin=\"round\"\n listening={false}\n perfectDrawEnabled={false}\n />\n <Line\n points={arrowHeadPoints}\n stroke={strokeColor}\n strokeWidth={STROKE_WIDTH}\n lineCap=\"round\"\n lineJoin=\"round\"\n opacity={0.9}\n listening={false}\n perfectDrawEnabled={false}\n />\n {label && pathData && (\n <>\n {/* Background text for contrast */}\n <TextPath\n data={pathData}\n text={label}\n fontSize={fontSize}\n fontFamily=\"'Playpen Sans', cursive\"\n fontStyle=\"normal\"\n fill=\"#ffffff\"\n align=\"center\"\n letterSpacing={0.5}\n listening={false}\n opacity={0.9}\n />\n {/* Foreground label text */}\n <TextPath\n data={pathData}\n text={label}\n fontSize={fontSize}\n fontFamily=\"'Playpen Sans', cursive\"\n fontStyle=\"normal\"\n fill=\"#6b6860\"\n align=\"center\"\n letterSpacing={0.5}\n listening={false}\n opacity={0.9}\n />\n </>\n )}\n </Group>\n );\n});\n\nexport default KonvaEdge;\n","// ─── KonvaContainerLayer ─────────────────────────────────────────────────────\n//\n// Renders container outlines beneath nodes (non-interactive).\n//\n// Node positions are read from useNodeStore (live), matching the visualli.ai\n// reference — containers follow dragged nodes in real-time every RAF frame.\n\nimport React, { useRef, useLayoutEffect } from 'react';\nimport { KLayer as Layer } from '../konvaCompat';\nimport type Konva from 'konva';\nimport type { FlatNode } from '@visualli/core';\nimport { useNodeStore } from '../stores/useNodeStore';\nimport KonvaContainer from './KonvaContainer';\n\nexport interface ContainerGroup {\n id: string;\n label?: string;\n nodeIds: string[];\n level: number;\n}\n\nexport interface KonvaContainerLayerProps {\n /** Layout-snapshot nodes — used only as a seed for initial IDs. */\n nodes: FlatNode[];\n containers: ContainerGroup[];\n isDark?: boolean;\n}\n\nexport default function KonvaContainerLayer({ nodes, containers, isDark = false }: KonvaContainerLayerProps) {\n const layerRef = useRef<Konva.Layer | null>(null);\n\n // Subscribe to live store — updated every RAF frame during drag.\n // This is the same pattern used by KonvaEdgeLayer so containers and edges\n // both track dragged nodes in real-time.\n const storeNodes = useNodeStore(s => s.nodes);\n\n // batchDraw deps include storeNodes so the layer redraws whenever any node\n // position changes (including mid-drag RAF updates).\n useLayoutEffect(() => { layerRef.current?.batchDraw(); }, [containers, isDark, storeNodes]);\n\n if (containers.length === 0) return null;\n\n return (\n <Layer ref={layerRef} listening={false}>\n {containers.map(c => {\n // Read positions from live store — not from the layout snapshot\n const groupNodes = c.nodeIds\n .map(id => storeNodes.get(id))\n .filter((n): n is FlatNode => !!n);\n if (groupNodes.length === 0) return null;\n\n return (\n <KonvaContainer\n key={c.id}\n nodes={groupNodes}\n label={c.label}\n isDark={isDark}\n />\n );\n })}\n </Layer>\n );\n}\n","// ─── KonvaContainer ──────────────────────────────────────────────────────────\n//\n// Renders a smooth dashed hull around a group of nodes with an inverse-scaled\n// pill label — matches the visualli.ai KonvaContainer exactly.\n//\n// • 48-point ellipse sampling per node (not bounding box corners)\n// • Graham-scan convex hull → 6-pass Chaikin smoothing\n// • Dashed stroke \"#747270\", no fill\n// • Pill label: parchment bg (#ddd9d0), Playpen Sans 800, inverse-zoom-scaled\n// • Label anchored to the hull edge (bottom for horizontal, top for vertical)\n\nimport React, { memo, useMemo } from 'react';\nimport {\n KGroup as Group,\n KLine as Line,\n KRect as Rect,\n KText as Text,\n} from '../konvaCompat';\nimport type { FlatNode } from '@visualli/core';\nimport { NODE_HEIGHT, TEXT_LABEL_HIDE_BELOW_ZOOM } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\nimport {\n CONTAINER_LABEL_BASE_FONT_PX,\n computeNodeTextScreenScale,\n} from '../config/textScaling';\n\n// ── Constants (mirrors visualli.ai) ──────────────────────────────────────────\n\nconst CONTAINER_PADDING = 50;\nconst CONTAINER_DASH = [10, 5] as const;\nconst LABEL_BG = '#ddd9d0';\nconst LABEL_BORDER_RADIUS = 20;\nconst LABEL_FONT_SIZE = CONTAINER_LABEL_BASE_FONT_PX;\nconst LABEL_FONT_WEIGHT = '800';\nconst LABEL_FONT_FAMILY = \"'Playpen Sans', Quicksand, sans-serif\";\nconst LABEL_PAD_H = 20;\nconst LABEL_PAD_V = 10;\nconst LABEL_LINE_HEIGHT = 1.2;\n// Max normalized blob extents — Shape 5 reaches ±1.275 X, ±1.234 Y\nconst MAX_BLOB_EXTENT_X = 1.275;\nconst MAX_BLOB_EXTENT_Y = 1.234;\n\n// ── Text measurement ──────────────────────────────────────────────────────────\n\nlet _labelCtx: CanvasRenderingContext2D | null = null;\nfunction measureLabelBoxWidth(text: string, fontSize: number): number {\n if (!_labelCtx) {\n const c = document.createElement('canvas');\n _labelCtx = c.getContext('2d');\n }\n if (!_labelCtx) return Math.ceil(text.length * fontSize * 0.65 + 2 * LABEL_PAD_H);\n _labelCtx.font = `${LABEL_FONT_WEIGHT} ${fontSize}px ${LABEL_FONT_FAMILY}`;\n return Math.ceil(_labelCtx.measureText(text).width + 2 * LABEL_PAD_H);\n}\n\n// ── Convex hull (Graham scan) ─────────────────────────────────────────────────\n\ntype Pt = { x: number; y: number };\n\nfunction isLeftTurn(p1: Pt, p2: Pt, p3: Pt): boolean {\n return (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x) > 0;\n}\n\nfunction convexHull(points: Pt[]): Pt[] {\n if (points.length < 3) return points;\n let start = 0;\n for (let i = 1; i < points.length; i++) {\n if (points[i].y < points[start].y ||\n (points[i].y === points[start].y && points[i].x < points[start].x)) start = i;\n }\n const sorted = [...points];\n const sp = sorted.splice(start, 1)[0];\n sorted.sort((a, b) => {\n const da = Math.atan2(a.y - sp.y, a.x - sp.x);\n const db = Math.atan2(b.y - sp.y, b.x - sp.x);\n if (da !== db) return da - db;\n return Math.hypot(a.x - sp.x, a.y - sp.y) - Math.hypot(b.x - sp.x, b.y - sp.y);\n });\n const hull: Pt[] = [sp, sorted[0]];\n for (let i = 1; i < sorted.length; i++) {\n while (hull.length > 1 && !isLeftTurn(hull[hull.length - 2], hull[hull.length - 1], sorted[i])) hull.pop();\n hull.push(sorted[i]);\n }\n return hull;\n}\n\n// ── Chaikin smoothing (6 passes, returns flat [x,y,…] array) ─────────────────\n\nfunction chaikinSmooth(pts: Pt[], passes = 6): number[] {\n let cur = pts;\n for (let iter = 0; iter < passes; iter++) {\n const next: Pt[] = [];\n const n = cur.length;\n for (let i = 0; i < n; i++) {\n const a = cur[i], b = cur[(i + 1) % n];\n next.push({ x: 0.75 * a.x + 0.25 * b.x, y: 0.75 * a.y + 0.25 * b.y });\n next.push({ x: 0.25 * a.x + 0.75 * b.x, y: 0.25 * a.y + 0.75 * b.y });\n }\n cur = next;\n }\n return cur.flatMap(p => [p.x, p.y]);\n}\n\n// ── Hull edge Y at a given X (for label anchor) ───────────────────────────────\n\nfunction hullEdgeYAtX(points: number[], targetX: number, isBottom: boolean): number {\n const n = points.length;\n let result = isBottom ? -Infinity : Infinity;\n for (let i = 0; i < n; i += 2) {\n const x1 = points[i], y1 = points[i + 1];\n const x2 = points[(i + 2) % n], y2 = points[(i + 3) % n];\n if ((x1 < targetX && x2 >= targetX) || (x2 < targetX && x1 >= targetX)) {\n const t = (targetX - x1) / (x2 - x1);\n const y = y1 + t * (y2 - y1);\n if (isBottom) result = Math.max(result, y); else result = Math.min(result, y);\n }\n }\n if (!isFinite(result)) {\n for (let i = 1; i < n; i += 2) {\n if (isBottom) result = Math.max(result, points[i]); else result = Math.min(result, points[i]);\n }\n }\n return result;\n}\n\n// ── Hull calculation ──────────────────────────────────────────────────────────\n\nfunction calculateHull(\n containerNodes: FlatNode[],\n): { points: number[]; anchorX: number; anchorEdgeY: number } | null {\n if (containerNodes.length === 0) return null;\n\n const NUM_SAMPLES = 48;\n const samples: Pt[] = [];\n for (const node of containerNodes) {\n const baseRX = node.width / 2;\n const baseRY = Math.max((NODE_HEIGHT * 1.6) / 2, baseRX * 0.74);\n const halfW = baseRX * MAX_BLOB_EXTENT_X + CONTAINER_PADDING;\n const halfH = baseRY * MAX_BLOB_EXTENT_Y + CONTAINER_PADDING;\n for (let j = 0; j < NUM_SAMPLES; j++) {\n const angle = (j / NUM_SAMPLES) * Math.PI * 2;\n samples.push({ x: node.x + halfW * Math.cos(angle), y: node.y + halfH * Math.sin(angle) });\n }\n }\n\n const hull = convexHull(samples);\n const points = chaikinSmooth(hull, 6);\n\n const xs = containerNodes.map(n => n.x);\n const ys = containerNodes.map(n => n.y);\n const spanX = Math.max(...xs) - Math.min(...xs);\n const spanY = Math.max(...ys) - Math.min(...ys);\n const useTopEdge = spanY > spanX * 2.0;\n\n let hullMinX = Infinity, hullMaxX = -Infinity;\n for (let i = 0; i < points.length; i += 2) {\n if (points[i] < hullMinX) hullMinX = points[i];\n if (points[i] > hullMaxX) hullMaxX = points[i];\n }\n const anchorX = (hullMinX + hullMaxX) / 2;\n const anchorEdgeY = hullEdgeYAtX(points, anchorX, !useTopEdge);\n\n return { points, anchorX, anchorEdgeY };\n}\n\n// ── Props ─────────────────────────────────────────────────────────────────────\n\nexport interface KonvaContainerProps {\n /** All nodes in this container group (already resolved from nodeMap). */\n nodes: FlatNode[];\n /** Label text shown on the pill badge. */\n label?: string;\n /** Unused – kept for API compat; stroke is always #747270. */\n color?: string;\n isDark?: boolean;\n}\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nconst KonvaContainer = memo(function KonvaContainer({\n nodes,\n label = '',\n}: KonvaContainerProps) {\n const zoomLevel = useViewportStore(s => s.zoomLevel);\n\n const hullData = useMemo(() => calculateHull(nodes), [nodes]);\n\n if (!hullData) return null;\n\n // Inverse-scaled label metrics\n const refNode = nodes[0];\n const screenScale = refNode ? computeNodeTextScreenScale(refNode.width, zoomLevel) : 1;\n const labelFontSize = LABEL_FONT_SIZE * screenScale;\n const labelBoxHeight = Math.ceil(labelFontSize * LABEL_LINE_HEIGHT + 2 * LABEL_PAD_V);\n const boxWidth = label ? measureLabelBoxWidth(label, labelFontSize) : 0;\n const boxX = hullData.anchorX - boxWidth / 2;\n const boxY = hullData.anchorEdgeY - labelBoxHeight / 2;\n\n return (\n <Group listening={false}>\n {/* Dashed hull outline */}\n <Line\n points={hullData.points}\n stroke=\"#747270\"\n strokeWidth={1}\n dash={CONTAINER_DASH}\n closed={true}\n tension={0}\n listening={false}\n perfectDrawEnabled={false}\n />\n\n {/* Inverse-scaled pill label */}\n {label.length > 0 && (\n <Group\n x={boxX + boxWidth / 2}\n y={boxY + labelBoxHeight / 2}\n offsetX={boxWidth / 2}\n offsetY={labelBoxHeight / 2}\n scaleX={1 / zoomLevel}\n scaleY={1 / zoomLevel}\n visible={zoomLevel >= TEXT_LABEL_HIDE_BELOW_ZOOM}\n listening={false}\n >\n <Rect\n width={boxWidth}\n height={labelBoxHeight}\n fill={LABEL_BG}\n cornerRadius={LABEL_BORDER_RADIUS}\n shadowEnabled={false}\n perfectDrawEnabled={false}\n />\n <Text\n x={LABEL_PAD_H}\n y={LABEL_PAD_V}\n width={boxWidth - 2 * LABEL_PAD_H}\n height={labelBoxHeight - 2 * LABEL_PAD_V}\n text={label}\n fontSize={labelFontSize}\n fontFamily={LABEL_FONT_FAMILY}\n fontStyle={LABEL_FONT_WEIGHT}\n fill=\"rgba(0,0,0,1)\"\n align=\"center\"\n verticalAlign=\"middle\"\n lineHeight={LABEL_LINE_HEIGHT}\n perfectDrawEnabled={false}\n listening={false}\n />\n </Group>\n )}\n </Group>\n );\n});\n\nexport default KonvaContainer;\n","// ─── Text Scaling Helpers ─────────────────────────────────────────────────────\n//\n// Determines the scale applied to node title text, keeping text legible and\n// fitted inside the blob shape across the full zoom range.\n//\n// Matches the visualli.ai textScaling logic exactly.\n\nimport { NODE_HEIGHT } from '@visualli/core';\n\nexport const NODE_TEXT_BASE_FONT_PX = 30;\nexport const DESCRIPTION_TEXT_BASE_FONT_PX = 12;\nexport const CONTAINER_LABEL_BASE_FONT_PX = 24;\nexport const EDGE_LABEL_BASE_FONT_PX = 18;\nexport const OVERLAY_FONT_UPPER_BOOST_PX = 8;\n\n// Keep text away from blob edges\nconst NODE_TEXT_SAFE_BLOB_FILL_RATIO = 0.88;\n\n/**\n * Computes world-space text scale for node title:\n * - inverse zoom for screen-space consistency\n * - clamped so text stays inside the node blob with safe padding\n * - uses base width of 300px for consistent text sizing\n * - allows taller text box for multi-line wrapping\n *\n * Improved from visualli.ai to handle long labels better with multi-line support.\n */\nexport function computeNodeTextWorldScale(nodeWidth: number, zoomLevel: number): number {\n const safeZoom = Math.max(zoomLevel, 0.0001);\n \n // Use a consistent base width (300px) for text scaling\n // This keeps font size more consistent across different node widths\n const baseWidth = 300;\n \n const baseRadiusX = baseWidth / 2;\n const baseRadiusY = Math.max((NODE_HEIGHT * 1.6) / 2, baseRadiusX * 0.74);\n const textNaturalWidth = baseWidth - 40;\n // Increase text height to allow 2-3 lines of wrapped text\n const textNaturalHeight = NODE_HEIGHT * 1.2;\n\n const maxScaleX = ((baseRadiusX * 2) * NODE_TEXT_SAFE_BLOB_FILL_RATIO) / Math.max(textNaturalWidth, 1);\n const maxScaleY = ((baseRadiusY * 2) * NODE_TEXT_SAFE_BLOB_FILL_RATIO) / Math.max(textNaturalHeight, 1);\n const fitScale = Math.max(0.01, Math.min(maxScaleX, maxScaleY));\n\n return Math.min(1 / safeZoom, fitScale);\n}\n\n/** Screen-space scale (zoom-adjusted) for text overlays. */\nexport function computeNodeTextScreenScale(nodeWidth: number, zoomLevel: number): number {\n return computeNodeTextWorldScale(nodeWidth, zoomLevel) * zoomLevel;\n}\n\n/**\n * Screen-space overlay scale for description/semantic tooltips.\n * - lower bound: 1x\n * - upper bound: node-title-root + OVERLAY_FONT_UPPER_BOOST_PX\n */\nexport function computeOverlayScale(zoomLevel: number): number {\n const safeZoom = Math.max(zoomLevel, 0.0001);\n const inverseScale = 1 / safeZoom;\n const maxScale = (NODE_TEXT_BASE_FONT_PX + OVERLAY_FONT_UPPER_BOOST_PX) / NODE_TEXT_BASE_FONT_PX;\n return Math.min(Math.max(inverseScale, 1), maxScale);\n}\n\n/** Scale for edge path labels in screen pixels. */\nexport function computeEdgeLabelScale(zoomLevel: number): number {\n const safeZoom = Math.max(zoomLevel, 0.0001);\n return Math.min(Math.max(EDGE_LABEL_BASE_FONT_PX / safeZoom, 10), 32);\n}\n","// ─── NavigationStack ─────────────────────────────────────────────────────────\n//\n// Vertical navigation stack rendered as a fixed left-side overlay.\n// Matches the visualli.ai VisualliNavigationStack design:\n// • Organic hand-drawn circle SVGs per level\n// • Vertical connector lines between levels\n// • Active level highlighted, previous levels clickable to navigate back\n// • Font: Nunito\n\nimport React, { memo, useState } from 'react';\nimport type { VisualliLayer } from '@visualli/core';\n\nexport interface NavStackEntry {\n layerId: string;\n layer: VisualliLayer;\n label: string;\n}\n\nexport interface NavigationStackProps {\n stack: NavStackEntry[];\n onNavigateBack: (index: number) => void;\n isDark?: boolean;\n top?: string;\n left?: string;\n}\n\n// Pastel fills cycled across levels\nconst PASTEL_FILLS = [\n '#b6eea7', '#d5bcfe', '#a1c4fc', '#a6f5d8',\n '#ffc9de', '#c4e8ff', '#f0c4ff', '#ffe0a3',\n];\n\n// Organic circle SVG paths (small / active variants matching visualli.ai)\nconst ORGANIC_PATHS_SMALL = [\n 'M13.72,6.31 C15.12,6.29 17.96,8.57 17.99,10.60 C18.07,14.62 16.72,17.90 11.12,18.00 C7.26,18.07 4.07,14.86 4.00,10.85 C3.93,6.83 9.44,2.02 13.69,4.85',\n 'M13.88,6.41 C15.28,6.43 18.04,8.82 18.00,10.85 C17.93,14.86 16.48,18.10 10.88,18.00 C7.02,17.93 3.94,14.62 4.01,10.60 C4.08,6.59 9.76,1.97 13.91,4.95',\n];\nconst ORGANIC_PATH_ACTIVE =\n 'M16.55,9.22 C17.95,9.15 20.87,11.33 20.97,13.36 C21.19,17.37 19.96,20.70 14.37,20.99 C10.51,21.19 7.20,18.10 7.00,14.09 C6.78,10.08 12.13,5.08 16.48,7.77';\n\nconst CIRCLE_SIZE = 14;\n\nfunction hexToRgba(hex: string, opacity: number): string {\n const h = hex.replace('#', '');\n const r = parseInt(h.substring(0, 2), 16);\n const g = parseInt(h.substring(2, 4), 16);\n const b = parseInt(h.substring(4, 6), 16);\n return `rgba(${r},${g},${b},${opacity})`;\n}\n\nconst OrganicCircle = memo(function OrganicCircle({\n size, fill, stroke, strokeWidth, variant, isActive,\n}: {\n size: number; fill: string; stroke: string; strokeWidth: number; variant: number; isActive?: boolean;\n}) {\n const path = isActive ? ORGANIC_PATH_ACTIVE : ORGANIC_PATHS_SMALL[variant % ORGANIC_PATHS_SMALL.length];\n const vb = isActive ? '4 3 20 20' : '2 1 18 18';\n const vbSz = isActive ? 20 : 18;\n const sw = strokeWidth * vbSz / size;\n return (\n <svg width={size} height={size} viewBox={vb} fill=\"none\" style={{ display: 'block' }}>\n <path d={path} fill={fill} fillOpacity={1} />\n <path d={path} fill=\"none\" stroke={stroke} strokeWidth={sw} strokeLinecap=\"round\" />\n </svg>\n );\n});\n\nconst NavigationStack = memo(function NavigationStack({\n stack,\n onNavigateBack,\n isDark = false,\n top = '16px',\n left = '16px',\n}: NavigationStackProps) {\n const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);\n\n // Always render at least the root entry so the user knows where they are.\n if (stack.length === 0) return null;\n\n const visitedStroke = isDark ? '#908e8c' : '#747270';\n const visitedText = isDark ? '#908e8c' : '#747270';\n const activeStroke = isDark ? '#e8e6e4' : '#1a1a18';\n const activeText = isDark ? '#e8e6e4' : '#1a1a18';\n const connectorColor = isDark ? '#908e8c' : '#747270';\n const connectorMarginLeft = 10.5; // padding(4) + circleHalf(7) - connectorHalf(0.5)\n const currentIndex = stack.length - 1;\n\n return (\n <div\n data-help=\"navigation-stack\"\n style={{\n position: 'absolute',\n top,\n left,\n zIndex: 30,\n pointerEvents: 'auto',\n }}\n >\n <div style={{ display: 'flex', flexDirection: 'column', padding: '8px' }}>\n {stack.flatMap((entry, index) => {\n const isCurrent = index === currentIndex;\n const isClickable = index < currentIndex;\n const isHovered = hoveredIndex === index;\n const pastelFill = PASTEL_FILLS[index % PASTEL_FILLS.length];\n const rowBg = isCurrent\n ? hexToRgba(pastelFill, 0.6)\n : isHovered && isClickable\n ? hexToRgba(pastelFill, 0.3)\n : 'transparent';\n\n const items: React.ReactNode[] = [];\n\n if (index > 0) {\n items.push(\n <div\n key={`conn-${index}`}\n style={{\n width: '1px',\n height: '20px',\n marginLeft: `${connectorMarginLeft}px`,\n marginTop: '-6px',\n marginBottom: '-6px',\n background: connectorColor,\n alignSelf: 'flex-start',\n flexShrink: 0,\n position: 'relative',\n zIndex: 1,\n }}\n />,\n );\n }\n\n items.push(\n <div\n key={`${entry.layerId}-${index}`}\n style={{\n position: 'relative',\n zIndex: 2,\n alignSelf: 'flex-start',\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n height: '22px',\n padding: '4px',\n borderRadius: '8px',\n cursor: isClickable ? 'pointer' : 'default',\n background: rowBg,\n transition: 'background 0.15s',\n }}\n onMouseEnter={() => setHoveredIndex(index)}\n onMouseLeave={() => setHoveredIndex(null)}\n onClick={e => { e.stopPropagation(); if (isClickable) onNavigateBack(index); }}\n >\n <div style={{ width: CIRCLE_SIZE, height: CIRCLE_SIZE, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, zIndex: 4 }}>\n {isCurrent ? (\n <OrganicCircle size={CIRCLE_SIZE} fill={pastelFill} stroke={activeStroke} strokeWidth={1.5} variant={index} isActive />\n ) : (\n <OrganicCircle size={CIRCLE_SIZE} fill={pastelFill} stroke={visitedStroke} strokeWidth={1} variant={index} />\n )}\n </div>\n <span\n style={{\n fontFamily: \"'Nunito', sans-serif\",\n fontSize: isCurrent || (isHovered && isClickable) ? '11px' : '9px',\n fontWeight: isCurrent ? 600 : 400,\n color: isCurrent ? activeText : visitedText,\n lineHeight: 1,\n whiteSpace: 'nowrap',\n transition: 'color 0.15s, font-size 0.15s',\n }}\n >\n {entry.label}\n </span>\n </div>,\n );\n\n return items;\n })}\n </div>\n </div>\n );\n});\n\nexport default NavigationStack;\n","// ─── ZoomControls ─────────────────────────────────────────────────────────────\n//\n// Floating zoom control matching the visualli.ai design:\n// • Side-by-side ZoomIn / ZoomOut buttons (65×32px)\n// • SVG icons (no external dependency)\n// • Inline styles (no Tailwind required in SDK)\n\nimport React, { useCallback, memo } from 'react';\nimport { ZOOM_MIN, ZOOM_MAX } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\n\nexport interface ZoomControlsProps {\n isDark?: boolean;\n}\n\n// ── ZoomIn SVG (Lucide-compatible path) ───────────────────────────────────────\nconst ZoomInIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\n <line x1=\"11\" y1=\"8\" x2=\"11\" y2=\"14\" />\n <line x1=\"8\" y1=\"11\" x2=\"14\" y2=\"11\" />\n </svg>\n);\n\n// ── ZoomOut SVG ───────────────────────────────────────────────────────────────\nconst ZoomOutIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\" />\n <line x1=\"8\" y1=\"11\" x2=\"14\" y2=\"11\" />\n </svg>\n);\n\nconst ZOOM_STEP = 0.2;\n\nconst ZoomControls = memo(function ZoomControls({ isDark = false }: ZoomControlsProps) {\n const zoomLevel = useViewportStore(s => s.zoomLevel);\n const setZoom = useViewportStore(s => s.setZoom);\n\n const handleZoomIn = useCallback(() => setZoom(Math.min(ZOOM_MAX, zoomLevel * 1.2)), [zoomLevel, setZoom]);\n const handleZoomOut = useCallback(() => setZoom(Math.max(ZOOM_MIN, zoomLevel / 1.2)), [zoomLevel, setZoom]);\n\n const surfaceBg = isDark ? 'var(--bg-surface, #1C1C1A)' : 'var(--bg-surface, #FAF8F4)';\n const border = isDark ? 'var(--border-color, #333330)' : 'var(--border-color, #DDD9D0)';\n const primary = isDark ? 'var(--text-primary, #F0EDE6)' : 'var(--text-primary, #1A1A18)';\n const muted = isDark ? 'var(--text-muted, #8E8C88)' : 'var(--text-muted, #747270)';\n\n return (\n <div\n style={{\n position: 'relative',\n background: surfaceBg,\n border: `0.5px solid ${border}`,\n borderRadius: '8px',\n overflow: 'hidden',\n width: '65px',\n height: '32px',\n flexShrink: 0,\n }}\n role=\"group\"\n aria-label=\"Zoom controls\"\n >\n {/* Zoom In — left half */}\n <button\n onClick={handleZoomIn}\n disabled={zoomLevel >= ZOOM_MAX}\n style={{\n position: 'absolute',\n top: 0, left: 0,\n width: '32px', height: '100%',\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n border: 'none', background: 'transparent', cursor: zoomLevel >= ZOOM_MAX ? 'not-allowed' : 'pointer',\n color: zoomLevel >= ZOOM_MAX ? muted : primary,\n transition: 'background 0.15s',\n }}\n onMouseEnter={e => { if (zoomLevel < ZOOM_MAX) (e.currentTarget as HTMLButtonElement).style.background = isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.05)'; }}\n onMouseLeave={e => { (e.currentTarget as HTMLButtonElement).style.background = 'transparent'; }}\n aria-label=\"Zoom in\"\n >\n <ZoomInIcon />\n </button>\n\n {/* Divider */}\n <div style={{ position: 'absolute', top: 0, bottom: 0, left: '32px', width: '0.5px', background: border }} />\n\n {/* Zoom Out — right half */}\n <button\n onClick={handleZoomOut}\n disabled={zoomLevel <= ZOOM_MIN}\n style={{\n position: 'absolute',\n top: 0, right: 0,\n width: '33px', height: '100%',\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n border: 'none', background: 'transparent', cursor: zoomLevel <= ZOOM_MIN ? 'not-allowed' : 'pointer',\n color: zoomLevel <= ZOOM_MIN ? muted : primary,\n transition: 'background 0.15s',\n }}\n onMouseEnter={e => { if (zoomLevel > ZOOM_MIN) (e.currentTarget as HTMLButtonElement).style.background = isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.05)'; }}\n onMouseLeave={e => { (e.currentTarget as HTMLButtonElement).style.background = 'transparent'; }}\n aria-label=\"Zoom out\"\n >\n <ZoomOutIcon />\n </button>\n </div>\n );\n});\n\nexport default ZoomControls;\n","// ─── SketchyBoxKonva ─────────────────────────────────────────────────────────\n//\n// Renders the hand-drawn tooltip box using an imperative Konva canvas.\n// Two paths are scaled to fit the container:\n// - BACK_PATH : shadow stroke, offset 8px down\n// - FRONT_PATH: filled main box, offset 5.65px right\n//\n// Matches the visualli.ai SketchyBoxKonva component exactly.\n\nimport React, { useEffect, useRef } from 'react';\nimport Konva from 'konva';\n\nconst BACK_PATH =\n 'M0.653,0 L485.653,1 C485.653,1,484.782,152.773,' +\n '486.653,165 C413.653,171,14.653,178,5.653,168' +\n 'C2.653,158,0.653,0,0.653,0';\n\nconst FRONT_PATH =\n 'M485,167.524 L0,166.524' +\n 'C0,166.524,1.870,8.751,0,0' +\n 'C73,0,479,0,487,8' +\n 'C490,18,485,167.524,485,167.524';\n\nconst BACK_W = 486;\nconst BACK_H = 178;\nconst FRONT_W = 490;\nconst FRONT_H = 168;\n\nconst BACK_OFFSET_Y = 8;\nconst FRONT_OFFSET_X = 5.65;\nconst SHADOW_PAD = 12;\n\nexport interface SketchyBoxKonvaProps {\n children: React.ReactNode;\n fill: string;\n stroke: string;\n backStroke: string;\n padding?: string;\n}\n\nconst SketchyBoxKonva: React.FC<SketchyBoxKonvaProps> = ({\n children,\n fill,\n stroke,\n backStroke,\n padding = '1rem 1.25rem',\n}) => {\n const wrapperRef = useRef<HTMLDivElement>(null);\n const konvaContainerRef = useRef<HTMLDivElement>(null);\n const stageRef = useRef<Konva.Stage | null>(null);\n\n useEffect(() => {\n const wrapper = wrapperRef.current;\n const konvaEl = konvaContainerRef.current;\n if (!wrapper || !konvaEl) return;\n\n function draw(W: number, H: number) {\n if (!konvaEl || W <= 0 || H <= 0) return;\n if (stageRef.current) { stageRef.current.destroy(); stageRef.current = null; }\n\n const stage = new Konva.Stage({ container: konvaEl, width: W, height: H });\n const layer = new Konva.Layer({ listening: false });\n const contentH = H - SHADOW_PAD;\n\n layer.add(new Konva.Path({\n x: 0, y: BACK_OFFSET_Y,\n data: BACK_PATH,\n scaleX: W / BACK_W,\n scaleY: contentH / BACK_H,\n fill: '#ffffff',\n stroke: backStroke,\n strokeWidth: 2,\n strokeScaleEnabled: false,\n listening: false,\n }));\n\n layer.add(new Konva.Path({\n x: FRONT_OFFSET_X, y: 0,\n data: FRONT_PATH,\n scaleX: (W - FRONT_OFFSET_X) / FRONT_W,\n scaleY: contentH / FRONT_H,\n fill,\n stroke,\n strokeWidth: 3,\n strokeScaleEnabled: false,\n listening: false,\n }));\n\n stage.add(layer);\n stageRef.current = stage;\n }\n\n draw(wrapper.offsetWidth, wrapper.offsetHeight);\n\n const ro = new ResizeObserver(entries => {\n const el = entries[0].target as HTMLElement;\n draw(el.offsetWidth, el.offsetHeight);\n });\n ro.observe(wrapper);\n\n return () => {\n ro.disconnect();\n stageRef.current?.destroy();\n stageRef.current = null;\n };\n }, [fill, stroke, backStroke]);\n\n return (\n <div ref={wrapperRef} style={{ position: 'relative', paddingBottom: `${SHADOW_PAD}px` }}>\n <div\n ref={konvaContainerRef}\n style={{ position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 0, overflow: 'hidden' }}\n />\n <div style={{ position: 'relative', padding, zIndex: 1 }}>\n {children}\n </div>\n </div>\n );\n};\n\nexport default SketchyBoxKonva;\n","// ─── Visualli Context ─────────────────────────────────────────────────────────\n//\n// React Context for Visualli components (minimal implementation)\n\nimport React, { createContext, useContext } from 'react';\n\nexport interface VisualliContextValue {\n // Reserved for future use\n}\n\nconst VisualliContext = createContext<VisualliContextValue | null>(null);\n\nexport interface VisualliProviderProps {\n children: React.ReactNode;\n}\n\n/**\n * Provider for Visualli context\n * \n * @example\n * ```tsx\n * <VisualliProvider>\n * <VisualliCanvas document={doc} />\n * </VisualliProvider>\n * ```\n */\nexport function VisualliProvider({\n children,\n}: VisualliProviderProps) {\n const value: VisualliContextValue = {};\n\n return (\n <VisualliContext.Provider value={value}>\n {children}\n </VisualliContext.Provider>\n );\n}\n\n/**\n * Hook to access Visualli context\n * \n * Returns default empty values if used outside of VisualliProvider\n */\nexport function useVisualli(): VisualliContextValue {\n const ctx = useContext(VisualliContext);\n if (!ctx) {\n return {};\n }\n return ctx;\n}\n"],"mappings":"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","names":["import_react","import_core","import_react","import_core","set","import_zustand","import_zustand","import_core","stage","import_react","import_core","import_core","import_react","KonvaStage","import_react","import_react","import_core","import_react","import_core","import_core","import_jsx_runtime","React","KonvaNode","import_jsx_runtime","import_react","import_react","import_core","import_jsx_runtime","KonvaEdge","import_jsx_runtime","import_react","import_react","import_core","import_core","DESCRIPTION_TEXT_BASE_FONT_PX","CONTAINER_LABEL_BASE_FONT_PX","computeNodeTextWorldScale","computeNodeTextScreenScale","import_jsx_runtime","CONTAINER_LABEL_BASE_FONT_PX","KonvaContainer","computeNodeTextScreenScale","import_jsx_runtime","import_react","import_jsx_runtime","OrganicCircle","NavigationStack","import_react","import_core","import_jsx_runtime","ZoomControls","import_react","import_jsx_runtime","Konva","import_jsx_runtime","hexToRgba","DESCRIPTION_TEXT_BASE_FONT_PX","import_jsx_runtime","import_react","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/VisualliRenderer.tsx","../src/VisualliCanvas.tsx","../src/stores/useNodeStore.ts","../src/stores/useViewportStore.ts","../src/stores/stores.ts","../src/hooks/useKonvaRenderer.ts","../src/hooks/useLayerChoreography.ts","../src/utils/layerNavigation.ts","../src/design/choreography.ts","../src/components/KonvaStage.tsx","../src/konvaCompat.ts","../src/design/runtime.ts","../src/generated/specCss.ts","../src/components/KonvaNodeLayer.tsx","../src/design/design.ts","../src/design/drawing.ts","../src/components/useFrames.ts","../src/components/KonvaEdgeLayer.tsx","../src/components/KonvaContainerLayer.tsx","../src/design/containers.ts","../src/components/KonvaContainerLabelLayer.tsx","../src/components/NavigationStack.tsx","../src/components/Overlays.tsx","../src/components/A11yLayer.tsx","../src/design/useDesign.ts","../src/design/measure.ts","../src/context/VisualliContext.tsx","../src/hooks/useViewportNodes.ts","../src/components/KonvaNode.tsx","../src/components/KonvaEdge.tsx","../src/components/KonvaContainer.tsx"],"sourcesContent":["// ─── @visualli/react ─────────────────────────────────────────────────────────\n\n// ── Primary component (recommended for public use) ────────────────────────────────────────\nexport { default as VisualliRenderer } from './VisualliRenderer';\nexport type { VisualliRendererProps, VisualliTheme } from './VisualliRenderer';\n\n// ── Canvas component (for advanced integrations) ───────────────────────────────────────────\nexport { default as VisualliCanvas } from './VisualliCanvas';\nexport type { VisualliCanvasProps } from './VisualliCanvas';\n\n// ── Context and Provider ──────────────────────────────────────────────────────\nexport { VisualliProvider, useVisualli } from './context/VisualliContext';\nexport type { \n VisualliProviderProps, \n VisualliContextValue\n} from './context/VisualliContext';\n\n// Stores\nexport { useNodeStore } from './stores/useNodeStore';\nexport { useViewportStore } from './stores/useViewportStore';\nexport { useSelectionStore, useRenderConfigStore } from './stores/stores';\nexport type { INodeStore } from './stores/useNodeStore';\nexport type { IViewportStore } from './stores/useViewportStore';\n\n// Hooks\nexport { useKonvaRenderer } from './hooks/useKonvaRenderer';\nexport { useLayerChoreography } from './hooks/useLayerChoreography';\nexport type { LayerChoreography, LayerChoreographyOptions } from './hooks/useLayerChoreography';\nexport { useViewportNodes } from './hooks/useViewportNodes';\nexport type { UseKonvaRendererOptions, UseKonvaRendererReturn } from './hooks/useKonvaRenderer';\n\nexport type { AnimatorViewport } from './hooks/useLayerChoreography';\n\n// Design system: themes, comfort, tokens, geometry (generated from design-system/ in @visualli/core)\nexport {\n THEME_NAMES, TOPICS, DESIGN_SYSTEM_VERSION, TOKENS, METRICS,\n resolveTheme, resolveComfort, ideaColor, ideaStyle, topicStyle, getTokens,\n BLOB_SHAPES, RINGS, blobPath, blobRadius, edgePath, arrowPath, shapeForLevel,\n IDEA, LABEL_GROWTH, ideaSize, labelGrowth,\n} from '@visualli/core';\nexport type { ThemeName, ThemeInput, TopicName, Comfort } from '@visualli/core';\nexport { useDesign, useReaderEnv } from './design/useDesign';\nexport { makeDesign, resolveDesign, DEFAULT_DESIGN } from './design/design';\nexport type { Design, DesignProps } from './design/design';\nexport { ensureDesignSystemStyles, loadCanvasFonts } from './design/runtime';\nexport type { DesignSystemAssets } from './design/runtime';\n\n// Utils\nexport {\n getConnectionsForLayer,\n getChildLayerForNode,\n getLayerForNavigation,\n calculateFitZoom,\n calculateFitCenter,\n calculateFitView,\n} from './utils/layerNavigation';\nexport type { FitResult } from './utils/layerNavigation';\n\n// Sub-components (for advanced usage / composition)\nexport { default as KonvaStage } from './components/KonvaStage';\nexport { default as KonvaNode } from './components/KonvaNode';\nexport { default as KonvaEdge } from './components/KonvaEdge';\nexport { default as KonvaNodeLayer } from './components/KonvaNodeLayer';\nexport { default as KonvaEdgeLayer } from './components/KonvaEdgeLayer';\nexport { default as KonvaContainer } from './components/KonvaContainer';\nexport { default as KonvaContainerLayer } from './components/KonvaContainerLayer';\nexport { default as KonvaContainerLabelLayer } from './components/KonvaContainerLabelLayer';\nexport { default as NavigationStack } from './components/NavigationStack';\nexport { default as ZoomControls } from './components/ZoomControls';\nexport { PeekCard, TermCard, DepthTrail, splitTerms, paintVars } from './components/Overlays';\nexport { A11yLayer } from './components/A11yLayer';\nexport type { NavStackEntry } from './components/NavigationStack';\nexport type { PeekCardProps, TrailEntry, DepthTrailProps, IdeaPaint } from './components/Overlays';\nexport { ideaMeasure } from './design/measure';\nexport type { KonvaNodeProps } from './components/KonvaNode';\nexport type { KonvaEdgeProps } from './components/KonvaEdge';\nexport type { KonvaStageProps } from './components/KonvaStage';\nexport type { ContainerGroup } from './components/KonvaContainerLayer';\nexport { layoutContainers, measurePill, drawHull, drawPill } from './design/containers';\nexport type { PlacedContainer, PlacedPill } from './design/containers';\n\n","// ─── VisualliRenderer ────────────────────────────────────────────────────────\n//\n// The single public-facing component for rendering a .visualli document.\n//\n// <VisualliRenderer visualliString={str} theme=\"dark\" width=\"100%\" height=\"600px\" />\n// <VisualliRenderer visualliFile={file} theme=\"auto\" width={800} height={600} />\n// <VisualliRenderer document={doc} theme=\"auto\" width={800} height={600} />\n//\n// Handles:\n// • theme: 'dark' | 'light' | 'auto' — auto follows prefers-color-scheme\n// • width / height as first-class props (CSS string or pixel number)\n// • Empty state — no data prop provided\n// • Loading state — while parsing a .visualli file/string\n// • Error state — parse failure with message\n// • useWorker — offload parsing to a Web Worker (default: false)\n// • Delegates all canvas/navigation/zoom logic to VisualliCanvas\n\nimport React, { useEffect, useRef, useState, useMemo } from 'react';\nimport type { VisualliDocument, Comfort, ThemeInput, TopicName } from '@visualli/core';\nimport { blobPath, parseVisualliFile, shapeForLevel } from '@visualli/core';\nimport VisualliCanvas from './VisualliCanvas';\nimport { useDesign } from './design/useDesign';\nimport { ensureDesignSystemStyles, type DesignSystemAssets } from './design/runtime';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\n/**\n * Any of the 8 design-system themes ('light', 'dark', 'focus-light', 'focus-dark', 'colorsafe-light',\n * 'colorsafe-dark', 'contrast-light', 'contrast-dark'), a family ('focus' | 'colorsafe' | 'contrast'),\n * or 'auto' (follow the reader's colour scheme). 'light' | 'dark' | 'auto' are the pre-0.2 values and keep working.\n */\nexport type VisualliTheme = ThemeInput;\n\nexport interface VisualliRendererProps {\n /**\n * Raw JSONL string — the content of a .visualli file.\n * Simply pass the string data directly, no preprocessing needed.\n * Example: visualliString=\"{\\\"type\\\":\\\"meta\\\"...}\\n{\\\"type\\\":\\\"layer\\\"...}\"\n */\n visualliString?: string;\n\n /**\n * A .visualli file — can be:\n * - File object (e.g. from <input type=\"file\">)\n * - String path to file (e.g. '/data/myfile.visualli' or './src/data/data.visualli')\n * The renderer automatically fetches, reads, and parses it.\n * No user code required for conversion or processing.\n */\n visualliFile?: File | string;\n\n /**\n * When true, parsing is offloaded to a Web Worker so the main thread never\n * blocks during JSON.parse. Recommended for large documents (>500 nodes).\n * Has no effect when `document` is supplied (already parsed).\n * @default true\n */\n useWorker?: boolean;\n\n /**\n * Colour theme (see VisualliTheme).\n * - 'auto' follows prefers-color-scheme (and switches to high contrast under forced-colors)\n * @default 'light'\n */\n theme?: VisualliTheme;\n\n /** Comfort settings: readable type, larger text, reduced motion ('system' follows the OS). */\n comfort?: Comfort;\n\n /** Switch to the high-contrast theme under forced-colors. @default true */\n respectForcedColors?: boolean;\n\n /**\n * Interaction layout: 'auto' follows the reader's input (touch -> bottom-sheet peek and larger\n * controls, pointer -> floating peek on hover); force one with 'touch' or 'pointer'.\n * @default 'auto'\n */\n layout?: 'auto' | 'touch' | 'pointer';\n\n /** Where the zoom / fit controls sit: the design system's 'bottom-right' (default) or the pre-0.2 'top-right'. */\n /**\n * The map is the page (an app such as Visualli's web app): it takes every touch gesture, so the browser never\n * zooms or scrolls the page — the design system's `.vi-map.is-app` (`touch-action: none`). Leave it off when the\n * map is embedded in a scrolling page: one finger then still scrolls the page, two fingers pinch the map.\n */\n app?: boolean;\n /** Where the zoom / fit controls sit: 'top-right' (default, the design system's placement) or 'bottom-right'. */\n controlsPosition?: 'top-right' | 'bottom-right';\n\n /**\n * Enable chromatic immersion background effect.\n * When true:\n * - Root layer (level 0) shows the plain canvas\n * - Child layers are tinted with the parent idea's topic colour\n * @default false\n */\n chromaticImmersion?: boolean;\n\n /**\n * Width of the renderer. Accepts any CSS length string ('100%', '800px', '100vw')\n * or a plain number treated as pixels.\n * @default '100%'\n */\n width?: string | number;\n\n /**\n * Height of the renderer. Accepts any CSS length string ('100%', '600px', '100vh')\n * or a plain number treated as pixels.\n * @default '100%'\n */\n height?: string | number;\n\n /** Directory URL the bundled Caveat font is served from (defaults to the copy in the npm package, via jsDelivr). */\n fontBaseUrl?: DesignSystemAssets['fontBaseUrl'];\n\n /** Set false when you load Kalam and Atkinson Hyperlegible yourself. */\n loadWebFonts?: DesignSystemAssets['loadWebFonts'];\n\n /** Additional CSS class on the root element. */\n className?: string;\n\n /** Additional inline styles merged onto the root element. */\n style?: React.CSSProperties;\n}\n\n// ── Empty / Loading / Error states ───────────────────────────────────────────\n// A still note in the middle of the map: an idea's blob in a topic colour, a title and a line of text — the design\n// system's shapes, tokens and type styles only, and no motion of its own (the product's own state screens live in\n// Visualli's apps).\n\nconst stateBox: React.CSSProperties = { display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', width: '100%', height: '100%', gap: 'var(--space-3)', padding: 'var(--space-7)', boxSizing: 'border-box', textAlign: 'center', color: 'var(--ink-muted)', background: 'var(--canvas)' };\n\nfunction StateNote({ topic, title, children, role }: { topic: TopicName; title: string; children?: React.ReactNode; role?: 'status' | 'alert' }) {\n return (\n <div className=\"vi-map\" style={stateBox} role={role} aria-live={role === 'status' ? 'polite' : undefined}>\n <svg width=\"64\" height=\"52\" viewBox=\"-32 -26 64 52\" aria-hidden=\"true\">\n <path d={blobPath(shapeForLevel(0), 26, 20)} fill={`var(--topic-${topic})`} stroke={`var(--topic-${topic}-ring)`} strokeWidth=\"2\" />\n </svg>\n <p className=\"vi-text-label\" style={{ margin: 0, color: 'var(--ink)' }}>{title}</p>\n {children && <div className=\"vi-text-body-sm\" style={{ margin: 0, maxWidth: 480, overflowWrap: 'anywhere' }}>{children}</div>}\n </div>\n );\n}\n\nfunction EmptyState() {\n return (\n <StateNote topic=\"stone\" title=\"Nothing to show yet\">\n Pass a <code style={{ fontFamily: 'var(--font-mono)' }}>visualliFile</code> or <code style={{ fontFamily: 'var(--font-mono)' }}>visualliString</code>.\n </StateNote>\n );\n}\n\nfunction LoadingState() {\n return <StateNote topic=\"teal\" title=\"Opening the map…\" role=\"status\" />;\n}\n\nfunction ErrorState({ message }: { message: string }) {\n return (\n <StateNote topic=\"berry\" title=\"This map couldn't be opened\" role=\"alert\">\n <code style={{ fontFamily: 'var(--font-mono)' }}>{message}</code>\n </StateNote>\n );\n}\n\n// ── Inline worker script ──────────────────────────────────────────────────────\n// Self-contained JSONL parser that mirrors parseVisualliFile.\n// Runs in a Web Worker when useWorker=true; no external imports needed.\n\nconst WORKER_SCRIPT = `\nself.onmessage = function(e) {\n var content = e.data;\n try {\n var lines = content.trim().split('\\\\n');\n var doc = {\n meta: null,\n layers: new Map(),\n layersByLevel: new Map(),\n rootLayer: null,\n extensions: {},\n };\n for (var i = 0; i < lines.length; i++) {\n var line = lines[i].trim();\n if (!line) continue;\n var obj;\n try { obj = JSON.parse(line); }\n catch(err) { throw new Error('Failed to parse JSON at line ' + (i+1) + ': ' + err); }\n if (!obj.type) throw new Error(\"Missing 'type' field at line \" + (i+1));\n if (obj.type === 'meta') {\n doc.meta = obj;\n } else if (obj.type === 'layer') {\n doc.layers.set(obj.id, obj);\n if (!doc.layersByLevel.has(obj.level)) doc.layersByLevel.set(obj.level, []);\n doc.layersByLevel.get(obj.level).push(obj);\n if (obj.level === 0) doc.rootLayer = obj;\n } else if (obj.type === 'extension' && typeof obj.id === 'string') {\n doc.extensions[obj.id] = Array.isArray(obj.data) ? obj.data : [];\n }\n }\n if (!doc.meta) throw new Error('Missing required meta section');\n if (!doc.rootLayer) throw new Error('Missing root layer (level 0)');\n self.postMessage({ ok: true, doc: doc });\n } catch(err) {\n self.postMessage({ ok: false, message: err.message || String(err) });\n }\n};\n`;\n\n// Lazy-create worker URL once (module-level singleton).\nlet _workerUrl: string | null = null;\nfunction getWorkerUrl(): string {\n if (!_workerUrl) {\n _workerUrl = URL.createObjectURL(new Blob([WORKER_SCRIPT], { type: 'text/javascript' }));\n }\n return _workerUrl;\n}\n\n// ── Parse hook ────────────────────────────────────────────────────────────────\n\ntype ParseState =\n | { status: 'idle' }\n | { status: 'loading' }\n | { status: 'ready'; doc: VisualliDocument }\n | { status: 'error'; message: string };\n\n/**\n * Resolves a raw string + optional File into a ParseState.\n * When useWorker=true the JSON.parse work runs in a Web Worker so the main\n * thread is never blocked, even for very large documents.\n */\nfunction useAsyncParse(\n content: string | undefined,\n useWorker: boolean,\n): ParseState {\n const [state, setState] = useState<ParseState>({ status: 'idle' });\n const workerRef = useRef<Worker | null>(null);\n\n useEffect(() => {\n if (!content) { setState({ status: 'idle' }); return; }\n\n setState({ status: 'loading' });\n let cancelled = false;\n\n if (useWorker && typeof Worker !== 'undefined') {\n // Terminate any previous worker\n workerRef.current?.terminate();\n const w = new Worker(getWorkerUrl());\n workerRef.current = w;\n\n w.onmessage = (e: MessageEvent) => {\n if (cancelled) return;\n if (e.data.ok) {\n setState({ status: 'ready', doc: e.data.doc as VisualliDocument });\n } else {\n setState({ status: 'error', message: e.data.message });\n }\n };\n w.onerror = (e: ErrorEvent) => {\n if (!cancelled) setState({ status: 'error', message: e.message });\n };\n w.postMessage(content);\n\n return () => {\n cancelled = true;\n w.terminate();\n workerRef.current = null;\n };\n }\n\n // Main-thread path: defer via microtask so React paints the loading state first\n Promise.resolve().then(() => {\n if (cancelled) return;\n try {\n const doc = parseVisualliFile(content);\n if (!cancelled) setState({ status: 'ready', doc });\n } catch (err) {\n if (!cancelled) setState({ status: 'error', message: err instanceof Error ? err.message : String(err) });\n }\n });\n return () => { cancelled = true; };\n }, [content, useWorker]);\n\n // Terminate worker on unmount\n useEffect(() => () => { workerRef.current?.terminate(); }, []);\n\n return state;\n}\n\n// ── File → string hook ────────────────────────────────────────────────────────\n\nfunction useFileText(file: File | string | undefined): { text: string | undefined; error: string | undefined; loading: boolean } {\n const [text, setText] = useState<string | undefined>(undefined);\n const [error, setError] = useState<string | undefined>(undefined);\n const [loading, setLoading] = useState(false);\n\n useEffect(() => {\n if (!file) { setText(undefined); setError(undefined); setLoading(false); return; }\n setLoading(true); setText(undefined); setError(undefined);\n let cancelled = false;\n\n // Handle string path - fetch the file\n if (typeof file === 'string') {\n fetch(file)\n .then(response => {\n if (!response.ok) throw new Error(`Failed to fetch file: ${response.statusText}`);\n return response.text();\n })\n .then(t => {\n if (!cancelled) { setText(t); setLoading(false); }\n })\n .catch((err: unknown) => {\n if (!cancelled) { setError(err instanceof Error ? err.message : String(err)); setLoading(false); }\n });\n }\n // Handle File object - read as text\n else {\n file.text().then(t => {\n if (!cancelled) { setText(t); setLoading(false); }\n }).catch((err: unknown) => {\n if (!cancelled) { setError(err instanceof Error ? err.message : String(err)); setLoading(false); }\n });\n }\n \n return () => { cancelled = true; };\n }, [file]);\n\n return { text, error, loading };\n}\n\n// ── VisualliRenderer ──────────────────────────────────────────────────────────\n\nexport default function VisualliRenderer({\n visualliString,\n visualliFile,\n theme = 'light',\n comfort,\n respectForcedColors,\n layout,\n controlsPosition,\n app,\n width = '100%',\n height = '100%',\n useWorker = true,\n chromaticImmersion = false,\n fontBaseUrl,\n loadWebFonts,\n className,\n style,\n}: VisualliRendererProps) {\n // Resolve once here so the empty / loading / error states carry the same theme attributes as the map.\n const design = useDesign({ theme, comfort, respectForcedColors });\n useState(() => { ensureDesignSystemStyles({ fontBaseUrl, loadWebFonts }); return true; });\n\n const cssWidth = typeof width === 'number' ? `${width}px` : width;\n const cssHeight = typeof height === 'number' ? `${height}px` : height;\n\n // Read File → text (no-op if not provided)\n const { text: fileText, error: fileReadError, loading: fileReading } = useFileText(visualliFile);\n\n // The raw JSONL string to parse: file takes priority over string prop\n const rawContent = fileText ?? visualliString;\n\n const parseState = useAsyncParse(rawContent, useWorker);\n\n const resolvedDoc: VisualliDocument | null = useMemo(() => {\n if (parseState.status === 'ready') return parseState.doc;\n return null;\n }, [parseState]);\n\n const wrapperStyle: React.CSSProperties = { width: cssWidth, height: cssHeight, overflow: 'hidden', ...style };\n const attrs = design.attrs;\n\n // ── Empty state ─────────────────────────────────────────────────────────────\n if (!visualliString && !visualliFile) {\n return <div className={className} {...attrs} style={wrapperStyle}><EmptyState /></div>;\n }\n\n // ── Loading state ───────────────────────────────────────────────────────────\n if (fileReading || parseState.status === 'loading') {\n return <div className={className} {...attrs} style={wrapperStyle}><LoadingState /></div>;\n }\n\n // ── Error state ─────────────────────────────────────────────────────────────\n if (fileReadError || parseState.status === 'error') {\n const msg = fileReadError ?? (parseState.status === 'error' ? parseState.message : 'Unknown error');\n return <div className={className} {...attrs} style={wrapperStyle}><ErrorState message={msg} /></div>;\n }\n\n // ── Canvas ──────────────────────────────────────────────────────────────────\n return (\n <div className={className} style={wrapperStyle}>\n <VisualliCanvas\n preParsedVisualli={resolvedDoc ?? undefined}\n theme={theme}\n comfort={comfort}\n respectForcedColors={respectForcedColors}\n layout={layout}\n controlsPosition={controlsPosition}\n app={app}\n fontBaseUrl={fontBaseUrl}\n loadWebFonts={loadWebFonts}\n chromaticImmersion={chromaticImmersion}\n style={{ width: '100%', height: '100%' }}\n />\n </div>\n );\n}\n","// ─── VisualliCanvas ───────────────────────────────────────────────────────────\n//\n// Main canvas component for rendering a VisualliDocument, drawn with the Visualli\n// design system (tokens, fonts and geometry from design-system/):\n// • Konva canvas for ideas, rings and connectors; DOM overlays for the peek,\n// term cards, depth trail and controls (the design system's own CSS)\n// • Stage-level hit detection via RBush spatial index (no Konva hit-canvas)\n// • 8 themes + comfort settings (readable type, larger text, reduced motion)\n// • Step inside / back out by idea, peek, depth trail, Escape or Backspace — zoom and pinch never navigate\n// • Layer transitions with the design system's motion (CSS-transform driven, no canvas redraws while animating)\n// • A visually hidden DOM mirror of the visible ideas for screen readers / Tab\n//\n// NOT included (read-only viewer): editing, generation, chat, sources, export.\n\nimport React, { useRef, useState, useCallback, useEffect, useMemo } from 'react';\nimport type Konva from 'konva';\nimport type { VisualliDocument, VisualliLayer, FlatNode, MindMapConnection, Comfort, ThemeInput } from '@visualli/core';\nimport {\n parseVisualliFile,\n getNodesForLayer,\n getSemanticAnchors,\n ideaColor,\n motionVars,\n nodeRadii,\n ringsFor,\n peekPosition,\n TRAIL,\n RBushSpatialIndex,\n GESTURE,\n pinchZoom,\n zoomAround,\n VIEW,\n PEEK,\n SHEET,\n} from '@visualli/core';\n\nimport { useNodeStore } from './stores/useNodeStore';\nimport { useViewportStore } from './stores/useViewportStore';\nimport { useSelectionStore } from './stores/stores';\n\nimport { useKonvaRenderer } from './hooks/useKonvaRenderer';\nimport { useLayerChoreography } from './hooks/useLayerChoreography';\nimport { RevealClock } from './design/choreography';\n\nimport KonvaStage from './components/KonvaStage';\nimport KonvaNodeLayer from './components/KonvaNodeLayer';\nimport KonvaEdgeLayer from './components/KonvaEdgeLayer';\nimport KonvaContainerLayer from './components/KonvaContainerLayer';\nimport KonvaContainerLabelLayer from './components/KonvaContainerLabelLayer';\nimport NavigationStack, { type NavStackEntry } from './components/NavigationStack';\nimport { ZoomControls, PeekCard, PeekSheet } from './components/Overlays';\nimport { A11yLayer } from './components/A11yLayer';\n\nimport { getChildLayerForNode, calculateFitView, getConnectionsForLayer, getContainersForLayer } from './utils/layerNavigation';\nimport type { ContainerGroup } from './components/KonvaContainerLayer';\nimport type { AnimatorViewport } from './hooks/useLayerChoreography';\nimport { useDesign } from './design/useDesign';\nimport { ideaMeasure } from './design/measure';\nimport { paintVars, type IdeaPaint } from './components/Overlays';\nimport { ensureDesignSystemStyles, loadCanvasFonts, type DesignSystemAssets } from './design/runtime';\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction resolveDocument(props: VisualliCanvasProps, fileText?: string): VisualliDocument | null {\n if (props.preParsedVisualli) return props.preParsedVisualli;\n const rawContent = fileText ?? props.visualliString;\n if (rawContent) {\n try { return parseVisualliFile(rawContent); } catch { return null; }\n }\n return null;\n}\n\nfunction layerLabel(doc: VisualliDocument, layer: VisualliLayer, layerId: string): string {\n if (layer.parentNodeId) {\n // Find the parent node in the parent layer to get its title\n const parentLayer = layer.parentLayerId ? doc.layers.get(layer.parentLayerId) : null;\n if (parentLayer) {\n const parentNode = parentLayer.nodes.find(n => n.id === layer.parentNodeId);\n if (parentNode) {\n return Array.isArray(parentNode.data.label)\n ? (parentNode.data.label as string[]).join(' ')\n : (parentNode.data.label || 'Untitled');\n }\n }\n }\n return layer.description ?? layerId;\n}\n\n/** Colour of the idea a layer opens from — the idea's own colour, including the sibling-order topic of an uncoloured\n * idea (the design system's TRAIL); the root layer is the map itself, TRAIL.rootTopic. */\nfunction layerPaint(doc: VisualliDocument, layer: VisualliLayer): IdeaPaint {\n const parentLayer = layer.parentLayerId ? doc.layers.get(layer.parentLayerId) : null;\n const index = parentLayer ? parentLayer.nodes.findIndex(n => n.id === layer.parentNodeId) : -1;\n if (!parentLayer || index < 0) return { topic: TRAIL.rootTopic };\n const { topic, custom } = ideaColor(parentLayer.nodes[index]!.data.color, index);\n return topic ? { topic } : { custom: custom! };\n}\n\nfunction getRootLayerId(doc: VisualliDocument): string | null {\n for (const [id, layer] of doc.layers) {\n if (!layer.parentLayerId) return id;\n }\n return doc.layers.keys().next().value ?? null;\n}\n\n// ── Props ─────────────────────────────────────────────────────────────────────\n\nexport interface VisualliCanvasProps {\n preParsedVisualli?: VisualliDocument;\n /**\n * Raw JSONL string — just pass the string data directly.\n * No preprocessing needed by user.\n */\n visualliString?: string;\n /**\n * A .visualli file — can be:\n * - File object (from file input)\n * - String path to file (e.g. '/data/file.visualli')\n * Component handles all fetching and parsing automatically.\n */\n visualliFile?: File | string;\n /**\n * Theme: one of the 8 design-system themes ('light', 'dark', 'focus-light', …), a family\n * ('focus' | 'colorsafe' | 'contrast') or 'auto' (follow the reader). Default 'light'.\n */\n theme?: ThemeInput;\n /** @deprecated use `theme`. true -> 'dark', false -> 'light'. Kept for one release. */\n isDark?: boolean;\n /** Comfort settings: readable type, larger text, reduced motion. */\n comfort?: Comfort;\n /**\n * How a layer arrives. 'gradual' (default): ideas bloom in one by one, then connectors draw\n * (design-system motion). 'instant': everything fades in together, as with reduced motion.\n */\n reveal?: 'gradual' | 'instant';\n /** Switch to the high-contrast theme under forced-colors. Default true. */\n respectForcedColors?: boolean;\n /**\n * Interaction layout. 'auto' (default) follows the reader's input: touch devices get the design\n * system's bottom-sheet peek and larger controls, pointer devices the floating peek on hover.\n * Force one with 'touch' or 'pointer'.\n */\n layout?: 'auto' | 'touch' | 'pointer';\n /**\n * The map is the page (an app such as Visualli's web app): it takes every touch gesture, so the browser never\n * zooms or scrolls the page — the design system's `.vi-map.is-app` (`touch-action: none`). Leave it off when the\n * map is embedded in a scrolling page: one finger then still scrolls the page, two fingers pinch the map.\n */\n app?: boolean;\n /**\n * Where the zoom / fit controls sit. Default 'top-right', the design system's placement (`.vi-map__ctrls`,\n * opposite the depth trail). 'bottom-right' moves them to the bottom corner for hosts that need the top edge;\n * there they rise above the touch peek sheet while it's open.\n */\n controlsPosition?: 'top-right' | 'bottom-right';\n /** Where the bundled Caveat font is served from (directory URL). Defaults to the copy in the npm package, via jsDelivr. */\n fontBaseUrl?: DesignSystemAssets['fontBaseUrl'];\n /** Set false when you load Kalam and Atkinson Hyperlegible yourself. */\n loadWebFonts?: DesignSystemAssets['loadWebFonts'];\n chromaticImmersion?: boolean;\n onNodeClick?: (node: FlatNode) => void;\n onLayerChange?: (layerId: string, layer: VisualliLayer) => void;\n onNodeHover?: (nodeId: string | null) => void;\n \n // Extension points for private features (implement in consuming app)\n renderOverlay?: (params: { isDark: boolean; theme: string; containerWidth: number; containerHeight: number }) => React.ReactNode;\n renderNodeContent?: (params: { \n summary: string; \n nodeId: string; \n nodeColor?: string;\n zoom: number;\n }) => React.ReactNode;\n navigationStackTop?: string;\n navigationStackLeft?: string;\n \n className?: string;\n style?: React.CSSProperties;\n}\n\n// ── Component ─────────────────────────────────────────────────────────────────\n\nexport default function VisualliCanvas(props: VisualliCanvasProps) {\n const { chromaticImmersion = false, onNodeClick, onLayerChange, onNodeHover, renderOverlay, renderNodeContent, navigationStackTop, navigationStackLeft, className = '', style } = props;\n // The host's hover callback, read through a ref so the stage's pointer handlers stay stable when it changes.\n const onNodeHoverRef = useRef(onNodeHover);\n onNodeHoverRef.current = onNodeHover;\n\n // Design system: resolve theme + comfort, inject its CSS once, and hold the first draw until its fonts are loaded.\n const design = useDesign({ theme: props.theme ?? (props.isDark === undefined ? 'light' : undefined), isDark: props.isDark, comfort: props.comfort, respectForcedColors: props.respectForcedColors });\n const isDark = design.isDark;\n const [fontSheet] = useState(() => ensureDesignSystemStyles({ fontBaseUrl: props.fontBaseUrl, loadWebFonts: props.loadWebFonts }));\n const [fontsReady, setFontsReady] = useState(false);\n useEffect(() => { let live = true; loadCanvasFonts(fontSheet).then(() => { if (live) setFontsReady(true); }); return () => { live = false; }; }, [fontSheet]);\n\n // Read file if provided (handles both File objects and string paths)\n const [fileText, setFileText] = useState<string | undefined>(undefined);\n useEffect(() => {\n if (!props.visualliFile) { setFileText(undefined); return; }\n let cancelled = false;\n \n // Handle string path - fetch the file\n if (typeof props.visualliFile === 'string') {\n fetch(props.visualliFile)\n .then(response => {\n if (!response.ok) throw new Error(`Failed to fetch: ${response.statusText}`);\n return response.text();\n })\n .then(t => {\n if (!cancelled) setFileText(t);\n })\n .catch(() => {\n if (!cancelled) setFileText(undefined);\n });\n }\n // Handle File object - read as text\n else {\n props.visualliFile.text().then(t => {\n if (!cancelled) setFileText(t);\n }).catch(() => {\n if (!cancelled) setFileText(undefined);\n });\n }\n \n return () => { cancelled = true; };\n }, [props.visualliFile]);\n\n const doc = useMemo(() => resolveDocument(props, fileText), [props.preParsedVisualli, props.visualliString, props.visualliFile, fileText]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // ── Navigation ────────────────────────────────────────────────────────────\n const [navStack, setNavStack] = useState<NavStackEntry[]>([]);\n const [currentLayerId, setCurrentLayerId] = useState<string | null>(null);\n const parentViewports = useRef<AnimatorViewport[]>([]);\n /** The idea being stepped into: the depth trail entry takes its colour and label from it, so they always match the idea that was clicked. */\n const stepTargetRef = useRef<{ paint: IdeaPaint; label: string } | null>(null);\n const [isTransitioning, setIsTransitioning] = useState(false);\n const isTransitioningRef = useRef(false);\n\n useEffect(() => {\n if (!doc) return;\n const rootId = getRootLayerId(doc);\n if (!rootId) return;\n const rootLayer = doc.layers.get(rootId)!;\n setCurrentLayerId(rootId);\n // The trail starts with the map's title (the design system's DepthTrail).\n setNavStack([{ layerId: rootId, layer: rootLayer, label: doc.meta?.title || 'Home', paint: { topic: TRAIL.rootTopic } }]);\n parentViewports.current = [];\n }, [doc]);\n\n // ── Active layer → FlatNodes ──────────────────────────────────────────────\n // Ideas are sized for their labels (the design system's idea.ts) with the real label face, so sizes are taken once\n // the fonts are in, and again when the face or the label scale changes (readable type, larger text).\n const sizing = useMemo(() => ({ measure: ideaMeasure(design), labelScale: design.labelScale }), [design.fontHand, design.labelScale, design.comfort.readableType, fontsReady]); // eslint-disable-line react-hooks/exhaustive-deps\n const { flatNodes, connections, containers } = useMemo(() => {\n if (!doc || !currentLayerId) return { flatNodes: [] as FlatNode[], connections: [] as MindMapConnection[], containers: [] as ContainerGroup[] };\n try {\n return {\n flatNodes: getNodesForLayer(doc, currentLayerId, sizing),\n connections: getConnectionsForLayer(doc, currentLayerId),\n containers: getContainersForLayer(doc, currentLayerId) as ContainerGroup[],\n };\n } catch { return { flatNodes: [] as FlatNode[], connections: [] as MindMapConnection[], containers: [] as ContainerGroup[] }; }\n }, [doc, currentLayerId, sizing]);\n const viewport = useViewportStore(s => ({\n centerX: s.centerX, centerY: s.centerY, zoomLevel: s.zoomLevel,\n canvasWidth: s.canvasWidth, canvasHeight: s.canvasHeight,\n }));\n const setCenter = useViewportStore(s => s.setCenter);\n const setZoom = useViewportStore(s => s.setZoom);\n\n const nodes = useNodeStore(s => s.nodes);\n const setNodes = useNodeStore(s => s.setNodes);\n const updateNodePosition = useNodeStore(s => s.updateNodePosition);\n\n const clearSel = useSelectionStore(s => s.clear);\n const select = useSelectionStore(s => s.select);\n\n // Sync nodes → store\n useEffect(() => {\n const map = new Map(flatNodes.map(n => [n.id, n]));\n setNodes(map);\n clearSel();\n }, [flatNodes, setNodes, clearSel]);\n\n // ── Choreography: a layer's arrival (ideas bloom, connectors draw) ────────\n const clock = useMemo(() => new RevealClock(), []);\n const instantReveal = design.comfort.reducedMotion || props.reveal === 'instant';\n useEffect(() => {\n if (!fontsReady || flatNodes.length === 0) return;\n clock.start(flatNodes, connections.length, instantReveal);\n // Lift the step-inside veil two frames from now, once the new layer's first frame has been painted.\n const r1 = requestAnimationFrame(() => { r2 = requestAnimationFrame(arrive); });\n let r2 = 0;\n return () => { cancelAnimationFrame(r1); cancelAnimationFrame(r2); };\n }, [flatNodes, fontsReady]); // eslint-disable-line react-hooks/exhaustive-deps\n useEffect(() => clock.subscribe((running) => {\n const el = containerRef.current;\n if (el) el.dataset.viReveal = running ? 'running' : 'idle';\n }), [clock]);\n useEffect(() => () => clock.stop(), [clock]);\n\n // ── Canvas refs ───────────────────────────────────────────────────────────\n const containerRef = useRef<HTMLDivElement | null>(null);\n const stageRef = useRef<Konva.Stage | null>(null);\n const canvasWrapperRef = useRef<HTMLDivElement>(null);\n\n // canvasSizeRef is kept in sync with the measured container size (not window).\n // Initialise to 0 — it will be updated synchronously before the first frame.\n const canvasSizeRef = useRef({ width: 0, height: 0 });\n\n // ── Node drag refs (RAF-throttled, matches visualli.ai) ───────────────────\n const dragMoveRafRef = useRef<number | null>(null);\n const dragMoveLatestRef = useRef<{ nodeId: string; x: number; y: number } | null>(null);\n const dragStartPosRef = useRef<Map<string, { x: number; y: number }>>(new Map());\n\n // ── Chromatic immersion: the colour of the idea stepped into tints the canvas at `immersion-alpha` ──\n const immersionFill = useMemo<string | null>(() => {\n if (!chromaticImmersion || !doc || !currentLayerId) return null;\n const layer = doc.layers.get(currentLayerId);\n if (!layer || layer.level === 0 || !layer.parentNodeId) return null;\n return paintVars(layerPaint(doc, layer)).fill;\n }, [chromaticImmersion, doc, currentLayerId]);\n\n // ── Spatial index (for stage-level hit detection) ─────────────────────────\n const spatialIndexRef = useRef<RBushSpatialIndex | null>(null);\n useEffect(() => {\n if (flatNodes.length === 0) { spatialIndexRef.current?.clear(); return; }\n const idx = new RBushSpatialIndex();\n idx.bulkLoad(flatNodes.map(n => {\n const { rx, ry } = nodeRadii(n);\n return { nodeId: n.id, bounds: { minX: n.x - rx, minY: n.y - ry, maxX: n.x + rx, maxY: n.y + ry } };\n }));\n spatialIndexRef.current = idx;\n return () => { spatialIndexRef.current?.clear(); };\n }, [flatNodes]);\n\n // ── Konva renderer (resize + FPS) ─────────────────────────────────────────\n const {\n handleWheel: rendererHandleWheel,\n handleMouseDown: rendererHandleMouseDown,\n handleMouseMove: rendererHandleMouseMove,\n handleMouseUp: rendererHandleMouseUp,\n cancelPan: rendererCancelPan,\n canvasWidth,\n canvasHeight,\n } = useKonvaRenderer({ containerRef, stageRef });\n\n // Keep canvasSizeRef in sync with the measured container size.\n // The fallback to containerRef.getBoundingClientRect covers the period before\n // the first ResizeObserver callback fires.\n const _cw = canvasWidth || containerRef.current?.getBoundingClientRect().width || 800;\n const _ch = canvasHeight || containerRef.current?.getBoundingClientRect().height || 600;\n canvasSizeRef.current = { width: _cw, height: _ch };\n\n // ── Individual node drag (RAF-throttled, matches visualli.ai) ────────────\n const handleDragStart = useCallback((nodeId: string) => {\n isDraggingRef.current = true;\n setIsDraggingState(true);\n setHoveredNode(null);\n const node = nodes.get(nodeId);\n if (node) dragStartPosRef.current.set(nodeId, { x: node.x, y: node.y });\n }, [nodes]);\n\n const handleDragMove = useCallback((nodeId: string, x: number, y: number) => {\n dragMoveLatestRef.current = { nodeId, x, y };\n if (dragMoveRafRef.current !== null) return;\n dragMoveRafRef.current = requestAnimationFrame(() => {\n dragMoveRafRef.current = null;\n const latest = dragMoveLatestRef.current;\n if (latest) { dragMoveLatestRef.current = null; updateNodePosition(latest.nodeId, latest.x, latest.y); }\n });\n }, [updateNodePosition]);\n\n const handleDragEnd = useCallback((nodeId: string, x: number, y: number) => {\n if (dragMoveRafRef.current !== null) { cancelAnimationFrame(dragMoveRafRef.current); dragMoveRafRef.current = null; }\n dragMoveLatestRef.current = null;\n isDraggingRef.current = false;\n setIsDraggingState(false);\n updateNodePosition(nodeId, x, y);\n // Update spatial index entry\n if (spatialIndexRef.current) {\n const node = nodes.get(nodeId);\n if (node) {\n const oldPos = dragStartPosRef.current.get(nodeId);\n if (oldPos) {\n const { rx, ry } = nodeRadii(node);\n spatialIndexRef.current.remove(nodeId, {\n minX: oldPos.x - rx, minY: oldPos.y - ry,\n maxX: oldPos.x + rx, maxY: oldPos.y + ry,\n });\n }\n const { rx, ry } = nodeRadii(node);\n spatialIndexRef.current.insert(nodeId, {\n minX: x - rx, minY: y - ry,\n maxX: x + rx, maxY: y + ry,\n });\n }\n }\n dragStartPosRef.current.delete(nodeId);\n }, [updateNodePosition, nodes]);\n // Keep a ref to the latest fitToScreen so async callbacks (onComplete) always\n // call the most current version without re-creating the animation pipeline.\n const fitToScreenRef = useRef<() => void>(() => {});\n\n const fitToScreen = useCallback(() => {\n if (flatNodes.length === 0) return;\n if (isTransitioningRef.current) return; // animation is controlling viewport\n // Use the container's measured size (not window) so the fit is always\n // relative to the renderer's actual bounding box.\n const cw = canvasSizeRef.current.width || containerRef.current?.getBoundingClientRect().width || 800;\n const ch = canvasSizeRef.current.height || containerRef.current?.getBoundingClientRect().height || 600;\n // Every layer, the root included, fits the same way (the design system's fit; never beyond VIEW.fitMax).\n const { centerX, centerY, zoomLevel } = calculateFitView(flatNodes, cw, ch, containers);\n // Zoom limits (VIEW) apply relative to the fit, as in the design system's map.\n useViewportStore.getState().setFit(zoomLevel, centerX, centerY);\n setCenter(centerX, centerY);\n setZoom(zoomLevel);\n }, [flatNodes, containers, setCenter, setZoom]);\n\n // Keep ref in sync after every render so async callbacks always use latest closure\n fitToScreenRef.current = fitToScreen;\n\n useEffect(() => { fitToScreen(); }, [currentLayerId]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Re-fit when the canvas is properly measured for the first time (the RAF in\n // useKonvaRenderer updates canvasWidth from 0 → container width asynchronously).\n const didFitAfterMeasureRef = useRef(false);\n useEffect(() => {\n if (!canvasWidth || didFitAfterMeasureRef.current) return;\n didFitAfterMeasureRef.current = true;\n fitToScreen();\n }, [canvasWidth, fitToScreen]);\n\n // ── Layer transitions ─────────────────────────────────────────────────────\n\n // Stores the target nav-back index so onSwapBack can read it\n const navBackTargetRef = useRef<number>(-1);\n\n const { stepInside: diveInto, backOut, arrive, isTransitioning: isAnimating } = useLayerChoreography({\n stageRef,\n canvasWrapperRef,\n reducedMotion: design.comfort.reducedMotion || props.reveal === 'instant',\n onSwapLayer: (childLayerId) => {\n const childLayer = doc?.layers.get(childLayerId);\n if (!childLayer || !doc) return;\n setCurrentLayerId(childLayerId);\n const target = stepTargetRef.current;\n stepTargetRef.current = null;\n setNavStack(prev => [...prev, {\n layerId: childLayerId,\n layer: childLayer,\n label: target?.label || layerLabel(doc, childLayer, childLayerId),\n paint: target?.paint ?? layerPaint(doc, childLayer),\n }]);\n onLayerChange?.(childLayerId, childLayer);\n },\n onSwapBack: () => {\n const targetIndex = navBackTargetRef.current;\n setNavStack(prev => {\n const newStack = prev.slice(0, targetIndex + 1);\n parentViewports.current = parentViewports.current.slice(0, targetIndex);\n const newLayerId = newStack[newStack.length - 1].layerId;\n setCurrentLayerId(newLayerId);\n onLayerChange?.(newLayerId, newStack[newStack.length - 1].layer);\n return newStack;\n });\n },\n onComplete: () => {\n setIsTransitioning(false);\n isTransitioningRef.current = false;\n // After every layer switch, snap to the fit view so zoom is always clean.\n requestAnimationFrame(() => { fitToScreenRef.current(); });\n },\n });\n\n const handleNavigate = useCallback((nodeId: string) => {\n if (!doc || !currentLayerId) {\n return;\n }\n if (isTransitioningRef.current || isAnimating()) {\n return;\n }\n\n const childLayer = getChildLayerForNode(doc, nodeId, currentLayerId);\n if (!childLayer) {\n return;\n }\n const childLayerId = [...doc.layers.entries()].find(([, l]) => l === childLayer)?.[0];\n if (!childLayerId) {\n return;\n }\n const childNodes = (() => { try { return getNodesForLayer(doc, childLayerId, sizing); } catch { return []; } })();\n if (childNodes.length === 0) {\n return;\n }\n\n const node = nodes.get(nodeId);\n if (!node) return;\n\n // Save the FIT viewport for this layer (not the current scroll position).\n // This ensures navigating back always returns to a clean, properly-zoomed view\n // rather than the arbitrary zoom that happened to trigger the navigation.\n const cw = canvasSizeRef.current.width || 800;\n const ch = canvasSizeRef.current.height || 600;\n const fitVp = calculateFitView(flatNodes, cw, ch, containers);\n parentViewports.current.push({ centerX: fitVp.centerX, centerY: fitVp.centerY, zoomLevel: fitVp.zoomLevel });\n\n stepTargetRef.current = { paint: { topic: node.topic, custom: node.custom }, label: node.title };\n setIsTransitioning(true);\n isTransitioningRef.current = true;\n\n diveInto(node, childLayerId, childNodes);\n }, [doc, currentLayerId, nodes, isAnimating, diveInto, sizing, flatNodes, containers]);\n\n const handleNavigateBack = useCallback((targetIndex: number) => {\n if (targetIndex >= navStack.length - 1) return;\n if (isTransitioningRef.current || isAnimating()) return;\n const savedVp = parentViewports.current[targetIndex];\n if (!savedVp) return;\n navBackTargetRef.current = targetIndex;\n setIsTransitioning(true);\n isTransitioningRef.current = true;\n backOut(savedVp);\n }, [navStack.length, isAnimating, backOut]);\n\n // ── Stage-level hit detection ─────────────────────────────────────────────\n const toWorldCoords = useCallback((stage: Konva.Stage, pointer: { x: number; y: number }) => {\n const sp = stage.position();\n const sc = stage.scaleX();\n return { worldX: (pointer.x - sp.x) / sc, worldY: (pointer.y - sp.y) / sc };\n }, []);\n\n const hitTestNode = useCallback((worldX: number, worldY: number): string | null => {\n if (!spatialIndexRef.current) return null;\n const hits = spatialIndexRef.current.query({ minX: worldX, minY: worldY, maxX: worldX, maxY: worldY });\n if (!hits.length) return null;\n let targetId: string | null = null, minDist = Infinity;\n for (const nodeId of hits) {\n const node = nodes.get(nodeId);\n if (!node) continue;\n const d = (worldX - node.x) ** 2 + (worldY - node.y) ** 2;\n if (d < minDist) { minDist = d; targetId = nodeId; }\n }\n return targetId;\n }, [nodes]);\n\n // Stage pointer interaction state\n const stageActiveNodeIdRef = useRef<string | null>(null);\n const stageDragNodeOffsetRef = useRef({ x: 0, y: 0 });\n const stageMouseDownPosRef = useRef<{ x: number; y: number } | null>(null);\n const stageDragCommittedRef = useRef(false);\n const stageLastPointerCheckRef = useRef<number>(0);\n const pointerNodeIdRef = useRef<string | null>(null);\n const isCanvasPanningRef = useRef(false);\n const isDraggingRef = useRef(false);\n\n const [pointerNodeId, setPointerNodeId] = useState<string | null>(null);\n const [pressedNodeId, setPressedNodeId] = useState<string | null>(null);\n const [isDraggingState, setIsDraggingState] = useState(false);\n\n // ── Node hover tooltip ────────────────────────────────────────────────────\n const [hoveredNode, setHoveredNode] = useState<{\n nodeId: string; summary: string; screenX: number; screenY: number;\n } | null>(null);\n\n const tooltipHoverRef = useRef(false);\n const keepTooltipOpenRef = useRef(false); // External request to keep tooltip open (e.g., from extensions)\n const clearTooltipTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const hoveredNodePosition = useMemo(() => {\n if (!hoveredNode) return null;\n const node = nodes.get(hoveredNode.nodeId);\n if (!node) return null;\n const cw = viewport.canvasWidth || canvasSizeRef.current.width;\n const ch = viewport.canvasHeight || canvasSizeRef.current.height;\n return {\n screenX: (node.x - viewport.centerX) * viewport.zoomLevel + cw / 2,\n screenY: (node.y - viewport.centerY) * viewport.zoomLevel + ch / 2,\n zoom: viewport.zoomLevel,\n };\n }, [hoveredNode, nodes, viewport]);\n\n // ── Context menu ──────────────────────────────────────────────────────────\n const [canvasContextMenu, setCanvasContextMenu] = useState<{ x: number; y: number } | null>(null);\n\n useEffect(() => {\n if (!canvasContextMenu) return;\n const close = () => setCanvasContextMenu(null);\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') close(); };\n window.addEventListener('pointerdown', close);\n window.addEventListener('keydown', onKey);\n return () => { window.removeEventListener('pointerdown', close); window.removeEventListener('keydown', onKey); };\n }, [canvasContextMenu]);\n\n const selectedNodeId = useSelectionStore(st => st.selectedId);\n const [focusedNodeId, setFocusedNodeId] = useState<string | null>(null);\n const anchors = useMemo(() => (doc ? getSemanticAnchors(doc) : []), [doc]);\n\n // ── Touch mode + pinned peek (bottom sheet) ───────────────────────────────\n // Touch browsers also fire compatibility mouse events after a tap; those are ignored so\n // they can neither reopen nor close the sheet.\n const [autoTouch, setAutoTouch] = useState<boolean>(() => typeof window !== 'undefined' && !!window.matchMedia && window.matchMedia('(hover: none)').matches);\n const touchMode = props.layout === 'touch' ? true : props.layout === 'pointer' ? false : autoTouch;\n const touchModeRef = useRef(touchMode);\n touchModeRef.current = touchMode;\n const lastTouchAtRef = useRef(0);\n const emptyTapRef = useRef<{ x: number; y: number } | null>(null);\n const [pinnedId, setPinnedId] = useState<string | null>(null);\n const [sheetExpanded, setSheetExpanded] = useState(false);\n const isEmulatedMouse = (evt: Event) => evt.type.startsWith('mouse') && performance.now() - lastTouchAtRef.current < 700;\n /** Client coordinates of a mouse or touch event. */\n const clientOf = (evt: MouseEvent | TouchEvent) => {\n const t = ('touches' in evt && (evt.touches[0] ?? evt.changedTouches[0])) || (evt as MouseEvent);\n return { x: t.clientX, y: t.clientY };\n };\n const pinnedIdRef = useRef<string | null>(null);\n pinnedIdRef.current = pinnedId;\n /** Collapsed sheet height: the design system's SHEET — a share of the map, at most SHEET.maxHeight. */\n const sheetHeight = Math.min(SHEET.maxHeight, Math.round((viewport.canvasHeight || canvasSizeRef.current.height || 600) * SHEET.heightRatio));\n\n /** Open the bottom sheet for an idea, scrolling the map so the idea stays visible above it. */\n const openSheet = (node: FlatNode) => {\n setPinnedId(node.id);\n setSheetExpanded(false);\n setHoveredNode(null);\n const vp = useViewportStore.getState();\n const ch = canvasSizeRef.current.height || vp.canvasHeight;\n const sh = Math.min(SHEET.maxHeight, Math.round(ch * SHEET.heightRatio));\n const screenY = (node.y - vp.centerY) * vp.zoomLevel + ch / 2;\n const reach = nodeRadii(node).ry * vp.zoomLevel;\n if (screenY + reach > ch - sh - 12 || screenY - reach < 0) vp.setCenter(vp.centerX, node.y + sh / (2 * vp.zoomLevel));\n };\n // Close the sheet when the layer changes.\n useEffect(() => { setPinnedId(null); }, [currentLayerId]);\n\n // ── Stage event handlers ──────────────────────────────────────────────────\n const handleStageMouseDown = useCallback((e: Konva.KonvaEventObject<MouseEvent>) => {\n if (isEmulatedMouse(e.evt)) return;\n const isTouch = e.evt.type.startsWith('touch');\n if (isTouch) lastTouchAtRef.current = performance.now();\n if (props.layout === undefined || props.layout === 'auto') setAutoTouch(isTouch);\n // Touch events carry no `button`: a touch is always a primary press.\n if (!isTouch && e.evt.button !== 0) { rendererHandleMouseDown(e); return; }\n const stage = e.target.getStage();\n if (!stage) { rendererHandleMouseDown(e); return; }\n const pointer = stage.getPointerPosition();\n if (!pointer) { rendererHandleMouseDown(e); return; }\n const { worldX, worldY } = toWorldCoords(stage, pointer);\n const nodeId = hitTestNode(worldX, worldY);\n if (nodeId) {\n const node = nodes.get(nodeId);\n if (node) {\n select(nodeId);\n stageActiveNodeIdRef.current = nodeId;\n stageDragNodeOffsetRef.current = { x: worldX - node.x, y: worldY - node.y };\n stageMouseDownPosRef.current = clientOf(e.evt);\n stageDragCommittedRef.current = false;\n setPressedNodeId(nodeId);\n setHoveredNode(null);\n return;\n }\n }\n setHoveredNode(null);\n emptyTapRef.current = clientOf(e.evt);\n isCanvasPanningRef.current = true;\n rendererHandleMouseDown(e);\n }, [hitTestNode, toWorldCoords, nodes, select, rendererHandleMouseDown, props.layout]);\n\n const handleStageMouseMove = useCallback((e: Konva.KonvaEventObject<MouseEvent>) => {\n if (isEmulatedMouse(e.evt)) return;\n const stage = e.target.getStage();\n if (!stage) { rendererHandleMouseMove(e); return; }\n const pointer = stage.getPointerPosition();\n if (!pointer) { rendererHandleMouseMove(e); return; }\n const { worldX, worldY } = toWorldCoords(stage, pointer);\n\n if (stageActiveNodeIdRef.current && stageMouseDownPosRef.current) {\n const cur = clientOf(e.evt);\n const moved = Math.hypot(cur.x - stageMouseDownPosRef.current.x, cur.y - stageMouseDownPosRef.current.y);\n if (!stageDragCommittedRef.current && moved >= 5) {\n stageDragCommittedRef.current = true;\n isDraggingRef.current = true;\n setIsDraggingState(true);\n pointerNodeIdRef.current = null;\n setPointerNodeId(null);\n handleDragStart(stageActiveNodeIdRef.current);\n }\n if (stageDragCommittedRef.current) {\n const offset = stageDragNodeOffsetRef.current;\n handleDragMove(stageActiveNodeIdRef.current, worldX - offset.x, worldY - offset.y);\n return;\n }\n return;\n }\n\n // During canvas pan — just apply the pan, skip hover detection to avoid re-renders\n if (isCanvasPanningRef.current) {\n rendererHandleMouseMove(e);\n return;\n }\n\n // Throttled hover detection (only when not panning or dragging)\n const now = performance.now();\n if (now - stageLastPointerCheckRef.current >= 50) {\n stageLastPointerCheckRef.current = now;\n const hovered = hitTestNode(worldX, worldY);\n if (hovered !== pointerNodeIdRef.current) {\n pointerNodeIdRef.current = hovered;\n setPointerNodeId(hovered);\n onNodeHoverRef.current?.(hovered);\n }\n // Cursors as the design system's: an idea is a button (pointer); the canvas keeps the default.\n stage.container().style.cursor = hovered ? 'pointer' : '';\n }\n\n rendererHandleMouseMove(e);\n }, [toWorldCoords, hitTestNode, handleDragStart, handleDragMove, rendererHandleMouseMove]);\n\n const handleStageMouseUp = useCallback((e: Konva.KonvaEventObject<MouseEvent>) => {\n if (isEmulatedMouse(e.evt)) return;\n setPressedNodeId(null);\n if (stageActiveNodeIdRef.current) {\n const nodeId = stageActiveNodeIdRef.current;\n if (stageDragCommittedRef.current) {\n // End drag — flush final world position\n const stage = e.target.getStage();\n if (stage) {\n const pointer = stage.getPointerPosition();\n if (pointer) {\n const { worldX, worldY } = toWorldCoords(stage, pointer);\n const offset = stageDragNodeOffsetRef.current;\n handleDragEnd(nodeId, worldX - offset.x, worldY - offset.y);\n }\n }\n } else {\n // Click — check if node has child layer (regardless of branchCount)\n const node = nodes.get(nodeId);\n if (node) {\n const childLayer = doc ? getChildLayerForNode(doc, nodeId, currentLayerId ?? '') : null;\n if (touchModeRef.current && childLayer && pinnedIdRef.current === nodeId) {\n // Touch: tapping the idea whose sheet is open steps inside (same as the sheet's Step inside).\n setPinnedId(null);\n handleNavigate(nodeId);\n } else if (touchModeRef.current && (node.description || childLayer)) {\n // Touch: the first tap opens the sheet; nothing flashes or navigates by itself.\n openSheet(node);\n } else if (childLayer) {\n handleNavigate(nodeId);\n }\n onNodeClick?.(node);\n }\n }\n isDraggingRef.current = false;\n setIsDraggingState(false);\n stageActiveNodeIdRef.current = null;\n stageMouseDownPosRef.current = null;\n stageDragCommittedRef.current = false;\n return;\n }\n // A tap (not a pan) on empty canvas dismisses the sheet.\n const tap = emptyTapRef.current;\n emptyTapRef.current = null;\n if (tap && pinnedIdRef.current) {\n const end = clientOf(e.evt);\n if (!Number.isFinite(end.x) || Math.hypot(end.x - tap.x, end.y - tap.y) < 6) setPinnedId(null);\n }\n isCanvasPanningRef.current = false;\n rendererHandleMouseUp(e);\n }, [toWorldCoords, handleDragEnd, nodes, handleNavigate, onNodeClick, rendererHandleMouseUp]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const handleStageContextMenu = useCallback((e: Konva.KonvaEventObject<MouseEvent>) => {\n e.evt.preventDefault();\n if (navStack.length <= 1) { setCanvasContextMenu(null); return; }\n const rect = containerRef.current?.getBoundingClientRect();\n const localX = rect ? e.evt.clientX - rect.left : e.evt.clientX;\n const localY = rect ? e.evt.clientY - rect.top : e.evt.clientY;\n setCanvasContextMenu({ x: localX, y: localY });\n }, [navStack.length]);\n\n // ── Pinch to zoom (the design system's GESTURE, geometry/interaction.ts) ─────\n // Two touch pointers zoom the contents around the point between them (pinchZoom / zoomAround, within VIEW's\n // limits) and pan as they move together. Only the Konva world moves — the trail, controls, peek and sheet are\n // DOM and never scale. A pinch never navigates, and never ends as a tap, a pan or an idea drag.\n const touchPointsRef = useRef(new Map<number, { x: number; y: number }>());\n const pinchRef = useRef<{ d0: number; m0: { x: number; y: number }; z0: number; c0: { x: number; y: number } } | null>(null);\n const pinchEndedAtRef = useRef(-Infinity);\n const [pinching, setPinching] = useState(false);\n const localOf = (e: React.PointerEvent) => { const r = containerRef.current!.getBoundingClientRect(); return { x: e.clientX - r.left, y: e.clientY - r.top }; };\n const onPinchDown = (e: React.PointerEvent) => {\n if (!GESTURE.pinchZoom || !GESTURE.pointers.includes(e.pointerType)) return;\n touchPointsRef.current.set(e.pointerId, localOf(e));\n if (touchPointsRef.current.size !== 2 || isTransitioningRef.current || isAnimating()) return;\n const [a, b] = [...touchPointsRef.current.values()];\n const vp = useViewportStore.getState();\n pinchRef.current = { d0: Math.hypot(a.x - b.x, a.y - b.y), m0: { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 }, z0: vp.zoomLevel, c0: { x: vp.centerX, y: vp.centerY } };\n // The first finger's press becomes part of the pinch: no tap, pan or drag comes of it.\n rendererCancelPan();\n isCanvasPanningRef.current = false;\n emptyTapRef.current = null;\n stageActiveNodeIdRef.current = null;\n stageDragCommittedRef.current = false;\n isDraggingRef.current = false;\n setPressedNodeId(null);\n setPinching(true);\n };\n const onPinchMove = (e: React.PointerEvent) => {\n if (!touchPointsRef.current.has(e.pointerId)) return;\n touchPointsRef.current.set(e.pointerId, localOf(e));\n const p = pinchRef.current;\n if (!p || touchPointsRef.current.size < 2) return;\n const [a, b] = [...touchPointsRef.current.values()];\n const fit = useViewportStore.getState().fitScale;\n const z = pinchZoom(p.z0 / fit, p.d0, Math.hypot(a.x - b.x, a.y - b.y)) * fit; // VIEW's limits relative to the fit\n const m = { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };\n const cw = canvasSizeRef.current.width || containerRef.current?.clientWidth || 800;\n const ch = canvasSizeRef.current.height || containerRef.current?.clientHeight || 600;\n // screen = (world − centre) × zoom + size / 2, i.e. translation t = size / 2 − centre × zoom\n const t = zoomAround({ x: cw / 2 - p.c0.x * p.z0, y: ch / 2 - p.c0.y * p.z0 }, p.z0, z, p.m0, GESTURE.twoFingerPan ? m : p.m0);\n setZoom(z);\n setCenter((cw / 2 - t.x) / z, (ch / 2 - t.y) / z);\n };\n const onPinchUp = (e: React.PointerEvent) => {\n if (!touchPointsRef.current.delete(e.pointerId)) return;\n if (pinchRef.current && touchPointsRef.current.size < 2) {\n pinchRef.current = null;\n pinchEndedAtRef.current = performance.now();\n setPinching(false);\n }\n };\n /** True while two fingers pinch, and for a moment after: the lifting fingers are not a tap. */\n const inPinch = () => pinchRef.current !== null || touchPointsRef.current.size > 1 || performance.now() - pinchEndedAtRef.current < 300;\n\n // Touch passthrough (one finger); a pinch owns the touches while it lasts.\n const handleStageTouchStart = useCallback((e: Konva.KonvaEventObject<TouchEvent>) => {\n if (inPinch() || e.evt.touches.length > 1) return;\n handleStageMouseDown(e as unknown as Konva.KonvaEventObject<MouseEvent>);\n }, [handleStageMouseDown]);\n const handleStageTouchMove = useCallback((e: Konva.KonvaEventObject<TouchEvent>) => {\n if (inPinch() || e.evt.touches.length > 1) return;\n handleStageMouseMove(e as unknown as Konva.KonvaEventObject<MouseEvent>);\n }, [handleStageMouseMove]);\n const handleStageTouchEnd = useCallback((e: Konva.KonvaEventObject<TouchEvent>) => {\n if (inPinch()) { isCanvasPanningRef.current = false; return; }\n handleStageMouseUp(e as unknown as Konva.KonvaEventObject<MouseEvent>);\n }, [handleStageMouseUp]);\n\n // Wheel / trackpad: zoom within VIEW's limits. It never navigates — stepping inside and backing out are\n // the design system's explicit actions (the idea, its peek, the depth trail, Escape / Backspace).\n const handleWheel = useCallback((e: Konva.KonvaEventObject<WheelEvent>) => { rendererHandleWheel(e); }, [rendererHandleWheel]);\n\n // Canvas mouse move for description tooltip\n const lastHoverCheckRef = useRef(0);\n const handleCanvasMouseMove = useCallback((e: React.MouseEvent<HTMLDivElement>) => {\n if (touchModeRef.current || isEmulatedMouse(e.nativeEvent)) return; // no hover peek on touch\n if (!containerRef.current || isDraggingRef.current || isCanvasPanningRef.current) {\n setHoveredNode(null);\n return;\n }\n const now = Date.now();\n if (now - lastHoverCheckRef.current < 50) return;\n lastHoverCheckRef.current = now;\n\n // Check if mouse is over a tooltip - if so, don't change hovered node\n const target = e.target as HTMLElement;\n const isOverTooltip = target.closest('[data-node-tooltip=\"true\"]') || target.closest('[data-semantic-tooltip=\"true\"]');\n \n // If tooltip is open and we're hovering it or keeping it open, don't detect new nodes\n if (tooltipHoverRef.current || keepTooltipOpenRef.current || isOverTooltip) {\n return;\n }\n\n const cw = viewport.canvasWidth || canvasSizeRef.current.width;\n const ch = viewport.canvasHeight || canvasSizeRef.current.height;\n // e.clientX is viewport-relative; subtract the container's left/top offset\n // so world-coordinate conversion is correct when the renderer isn't full-screen.\n const rect = containerRef.current?.getBoundingClientRect();\n const localX = rect ? e.clientX - rect.left : e.clientX;\n const localY = rect ? e.clientY - rect.top : e.clientY;\n const worldX = (localX - cw / 2) / viewport.zoomLevel + viewport.centerX;\n const worldY = (localY - ch / 2) / viewport.zoomLevel + viewport.centerY;\n\n // Use RBush spatial index for O(log n) hit detection\n let found = false;\n if (spatialIndexRef.current) {\n const hits = spatialIndexRef.current.query({ minX: worldX, minY: worldY, maxX: worldX, maxY: worldY });\n for (const nodeId of hits) {\n const node = nodes.get(nodeId);\n if (node?.description) {\n setHoveredNode({ nodeId: node.id, summary: node.description, screenX: e.clientX, screenY: e.clientY });\n found = true;\n break;\n }\n }\n }\n if (!found) {\n if (clearTooltipTimerRef.current) clearTimeout(clearTooltipTimerRef.current);\n clearTooltipTimerRef.current = setTimeout(() => {\n if (!tooltipHoverRef.current && !keepTooltipOpenRef.current) setHoveredNode(null);\n }, PEEK.hoverClose); // the design system's peek grace (geometry/interaction.ts)\n } else {\n if (clearTooltipTimerRef.current) { clearTimeout(clearTooltipTimerRef.current); clearTooltipTimerRef.current = null; }\n }\n }, [nodes, viewport, spatialIndexRef]);\n\n // Listen for external requests to keep tooltip open (e.g., from extensions)\n useEffect(() => {\n const handleKeepTooltipOpen = (event: CustomEvent) => {\n keepTooltipOpenRef.current = event.detail.keep;\n };\n \n // A custom event: its listener takes a CustomEvent, so it is cast to the DOM's EventListener.\n window.addEventListener('keepNodeTooltipOpen', handleKeepTooltipOpen as EventListener);\n \n return () => {\n window.removeEventListener('keepNodeTooltipOpen', handleKeepTooltipOpen as EventListener);\n };\n }, []);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n if (clearTooltipTimerRef.current) clearTimeout(clearTooltipTimerRef.current);\n spatialIndexRef.current?.clear();\n if (dragMoveRafRef.current !== null) cancelAnimationFrame(dragMoveRafRef.current);\n };\n }, []);\n\n // ── Activate an idea (click, or Enter/Space on its accessible button) ───────\n const activateNode = useCallback((node: FlatNode) => {\n const childLayer = doc ? getChildLayerForNode(doc, node.id, currentLayerId ?? '') : null;\n if (touchModeRef.current && childLayer && pinnedIdRef.current === node.id) { setPinnedId(null); handleNavigate(node.id); }\n else if (touchModeRef.current && (node.description || childLayer)) openSheet(node);\n else if (childLayer) handleNavigate(node.id);\n onNodeClick?.(node);\n }, [doc, currentLayerId, handleNavigate, onNodeClick]);\n\n const stepInside = useCallback((nodeId: string) => { setHoveredNode(null); handleNavigate(nodeId); }, [handleNavigate]);\n\n // The peek can unmount while the pointer is on it (Step inside, layer change): no mouseleave\n // fires then, so clear the \"pointer is on the peek\" flag whenever it closes.\n useEffect(() => { if (!hoveredNode) tooltipHoverRef.current = false; }, [hoveredNode]);\n\n // Keyboard, as the design system's canvas language: Escape or Backspace steps back out (Escape first closes a\n // pinned peek); ⌘ / Ctrl + + / − / 0 zoom in, zoom out and fit (by VIEW.zoomStep, within VIEW's limits).\n const handleKeyDown = useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {\n if ((e.target as HTMLElement).closest('input, textarea, [contenteditable=\"true\"]')) return;\n const cmd = e.metaKey || e.ctrlKey;\n if (cmd && !e.altKey) {\n if (e.key === '+' || e.key === '=') { e.preventDefault(); setZoom(viewport.zoomLevel * VIEW.zoomStep); }\n else if (e.key === '-' || e.key === '_') { e.preventDefault(); setZoom(viewport.zoomLevel / VIEW.zoomStep); }\n else if (e.key === '0') { e.preventDefault(); fitToScreen(); }\n return;\n }\n if (e.altKey || e.shiftKey) return;\n if (e.key === 'Escape' && pinnedIdRef.current) { e.preventDefault(); setPinnedId(null); }\n else if ((e.key === 'Escape' || e.key === 'Backspace') && navStack.length > 1) { e.preventDefault(); handleNavigateBack(navStack.length - 2); }\n }, [navStack.length, handleNavigateBack, setZoom, viewport.zoomLevel, fitToScreen]);\n\n // ── Render ────────────────────────────────────────────────────────────────\n if (!doc) {\n return (\n <div className={`vi-map ${className}`} {...design.attrs} style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', ...style }}>\n <span className=\"vi-text-body-sm\" style={{ color: 'var(--ink-muted)' }}>No document</span>\n </div>\n );\n }\n\n const hasBackOption = navStack.length > 1;\n const currentLayerTitle = navStack[navStack.length - 1]?.label ?? '';\n const peekNode = hoveredNode ? nodes.get(hoveredNode.nodeId) : undefined;\n const pinnedNode = pinnedId ? nodes.get(pinnedId) : undefined;\n const pinnedHasChild = !!(pinnedNode && getChildLayerForNode(doc, pinnedNode.id, currentLayerId ?? ''));\n const compact = (viewport.canvasWidth || canvasSizeRef.current.width || 1024) < 560;\n const medium = !compact && (viewport.canvasWidth || canvasSizeRef.current.width || 1024) < 900;\n const peekHasChild = !!(peekNode && doc && getChildLayerForNode(doc, peekNode.id, currentLayerId ?? ''));\n\n return (\n <div\n ref={containerRef}\n className={`vi-map${touchMode ? ' is-touch' : ''}${compact ? ' is-compact' : ''}${medium ? ' is-medium' : ''}${pinching ? ' is-pinching' : ''}${props.app ? ' is-app' : ''} ${className}`}\n {...design.attrs}\n data-reveal={instantReveal ? 'instant' : undefined}\n role=\"group\"\n aria-label={`${doc.meta?.title ?? 'Map'}${currentLayerTitle ? `, ${currentLayerTitle}` : ''}`}\n onKeyDown={handleKeyDown}\n // Focusable by pointer so Esc / + / - / 0 work after clicking the map (Tab order is the mirrored ideas).\n tabIndex={-1}\n onPointerDownCapture={(e) => { onPinchDown(e); if (!(e.target as HTMLElement).closest('button, a, input')) containerRef.current?.focus({ preventScroll: true }); }}\n onPointerMoveCapture={onPinchMove}\n onPointerUpCapture={onPinchUp}\n onPointerCancelCapture={onPinchUp}\n style={{ position: 'relative', overflow: 'hidden', userSelect: 'none', width: '100%', height: '100%', outline: 'none', ...(motionVars() as React.CSSProperties), ...style }}\n onMouseMove={handleCanvasMouseMove}\n onMouseLeave={() => {\n // Only close the peek on mouse leave if not keeping it open\n if (!tooltipHoverRef.current && !keepTooltipOpenRef.current) {\n setHoveredNode(null);\n }\n }}\n >\n {/* Chromatic immersion tint */}\n <div className=\"vi-map__immersion\" style={{ background: immersionFill ?? 'transparent' }} aria-hidden=\"true\" />\n\n {/* Konva canvas — opacity driven imperatively during transitions. Held back until the fonts are ready. */}\n <div ref={canvasWrapperRef} style={{ position: 'relative', zIndex: 1, pointerEvents: 'auto' }}>\n {fontsReady && (\n <KonvaStage\n ref={stageRef}\n onWheel={handleWheel}\n onMouseDown={handleStageMouseDown}\n onMouseMove={handleStageMouseMove}\n onMouseUp={handleStageMouseUp}\n onContextMenu={handleStageContextMenu}\n onTouchStart={handleStageTouchStart}\n onTouchMove={handleStageTouchMove}\n onTouchEnd={handleStageTouchEnd}\n >\n <KonvaContainerLayer nodes={flatNodes} containers={containers} connections={connections} design={design} />\n <KonvaEdgeLayer nodes={flatNodes} connections={connections} design={design} isDragging={isDraggingState} clock={clock} />\n <KonvaNodeLayer\n design={design}\n clock={clock}\n isTransitioning={isTransitioning}\n isDragging={isDraggingState}\n hoveredNodeId={pointerNodeId}\n pressedNodeId={pressedNodeId}\n selectedNodeId={selectedNodeId}\n focusedNodeId={focusedNodeId}\n touch={touchMode}\n peekedNodeId={touchMode ? pinnedId : null}\n />\n {/* Container names above connectors and ideas, so nothing runs over them. */}\n <KonvaContainerLabelLayer containers={containers} connections={connections} design={design} />\n </KonvaStage>\n )}\n </div>\n\n {/* Screen-reader / keyboard mirror of the visible ideas */}\n <A11yLayer\n nodes={flatNodes}\n label={`Ideas in ${currentLayerTitle || 'this map'}`}\n hasChildLayer={(id) => !!getChildLayerForNode(doc, id, currentLayerId ?? '')}\n onActivate={activateNode}\n onFocusNode={setFocusedNodeId}\n announcement={hasBackOption ? `Now inside ${currentLayerTitle}` : undefined}\n />\n\n {/* Context menu (right-click to go back) */}\n {canvasContextMenu && hasBackOption && (\n <div\n role=\"menu\"\n aria-label=\"Canvas options\"\n style={{\n position: 'absolute',\n zIndex: 'var(--z-menu)' as unknown as number,\n pointerEvents: 'auto',\n left: `${Math.min(canvasContextMenu.x, Math.max(8, (canvasSizeRef.current.width || 800) - 152))}px`,\n top: `${Math.min(canvasContextMenu.y, Math.max(8, (canvasSizeRef.current.height || 600) - 72))}px`,\n }}\n onContextMenu={e => e.preventDefault()}\n onPointerDown={e => e.stopPropagation()}\n >\n <button\n type=\"button\"\n role=\"menuitem\"\n className=\"vi-iconbtn vi-iconbtn--surface\"\n style={{ width: 'auto', padding: '6px var(--space-4)', boxShadow: 'var(--shadow-pop)' }}\n onClick={() => { setCanvasContextMenu(null); handleNavigateBack(navStack.length - 2); }}\n >\n Back\n </button>\n </div>\n )}\n\n {/* Depth trail (top-left) */}\n <NavigationStack stack={navStack} onNavigateBack={handleNavigateBack} top={navigationStackTop} left={navigationStackLeft} />\n\n {/* Canvas controls: the design system's placement (top-right); 'bottom-right' only on request */}\n <div\n className=\"vi-map__ctrls\"\n style={props.controlsPosition === 'bottom-right'\n ? { top: 'auto', bottom: pinnedNode && touchMode ? `calc(var(--space-4) + ${sheetHeight}px)` : 'var(--space-4)' }\n : undefined}\n >\n <ZoomControls onFit={fitToScreen} touch={touchMode} />\n </div>\n\n {/* Custom overlay from the consuming app */}\n {renderOverlay?.({ isDark, theme: design.theme, containerWidth: canvasSizeRef.current.width || 0, containerHeight: canvasSizeRef.current.height || 0 })}\n\n {/* Touch: the peek is the design system's bottom sheet, pinned until dismissed */}\n {touchMode && pinnedNode && (\n <PeekSheet\n node={pinnedNode}\n anchors={anchors}\n height={sheetHeight}\n expanded={sheetExpanded}\n onToggleExpanded={() => setSheetExpanded((v) => !v)}\n onClose={() => setPinnedId(null)}\n onStepInside={pinnedHasChild ? () => { setPinnedId(null); handleNavigate(pinnedNode.id); } : undefined}\n renderContent={renderNodeContent ? (summary) => renderNodeContent({ summary, nodeId: pinnedNode.id, nodeColor: pinnedNode.color, zoom: viewport.zoomLevel }) : undefined}\n />\n )}\n\n {/* Pointer: the peek floats over the hovered idea — the design system's card */}\n {!touchMode && hoveredNode && hoveredNodePosition && peekNode && (() => {\n // Beside the idea — right of it if it fits, else left — level with it (the design system's peekPosition).\n const rings = ringsFor(peekNode.branchCount);\n const half = nodeRadii(peekNode).rx * (rings.length ? rings[rings.length - 1]!.scale : 1) * hoveredNodePosition.zoom;\n const at = peekPosition({ x: hoveredNodePosition.screenX, y: hoveredNodePosition.screenY, half }, { w: canvasSizeRef.current.width || 800, h: canvasSizeRef.current.height || 600 });\n return (\n <div\n className=\"vi-map__fact\"\n style={{ left: at.left, top: at.top, pointerEvents: 'auto', zIndex: 'var(--z-card)' as unknown as number }}\n onMouseEnter={() => { tooltipHoverRef.current = true; if (clearTooltipTimerRef.current) { clearTimeout(clearTooltipTimerRef.current); clearTooltipTimerRef.current = null; } }}\n onMouseLeave={() => {\n tooltipHoverRef.current = false;\n // Delay clearing to allow external extensions to request keeping the peek open\n if (clearTooltipTimerRef.current) clearTimeout(clearTooltipTimerRef.current);\n clearTooltipTimerRef.current = setTimeout(() => {\n if (!keepTooltipOpenRef.current) setHoveredNode(null);\n }, PEEK.hoverClose);\n }}\n >\n <PeekCard\n node={peekNode}\n anchors={anchors}\n onStepInside={peekHasChild ? () => stepInside(peekNode.id) : undefined}\n renderContent={renderNodeContent ? (summary) => renderNodeContent({ summary, nodeId: peekNode.id, nodeColor: peekNode.color, zoom: viewport.zoomLevel }) : undefined}\n />\n </div>\n );\n })()}\n </div>\n );\n}\n","// ─── Node Store ───────────────────────────────────────────────────────────────\n\nimport { create } from 'zustand';\nimport type { FlatNode, NodeMap } from '@visualli/core';\n\nexport interface INodeStore {\n nodes: NodeMap;\n childrenIndex: Map<string | null, Set<string>>;\n\n setNodes: (nodes: NodeMap) => void;\n updateNode: (nodeId: string, updates: Partial<FlatNode>) => void;\n updateNodePosition: (nodeId: string, x: number, y: number) => void;\n addNode: (node: FlatNode) => void;\n removeNode: (nodeId: string) => void;\n setNodeExpanded: (nodeId: string, expanded: boolean) => void;\n\n getNode: (nodeId: string) => FlatNode | undefined;\n getChildren: (parentId: string | null) => FlatNode[];\n getChildrenIds: (parentId: string | null) => Set<string>;\n getAllNodes: () => FlatNode[];\n}\n\nfunction buildChildrenIndex(nodes: NodeMap): Map<string | null, Set<string>> {\n const index = new Map<string | null, Set<string>>();\n for (const node of nodes.values()) {\n const pid = node.parentId ?? null;\n if (!index.has(pid)) index.set(pid, new Set());\n index.get(pid)!.add(node.id);\n }\n return index;\n}\n\nexport const useNodeStore = create<INodeStore>((set, get) => ({\n nodes: new Map(),\n childrenIndex: new Map(),\n\n setNodes: (nodes) =>\n set({ nodes, childrenIndex: buildChildrenIndex(nodes) }),\n\n updateNode: (nodeId, updates) =>\n set((s) => {\n const node = s.nodes.get(nodeId);\n if (!node) return s;\n const next = new Map(s.nodes);\n next.set(nodeId, { ...node, ...updates, updatedAt: new Date() });\n return { nodes: next };\n }),\n\n updateNodePosition: (nodeId, x, y) =>\n set((s) => {\n const node = s.nodes.get(nodeId);\n if (!node || (node.x === x && node.y === y)) return s;\n const next = new Map(s.nodes);\n next.set(nodeId, { ...node, x, y });\n return { nodes: next };\n }),\n\n addNode: (node) =>\n set((s) => {\n const next = new Map(s.nodes);\n next.set(node.id, node);\n const idx = new Map(s.childrenIndex);\n const pid = node.parentId ?? null;\n if (!idx.has(pid)) idx.set(pid, new Set());\n idx.get(pid)!.add(node.id);\n return { nodes: next, childrenIndex: idx };\n }),\n\n removeNode: (nodeId) =>\n set((s) => {\n const node = s.nodes.get(nodeId);\n if (!node) return s;\n const next = new Map(s.nodes);\n next.delete(nodeId);\n const idx = new Map(s.childrenIndex);\n const pid = node.parentId ?? null;\n if (idx.has(pid)) {\n const set = new Set(idx.get(pid)!);\n set.delete(nodeId);\n if (set.size === 0) idx.delete(pid); else idx.set(pid, set);\n }\n return { nodes: next, childrenIndex: idx };\n }),\n\n setNodeExpanded: (nodeId, expanded) =>\n set((s) => {\n const node = s.nodes.get(nodeId);\n if (!node) return s;\n const next = new Map(s.nodes);\n next.set(nodeId, { ...node, isExpanded: expanded, updatedAt: new Date() });\n return { nodes: next };\n }),\n\n getNode: (nodeId) => get().nodes.get(nodeId),\n getChildren: (pid) => {\n const { nodes, childrenIndex } = get();\n return Array.from(childrenIndex.get(pid) ?? []).map(id => nodes.get(id)!).filter(Boolean);\n },\n getChildrenIds: (pid) => get().childrenIndex.get(pid) ?? new Set(),\n getAllNodes: () => Array.from(get().nodes.values()),\n}));\n","// ─── Viewport Store ───────────────────────────────────────────────────────────\n\nimport { create } from 'zustand';\nimport type { ViewportState } from '@visualli/core';\nimport {\n panViewport,\n zoomViewport,\n setViewportCenter,\n recalculateViewportBounds,\n clampZoom,\n DEFAULT_CANVAS_WIDTH,\n DEFAULT_CANVAS_HEIGHT,\n worldToScreen,\n screenToWorld,\n ZOOM_DEFAULT,\n} from '@visualli/core';\n\nexport interface IViewportStore extends ViewportState {\n canvasWidth: number;\n canvasHeight: number;\n /** The layer's fit to view (scale and centre): zoom is shown and limited (VIEW) relative to it, as in the design system. */\n fitScale: number;\n fitCenterX: number;\n fitCenterY: number;\n\n pan: (deltaX: number, deltaY: number) => void;\n zoom: (delta: number, pivotX?: number, pivotY?: number) => void;\n setCenter: (x: number, y: number) => void;\n setZoom: (level: number) => void;\n setFit: (scale: number, centerX: number, centerY: number) => void;\n updateCanvasSize: (width: number, height: number) => void;\n\n getVisibleBounds: () => ViewportState['visibleBounds'];\n worldToScreen: (x: number, y: number) => { x: number; y: number };\n screenToWorld: (x: number, y: number) => { x: number; y: number };\n}\n\nfunction makeInitial(w: number, h: number): ViewportState {\n const vp: ViewportState = {\n centerX: 0, centerY: 0,\n zoomLevel: ZOOM_DEFAULT,\n rotation: 0,\n visibleBounds: { minX: 0, minY: 0, maxX: 0, maxY: 0 },\n };\n return recalculateViewportBounds(vp, w, h);\n}\n\nconst getVP = (s: IViewportStore): ViewportState => ({\n centerX: s.centerX, centerY: s.centerY,\n zoomLevel: s.zoomLevel, rotation: s.rotation,\n visibleBounds: s.visibleBounds,\n});\n\nexport const useViewportStore = create<IViewportStore>((set, get) => {\n const init = makeInitial(DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT);\n return {\n ...init,\n canvasWidth: DEFAULT_CANVAS_WIDTH,\n canvasHeight: DEFAULT_CANVAS_HEIGHT,\n fitScale: 1,\n fitCenterX: 0,\n fitCenterY: 0,\n\n pan: (dx, dy) => set((s) => {\n const updated = recalculateViewportBounds(panViewport(dx, dy, getVP(s)), s.canvasWidth, s.canvasHeight);\n return { centerX: updated.centerX, centerY: updated.centerY, visibleBounds: updated.visibleBounds };\n }),\n\n zoom: (delta, pivotX, pivotY) => set((s) => {\n const updated = recalculateViewportBounds(\n zoomViewport(delta, getVP(s), pivotX, pivotY, s.canvasWidth, s.canvasHeight, s.fitScale),\n s.canvasWidth, s.canvasHeight,\n );\n return { centerX: updated.centerX, centerY: updated.centerY, zoomLevel: updated.zoomLevel, visibleBounds: updated.visibleBounds };\n }),\n\n setCenter: (x, y) => set((s) => {\n const updated = recalculateViewportBounds(setViewportCenter(x, y, getVP(s)), s.canvasWidth, s.canvasHeight);\n return { centerX: updated.centerX, centerY: updated.centerY, visibleBounds: updated.visibleBounds };\n }),\n\n setZoom: (level) => set((s) => {\n const clamped = clampZoom(level, s.fitScale);\n const updated = recalculateViewportBounds({ ...getVP(s), zoomLevel: clamped }, s.canvasWidth, s.canvasHeight);\n return { zoomLevel: updated.zoomLevel, visibleBounds: updated.visibleBounds };\n }),\n\n setFit: (scale, centerX, centerY) => set({ fitScale: scale > 0 ? scale : 1, fitCenterX: centerX, fitCenterY: centerY }),\n\n updateCanvasSize: (w, h) => set((s) => {\n const updated = recalculateViewportBounds(getVP(s), w, h);\n return { canvasWidth: w, canvasHeight: h, visibleBounds: updated.visibleBounds };\n }),\n\n getVisibleBounds: () => get().visibleBounds,\n worldToScreen: (x, y) => {\n const s = get();\n return worldToScreen(x, y, getVP(s), s.canvasWidth, s.canvasHeight);\n },\n screenToWorld: (x, y) => {\n const s = get();\n return screenToWorld(x, y, getVP(s), s.canvasWidth, s.canvasHeight);\n },\n };\n});\n","// ─── Selection Store ──────────────────────────────────────────────────────────\n\nimport { create } from 'zustand';\nimport { selectionStore, renderConfigStore } from '@visualli/core';\nimport type { ISelectionStore, IRenderConfigStore } from '@visualli/core';\n\nexport const useSelectionStore = create<ISelectionStore>((set) => {\n selectionStore.subscribe((state) => set(state));\n return selectionStore.getState();\n});\n\n// ─── Render Config Store ──────────────────────────────────────────────────────\n\nexport const useRenderConfigStore = create<IRenderConfigStore>((set) => {\n renderConfigStore.subscribe((state) => set(state));\n return renderConfigStore.getState();\n});\n","// ─── useKonvaRenderer ─────────────────────────────────────────────────────────\n//\n// Manages Konva rendering lifecycle: resize, pan, zoom, and FPS monitoring.\n// Returns Konva-level event handlers to be wired onto KonvaStage.\n//\n// Design matches visualli.ai's useKonvaRenderer:\n// - handleWheel / handleMouseDown / handleMouseMove / handleMouseUp are\n// Konva.KonvaEventObject handlers (not DOM-level)\n// - Pan is applied directly to the stage during drag for 60 fps, flushed to\n// Zustand store on mouseUp (no per-frame state updates)\n// - Zoom targets the cursor position (same math as visualli.ai)\n\nimport { useEffect, useCallback, useRef, useState } from 'react';\nimport type Konva from 'konva';\nimport { useViewportStore } from '../stores/useViewportStore';\nimport { useRenderConfigStore } from '../stores/stores';\n\nexport interface UseKonvaRendererOptions {\n containerRef: React.RefObject<HTMLDivElement | null>;\n stageRef?: React.RefObject<Konva.Stage | null>;\n enabled?: boolean;\n}\n\nexport interface UseKonvaRendererReturn {\n handleWheel: (e: Konva.KonvaEventObject<WheelEvent>) => void;\n handleMouseDown:(e: Konva.KonvaEventObject<MouseEvent>) => void;\n handleMouseMove:(e: Konva.KonvaEventObject<MouseEvent>) => void;\n handleMouseUp: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n /** End a one-finger / mouse pan now (e.g. a second finger turns it into a pinch), keeping how far it moved. */\n cancelPan: () => void;\n canvasWidth: number;\n canvasHeight: number;\n}\n\nexport function useKonvaRenderer({\n containerRef,\n enabled = true,\n}: UseKonvaRendererOptions): UseKonvaRendererReturn {\n const pan = useViewportStore(s => s.pan);\n const zoom = useViewportStore(s => s.zoom);\n const updateCanvasSize = useViewportStore(s => s.updateCanvasSize);\n const autoAdjust = useRenderConfigStore(s => s.autoAdjustQuality);\n\n const [canvasWidth, setCanvasWidth] = useState(0);\n const [canvasHeight, setCanvasHeight] = useState(0);\n const cachedSizeRef = useRef({ width: 0, height: 0 });\n\n const isPanningRef = useRef(false);\n const lastPanPointRef = useRef({ x: 0, y: 0 });\n const panAccumRef = useRef({ x: 0, y: 0 });\n\n // ── FPS monitor ──────────────────────────────────────────────────────────────\n const fpsRef = useRef({ frames: 0, last: performance.now() });\n const fpsRafId = useRef<number | null>(null);\n\n useEffect(() => {\n if (!enabled) return;\n const tick = (now: number): void => {\n fpsRef.current.frames++;\n if (now - fpsRef.current.last >= 2000) {\n const fps = (fpsRef.current.frames / ((now - fpsRef.current.last) / 1000)) | 0;\n autoAdjust(fps);\n fpsRef.current = { frames: 0, last: now };\n }\n fpsRafId.current = requestAnimationFrame(tick);\n };\n fpsRafId.current = requestAnimationFrame(tick);\n return () => { if (fpsRafId.current !== null) cancelAnimationFrame(fpsRafId.current); };\n }, [enabled, autoAdjust]);\n\n // ── Resize ────────────────────────────────────────────────────────────────────\n // Observes the container element (not window) so the canvas always fills\n // its parent, regardless of how the renderer is sized by the consuming app.\n useEffect(() => {\n if (!enabled) return;\n\n let rafId: number | null = null;\n\n const measure = () => {\n const el = containerRef.current;\n const w = el ? Math.round(el.getBoundingClientRect().width) : 800;\n const h = el ? Math.round(el.getBoundingClientRect().height) : 600;\n return { w, h };\n };\n\n const updateSize = () => {\n if (rafId) cancelAnimationFrame(rafId);\n rafId = requestAnimationFrame(() => {\n rafId = null;\n const { w, h } = measure();\n if (w > 0 && h > 0 &&\n (cachedSizeRef.current.width !== w || cachedSizeRef.current.height !== h)) {\n cachedSizeRef.current = { width: w, height: h };\n setCanvasWidth(w);\n setCanvasHeight(h);\n updateCanvasSize(w, h);\n }\n });\n };\n\n // Initial measurement\n updateSize();\n\n // ResizeObserver tracks the container itself (handles % / flex / grid sizing)\n let ro: ResizeObserver | null = null;\n if (typeof ResizeObserver !== 'undefined' && containerRef.current) {\n ro = new ResizeObserver(updateSize);\n ro.observe(containerRef.current);\n } else {\n // Fallback: window resize only\n window.addEventListener('resize', updateSize);\n }\n\n return () => {\n if (ro) ro.disconnect(); else window.removeEventListener('resize', updateSize);\n if (rafId) cancelAnimationFrame(rafId);\n };\n }, [enabled, containerRef, updateCanvasSize]);\n\n // ── Wheel zoom ────────────────────────────────────────────────────────────────\n const handleWheel = useCallback((e: Konva.KonvaEventObject<WheelEvent>): void => {\n e.evt.preventDefault();\n const stage = e.target.getStage();\n if (!stage) return;\n const pointer = stage.getPointerPosition();\n if (!pointer) return;\n const delta = -e.evt.deltaY / 1000;\n zoom(delta, pointer.x, pointer.y);\n }, [zoom]);\n\n // ── Mouse pan ─────────────────────────────────────────────────────────────────\n const handleMouseDown = useCallback((e: Konva.KonvaEventObject<MouseEvent>): void => {\n const clickedOnEmpty = e.target === e.target.getStage();\n if (clickedOnEmpty && e.evt.button === 0) {\n e.evt.preventDefault();\n isPanningRef.current = true;\n lastPanPointRef.current = { x: e.evt.clientX, y: e.evt.clientY };\n panAccumRef.current = { x: 0, y: 0 };\n }\n }, []);\n\n const handleMouseMove = useCallback((e: Konva.KonvaEventObject<MouseEvent>): void => {\n if (!isPanningRef.current) return;\n e.evt.preventDefault();\n const deltaX = e.evt.clientX - lastPanPointRef.current.x;\n const deltaY = e.evt.clientY - lastPanPointRef.current.y;\n\n // Apply pan directly to stage (no Zustand overhead per-frame)\n const stage = e.target.getStage();\n if (stage) {\n stage.x(stage.x() + deltaX);\n stage.y(stage.y() + deltaY);\n stage.batchDraw();\n }\n\n panAccumRef.current.x += deltaX;\n panAccumRef.current.y += deltaY;\n lastPanPointRef.current = { x: e.evt.clientX, y: e.evt.clientY };\n }, []); // No Zustand dep — pan flushed on mouseUp\n\n const handleMouseUp = useCallback((): void => {\n if (isPanningRef.current) {\n isPanningRef.current = false;\n const { x, y } = panAccumRef.current;\n if (x !== 0 || y !== 0) {\n pan(x, y);\n panAccumRef.current = { x: 0, y: 0 };\n }\n }\n }, [pan]);\n\n const cancelPan = useCallback((): void => {\n if (!isPanningRef.current) return;\n isPanningRef.current = false;\n const { x, y } = panAccumRef.current;\n if (x !== 0 || y !== 0) { pan(x, y); panAccumRef.current = { x: 0, y: 0 }; }\n }, [pan]);\n\n return { handleWheel, handleMouseDown, handleMouseMove, handleMouseUp, cancelPan, canvasWidth, canvasHeight };\n}\n","// ─── useLayerChoreography ─────────────────────────────────────────────────────\n//\n// Step inside / back out, as the design system's motion.ts describes them:\n//\n// step inside the current layer zooms toward the idea (scale 3.2, ease-zoom, 500ms)\n// and fades (160ms after 150ms); the layers swap at 320ms.\n// back out the current layer shrinks toward the centre (scale .6, 220ms) and\n// fades (200ms); the layers swap at 220ms.\n// arrive the new layer's ideas bloom in and its connectors draw (RevealClock),\n// while the layer as a whole settles from scale .94 (260ms).\n// reduced motion reduced (or instant reveal): no zoom, the layers swap at once and\n// the new one fades in (120ms).\n//\n// The zoom/fade/settle run on the canvas wrapper as compositor animations (Web\n// Animations API), so the Konva canvas is not redrawn while they play.\n// All numbers and easings come from core's MOTION (design-system/geometry/motion.ts).\n\nimport { useCallback, useEffect, useRef } from 'react';\nimport type Konva from 'konva';\nimport { MOTION, cssEase, swapDelay, type FlatNode } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\n/** A viewport to return to: centre and zoom. */\nexport interface AnimatorViewport { centerX: number; centerY: number; zoomLevel: number }\nimport { calculateFitView } from '../utils/layerNavigation';\n\nexport interface LayerChoreographyOptions {\n stageRef: React.RefObject<Konva.Stage | null>;\n /** The element around the Konva stage; the zoom, fade and settle play on it. */\n canvasWrapperRef: React.RefObject<HTMLDivElement | null>;\n reducedMotion: boolean;\n /** Switch the displayed layer to a child layer (the layers swap here). */\n onSwapLayer: (childLayerId: string) => void;\n /** Switch back to the parent layer (the layers swap here). */\n onSwapBack: () => void;\n /** Called once the new layer has settled. */\n onComplete: () => void;\n /** 'start' before anything moves, 'end' after the new layer has settled (pause hit-testing, GPU hints). */\n onLifecycle?: (phase: 'start' | 'end') => void;\n}\n\nexport interface LayerChoreography {\n /** Step inside `targetNode` into the child layer. */\n stepInside: (targetNode: FlatNode, childLayerId: string, childNodes: ReadonlyArray<FlatNode>) => void;\n /** Back out to a layer whose fit viewport is `parent`. */\n backOut: (parent: AnimatorViewport) => void;\n /** The new layer is committed and drawing at its first frame: lift the veil and settle. Call after the swap's React commit. */\n arrive: () => void;\n isTransitioning: () => boolean;\n}\n\nexport function useLayerChoreography(o: LayerChoreographyOptions): LayerChoreography {\n const { stageRef, canvasWrapperRef } = o;\n const opts = useRef(o);\n opts.current = o;\n\n const busy = useRef(false);\n const waiting = useRef(false); // swapped, waiting for the new layer's commit\n const anims = useRef<Animation[]>([]);\n const timers = useRef<ReturnType<typeof setTimeout>[]>([]);\n const after = useRef<number[]>([]);\n\n const clear = useCallback(() => {\n timers.current.forEach(clearTimeout); timers.current = [];\n after.current.forEach(cancelAnimationFrame); after.current = [];\n anims.current.forEach((a) => a.cancel()); anims.current = [];\n }, []);\n\n const applyViewport = useCallback((vp: AnimatorViewport) => {\n const stage = stageRef.current;\n if (stage) {\n stage.x(stage.width() / 2 - vp.centerX * vp.zoomLevel);\n stage.y(stage.height() / 2 - vp.centerY * vp.zoomLevel);\n stage.scaleX(vp.zoomLevel); stage.scaleY(vp.zoomLevel);\n stage.getLayers().forEach((l) => l.drawScene());\n }\n const s = useViewportStore.getState();\n s.setCenter(vp.centerX, vp.centerY);\n s.setZoom(vp.zoomLevel);\n }, [stageRef]);\n\n const lifecycle = useCallback((phase: 'start' | 'end') => {\n const stage = stageRef.current;\n stage?.getLayers().forEach((l) => { l.listening(phase === 'end'); });\n if (phase === 'end') stage?.batchDraw();\n opts.current.onLifecycle?.(phase);\n }, [stageRef]);\n\n const leave = useCallback((wrap: HTMLElement | null, dir: 'in' | 'out', origin: string, vp: AnimatorViewport, swap: () => void) => {\n busy.current = true;\n waiting.current = false;\n lifecycle('start');\n const reduced = opts.current.reducedMotion;\n if (wrap && !reduced && typeof wrap.animate === 'function') {\n const m = MOTION;\n wrap.style.transformOrigin = origin;\n wrap.style.willChange = 'transform, opacity';\n if (dir === 'in') {\n anims.current.push(\n wrap.animate([{ transform: 'scale(1)' }, { transform: `scale(${m.dive.scale})` }], { duration: m.dive.duration, easing: cssEase(m.dive.ease), fill: 'forwards' }),\n wrap.animate([{ opacity: 1 }, { opacity: 0 }], { delay: m.dive.fadeDelay, duration: m.dive.fade, easing: 'ease', fill: 'both' }),\n );\n } else {\n anims.current.push(\n wrap.animate([{ transform: 'scale(1)' }, { transform: `scale(${m.surface.scale})` }], { duration: m.surface.duration, easing: cssEase(m.surface.ease), fill: 'forwards' }),\n wrap.animate([{ opacity: 1 }, { opacity: 0 }], { duration: m.surface.fade, easing: 'ease', fill: 'both' }),\n );\n }\n }\n timers.current.push(setTimeout(() => {\n waiting.current = true;\n swap();\n applyViewport(vp);\n // Safety net: if the host never reports the commit, arrive anyway.\n timers.current.push(setTimeout(() => arriveRef.current(), 500));\n }, swapDelay(dir, reduced)));\n }, [applyViewport, lifecycle]);\n\n const arriveRef = useRef<() => void>(() => {});\n const arrive = useCallback(() => {\n if (!waiting.current) return;\n waiting.current = false;\n const wrap = canvasWrapperRef.current;\n const reduced = opts.current.reducedMotion;\n // Drop the zoomed-and-faded veil (the new layer is drawing its first frame, ideas not yet bloomed) and settle.\n anims.current.forEach((a) => a.cancel()); anims.current = [];\n let settle = reduced ? MOTION.reduced.fade : MOTION.settle.duration;\n if (wrap && !reduced && typeof wrap.animate === 'function') {\n const a = wrap.animate([{ transform: `scale(${MOTION.settle.fromScale})` }, { transform: 'none' }], { duration: MOTION.settle.duration, easing: cssEase(MOTION.settle.ease) });\n anims.current.push(a);\n settle = MOTION.settle.duration;\n }\n timers.current.push(setTimeout(() => {\n anims.current.forEach((a) => a.cancel()); anims.current = [];\n if (wrap) { wrap.style.willChange = 'auto'; wrap.style.transformOrigin = ''; }\n busy.current = false;\n opts.current.onComplete();\n lifecycle('end');\n }, settle));\n }, [canvasWrapperRef, lifecycle]);\n arriveRef.current = arrive;\n\n const stepInside = useCallback((targetNode: FlatNode, childLayerId: string, childNodes: ReadonlyArray<FlatNode>) => {\n if (busy.current) return;\n const stage = stageRef.current;\n const zoom = stage?.scaleX() ?? 1;\n const origin = stage ? `${targetNode.x * zoom + stage.x()}px ${targetNode.y * zoom + stage.y()}px` : '50% 50%';\n const fit = calculateFitView(childNodes as FlatNode[], stage?.width() ?? 800, stage?.height() ?? 600);\n leave(canvasWrapperRef.current, 'in', origin, { centerX: fit.centerX, centerY: fit.centerY, zoomLevel: fit.zoomLevel }, () => opts.current.onSwapLayer(childLayerId));\n }, [stageRef, canvasWrapperRef, leave]);\n\n const backOut = useCallback((parent: AnimatorViewport) => {\n if (busy.current) return;\n leave(canvasWrapperRef.current, 'out', '50% 50%', parent, () => opts.current.onSwapBack());\n }, [canvasWrapperRef, leave]);\n\n const isTransitioning = useCallback(() => busy.current, []);\n useEffect(() => () => { clear(); busy.current = false; }, [clear]);\n return { stepInside, backOut, arrive, isTransitioning };\n}\n","// ─── Layer Navigation Utilities ──────────────────────────────────────────────\n//\n// React-specific re-exports or wrappers of core navigation logic.\n\nexport {\n getConnectionsForLayer,\n getChildLayerForNode,\n getLayerForNavigation,\n calculateFitZoom,\n calculateFitCenter,\n getContainersForLayer,\n calculateFitView,\n} from '@visualli/core';\n\nexport type { FitResult, ContainerGroupInfo } from '@visualli/core';\n","// ─── Choreography ────────────────────────────────────────────────────────────\n//\n// Runs the design system's motion timeline (core's MOTION / revealDelay /\n// connectorDelay / bloomOffset / easeBezier, copied verbatim from\n// design-system/geometry/motion.ts) on the canvas: the same arrival, hover and\n// reduced-motion behaviour VisualMap gets from its CSS animations.\n//\n// No React and no Konva in here; the layers ask \"what does idea / connector i\n// look like right now?\" while they paint, and redraw each frame while a\n// timeline is running.\n\nimport { MOTION, easeBezier, bloomOffset, layerReveal, type FlatNode } from '@visualli/core';\n\nconst clamp01 = (v: number) => (v < 0 ? 0 : v > 1 ? 1 : v);\n\n/** How an idea looks mid-arrival (multiplies its resting look). */\nexport interface Arrival { alpha: number; scale: number; dx: number; dy: number }\n/** How a connector looks mid-arrival: `draw` is the fraction of the line drawn, `alpha` its group's fade. */\nexport interface EdgeArrival { alpha: number; draw: number }\n\n/** The timeline of one layer's arrival. Shared by the idea layer and the connector layer. */\nexport class RevealClock {\n private t0 = -Infinity;\n private end = 0;\n private plan = layerReveal(0, 0);\n private reduced = false;\n private center = { x: 0, y: 0 };\n private order = new Map<string, number>();\n private listeners = new Set<(running: boolean) => void>();\n private timer: ReturnType<typeof setTimeout> | null = null;\n\n /** Begin a layer's arrival. `reduced` (reduced motion or instant reveal): everything fades in together. */\n start(nodes: ReadonlyArray<FlatNode>, edgeCount: number, reduced: boolean, now = performance.now()): void {\n this.order.clear();\n nodes.forEach((n, i) => this.order.set(n.id, i));\n // The design system's arrival, large layers included (geometry/motion.ts → layerReveal): shared stagger slots\n // above largeLayer.staggerSlots, a fade-in together above largeLayer.bloomMax.\n this.plan = layerReveal(nodes.length, edgeCount);\n this.reduced = reduced || this.plan.instant;\n reduced = this.reduced;\n let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;\n for (const n of nodes) { minX = Math.min(minX, n.x); maxX = Math.max(maxX, n.x); minY = Math.min(minY, n.y); maxY = Math.max(maxY, n.y); }\n this.center = nodes.length ? { x: (minX + maxX) / 2, y: (minY + maxY) / 2 } : { x: 0, y: 0 };\n this.t0 = now;\n this.end = reduced ? MOTION.reduced.fade : this.plan.total;\n this.emit(true);\n if (this.timer) clearTimeout(this.timer);\n this.timer = setTimeout(() => { this.timer = null; this.emit(false); }, this.end + 50);\n }\n\n /** Jump to the finished state (e.g. on unmount). */\n stop(): void {\n this.t0 = -Infinity;\n if (this.timer) { clearTimeout(this.timer); this.timer = null; }\n this.emit(false);\n }\n\n /** True while the layer is still arriving. */\n active(now = performance.now()): boolean { return now - this.t0 < this.end; }\n\n /** Called with true when an arrival starts and false when it has finished. Returns the unsubscribe function. */\n subscribe(fn: (running: boolean) => void): () => void {\n this.listeners.add(fn);\n return () => { this.listeners.delete(fn); };\n }\n\n private emit(running: boolean) { this.listeners.forEach((fn) => fn(running)); }\n\n /** Fills `out` with idea `id`'s arrival look. Returns false when it has arrived (nothing to apply). */\n node(id: string, x: number, y: number, now: number, out: Arrival): boolean {\n const el = now - this.t0;\n if (el >= this.end) return false;\n const i = this.order.get(id);\n if (i === undefined) return false;\n if (this.reduced) {\n out.alpha = clamp01(el / MOTION.reduced.fade); out.scale = 1; out.dx = 0; out.dy = 0;\n return true;\n }\n const r = MOTION.reveal;\n const t = el - this.plan.ideaDelay(i);\n if (t >= r.duration) return false;\n const e = t <= 0 ? 0 : easeBezier(r.ease, t / r.duration); // `backwards` fill: waiting ideas sit at the first keyframe\n const from = bloomOffset({ x, y }, this.center);\n out.alpha = clamp01(e);\n out.scale = r.fromScale + (1 - r.fromScale) * e;\n out.dx = from.x * (1 - e);\n out.dy = from.y * (1 - e);\n return true;\n }\n\n /** Fills `out` with connector `i`'s arrival look. Returns false when it has arrived. */\n edge(i: number, dashed: boolean, now: number, out: EdgeArrival): boolean {\n const el = now - this.t0;\n if (el >= this.end) return false;\n if (this.reduced) { out.alpha = clamp01(el / MOTION.reduced.fade); out.draw = 1; return true; }\n const c = MOTION.connector;\n const t = el - this.plan.connectorDelay(i);\n if (t >= c.draw && t >= c.fade) return false;\n const group = t <= 0 ? 0 : easeBezier(c.ease, clamp01(t / c.fade));\n const line = t <= 0 ? 0 : easeBezier(c.ease, clamp01(t / c.draw));\n // A solid connector draws from source to target; a dashed one fades in instead.\n out.alpha = dashed ? group * line : group;\n out.draw = dashed ? 1 : line;\n return true;\n }\n}\n\n// ── Hover ─────────────────────────────────────────────────────────────────────\n\ninterface HoverTween { fromLift: number; fromRing: number; to: number; t0: number }\n\n/**\n * Hover / select / press: an idea lifts (ease-bloom, so it settles with a little\n * overshoot) while its rings turn and grow (ease-standard), both over\n * `MOTION.hover.duration`. Tracks each raised idea's progress so reversing\n * mid-way continues from where it was.\n */\nexport class HoverTweens {\n private tweens = new Map<string, HoverTween>();\n private raised = new Set<string>();\n\n /** Set which ideas are raised now. Returns true when anything started moving. */\n set(next: ReadonlySet<string>, reduced: boolean, now = performance.now()): boolean {\n let changed = false;\n const ids = new Set<string>([...this.raised, ...next]);\n for (const id of ids) {\n const was = this.raised.has(id), is = next.has(id);\n if (was === is) continue;\n const cur = this.progress(id, now);\n this.tweens.set(id, { fromLift: cur.lift, fromRing: cur.ring, to: is ? 1 : 0, t0: reduced ? -Infinity : now });\n changed = true;\n }\n this.raised = new Set(next);\n return changed;\n }\n\n private cache = { lift: 0, ring: 0 };\n /** Lift (bloom ease) and ring (standard ease) progress of an idea, 0 at rest and 1 fully raised. */\n progress(id: string, now: number): { lift: number; ring: number } {\n const tw = this.tweens.get(id);\n const out = this.cache;\n if (!tw) { out.lift = out.ring = this.raised.has(id) ? 1 : 0; return out; }\n const u = clamp01((now - tw.t0) / MOTION.hover.duration);\n out.lift = tw.fromLift + (tw.to - tw.fromLift) * easeBezier(MOTION.hover.liftEase, u);\n out.ring = tw.fromRing + (tw.to - tw.fromRing) * easeBezier(MOTION.hover.ringEase, u);\n if (u >= 1) { this.tweens.delete(id); out.lift = out.ring = tw.to; }\n return out;\n }\n\n /** True while any idea is still moving. */\n active(now = performance.now()): boolean {\n for (const tw of this.tweens.values()) if (now - tw.t0 < MOTION.hover.duration) return true;\n return false;\n }\n\n has(id: string): boolean { return this.tweens.has(id) || this.raised.has(id); }\n}\n","// ─── KonvaStage ───────────────────────────────────────────────────────────────\n//\n// Thin wrapper around react-konva <Stage> that:\n// • Binds canvas position/scale from the viewport store\n// • Accepts optional event handlers (wheel, mouse, touch, context-menu)\n// • Calls stage.destroy() on unmount (memory hygiene)\n// • Renders at devicePixelRatio and follows it when it changes (browser zoom,\n// moving the window to another display)\n\nimport React, { useRef, useEffect, forwardRef } from 'react';\nimport { KStage as Stage } from '../konvaCompat';\nimport Konva from 'konva';\nimport { useViewportStore } from '../stores/useViewportStore';\nimport { currentPixelRatio, watchPixelRatio } from '../design/runtime';\n\nexport interface KonvaStageProps {\n children: React.ReactNode;\n onWheel?: (e: Konva.KonvaEventObject<WheelEvent>) => void;\n onMouseDown?: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n onMouseMove?: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n onMouseUp?: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n onContextMenu?: (e: Konva.KonvaEventObject<MouseEvent>) => void;\n onTouchStart?: (e: Konva.KonvaEventObject<TouchEvent>) => void;\n onTouchMove?: (e: Konva.KonvaEventObject<TouchEvent>) => void;\n onTouchEnd?: (e: Konva.KonvaEventObject<TouchEvent>) => void;\n onStageReady?: (stage: Konva.Stage) => void;\n}\n\nconst KonvaStage = forwardRef<Konva.Stage, KonvaStageProps>(function KonvaStage(\n {\n children,\n onWheel, onMouseDown, onMouseMove, onMouseUp, onContextMenu,\n onTouchStart, onTouchMove, onTouchEnd,\n onStageReady,\n },\n ref,\n) {\n const internalRef = useRef<Konva.Stage | null>(null);\n const { centerX, centerY, zoomLevel, canvasWidth, canvasHeight } = useViewportStore();\n\n useEffect(() => {\n if (internalRef.current) {\n if (typeof ref === 'function') ref(internalRef.current);\n else if (ref) (ref as React.MutableRefObject<Konva.Stage | null>).current = internalRef.current;\n onStageReady?.(internalRef.current);\n }\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n const stage = internalRef.current; // the stage this mount created\n return () => { stage?.destroy(); };\n }, []);\n\n // Konva reads the global pixelRatio when a layer creates its canvases, so set it\n // before the first draw and re-size every canvas when the ratio changes later.\n Konva.pixelRatio = currentPixelRatio();\n useEffect(() => watchPixelRatio((ratio) => {\n Konva.pixelRatio = ratio;\n const stage = internalRef.current;\n if (!stage) return;\n stage.getLayers().forEach((l) => { l.getCanvas().setPixelRatio(ratio); l.getHitCanvas().setPixelRatio(ratio); });\n stage.batchDraw();\n }), []);\n\n const w = canvasWidth || 800;\n const h = canvasHeight || 600;\n const stageX = w / 2 - centerX * zoomLevel;\n const stageY = h / 2 - centerY * zoomLevel;\n\n return (\n <Stage\n ref={internalRef}\n width={w}\n height={h}\n x={stageX}\n y={stageY}\n scaleX={zoomLevel}\n scaleY={zoomLevel}\n onWheel={onWheel}\n onMouseDown={onMouseDown}\n onMouseMove={onMouseMove}\n onMouseUp={onMouseUp}\n onContextMenu={onContextMenu}\n onTouchStart={onTouchStart}\n onTouchMove={onTouchMove}\n onTouchEnd={onTouchEnd}\n draggable={false}\n >\n {children}\n </Stage>\n );\n});\n\nexport default KonvaStage;\n","// ─── konvaCompat ──────────────────────────────────────────────────────────────\n//\n// react-konva@18.x defines KonvaNodeComponent with return type\n// `ReactNode | Promise<ReactNode>`. @types/react v19 tightened the JSX checker\n// so that signature no longer satisfies `(props: any) => ReactNode`, causing\n// TS2786 errors everywhere a Konva primitive is used as JSX.\n//\n// The fix: re-export every Konva primitive cast to React.ComponentType<any>.\n// This is purely a type-level shim — no runtime behaviour changes.\n\nimport {\n Stage, Layer, Group, Shape, Path, Rect, Text, Arrow, Line, Circle, TextPath,\n} from 'react-konva';\nimport type React from 'react';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype C = React.ComponentType<any>;\n\nexport const KStage = Stage as unknown as C;\nexport const KLayer = Layer as unknown as C;\nexport const KGroup = Group as unknown as C;\nexport const KShape = Shape as unknown as C;\nexport const KPath = Path as unknown as C;\nexport const KRect = Rect as unknown as C;\nexport const KText = Text as unknown as C;\nexport const KArrow = Arrow as unknown as C;\nexport const KLine = Line as unknown as C;\nexport const KCircle = Circle as unknown as C;\nexport const KTextPath = TextPath as unknown as C;\n","// ─── Design-system runtime ───────────────────────────────────────────────────\n//\n// Injects the design system's CSS (tokens + spec components) once per page,\n// loads its fonts, and tracks devicePixelRatio for the canvas.\n//\n// Dependencies: ../generated/specCss.ts (generated from design-system/).\n\nimport { useSyncExternalStore } from 'react';\nimport { TOKENS, TYPE_STYLES } from '@visualli/core';\nimport {\n SPEC_BUNDLED_FONTS,\n SPEC_COMPONENT_CSS,\n SPEC_DESIGN_SYSTEM_VERSION,\n SPEC_FONTS_URL,\n SPEC_TOKENS_CSS,\n} from '../generated/specCss';\n\nconst STYLE_ID = 'visualli-design-system';\n\n/**\n * Responsive rules the SDK adds on top of the spec CSS. The design system defines the\n * touch variant (`.is-touch`, bottom sheet); phone / tablet / desktop widths are\n * handled with the container-width classes the canvas sets (`is-compact` < 560px,\n * `is-medium` < 900px). Only design-system custom properties are used.\n */\nconst LAYOUT_CSS = `\n.vi-map__ctrls { transition: bottom var(--duration-quick) var(--ease-standard); } /* controlsPosition 'bottom-right': rising above the sheet */\n.vi-map.is-compact .vi-trail li:not(:first-child):not(.is-current):not(:nth-last-child(2)) { display: none; }\n.vi-map.is-compact .vi-trail button span { max-width: 40vw; max-width: 40cqw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.vi-map.is-compact .vi-fact:not(.vi-fact--sheet) { width: min(300px, calc(100cqw - 2 * var(--space-4))); }\n.vi-map.is-touch .vi-trail button { min-height: 32px; }\n`;\nconst FONTS_ID = 'visualli-design-system-fonts';\nconst CAVEAT_ID = 'visualli-design-system-caveat';\n// Injected by tsup (`define`) from package.json so it can never drift from the published version.\ndeclare const __SDK_VERSION__: string;\nconst SDK_VERSION = typeof __SDK_VERSION__ === 'string' ? __SDK_VERSION__ : 'latest';\n\nexport interface DesignSystemAssets {\n /**\n * Where the bundled Caveat font file is served from (URL of the directory that\n * contains `Caveat-Variable.ttf`). Defaults to the copy shipped inside the npm\n * package, via jsDelivr.\n */\n fontBaseUrl?: string;\n /** Set false to skip the Google Fonts stylesheet (Kalam + Atkinson Hyperlegible), e.g. when self-hosting them. */\n loadWebFonts?: boolean;\n}\n\nlet webFontsSheet: Promise<void> = Promise.resolve();\n\n/**\n * Inject the spec CSS and font declarations once. Safe to call repeatedly and on the server (no-op).\n * The returned promise settles when the web-font stylesheet has loaded (its @font-face rules must exist\n * before document.fonts.load() can fetch anything).\n */\nexport function ensureDesignSystemStyles(assets: DesignSystemAssets = {}): Promise<void> {\n if (typeof document === 'undefined') return Promise.resolve();\n\n if (!document.getElementById(STYLE_ID)) {\n const style = document.createElement('style');\n style.id = STYLE_ID;\n style.setAttribute('data-design-system', SPEC_DESIGN_SYSTEM_VERSION);\n // Component CSS goes first so token rules (same specificity) win ties, exactly like index.css load order.\n style.textContent = `${SPEC_TOKENS_CSS}\\n${SPEC_COMPONENT_CSS}\\n${LAYOUT_CSS}`;\n document.head.appendChild(style);\n }\n\n if (assets.loadWebFonts !== false && SPEC_FONTS_URL && !document.getElementById(FONTS_ID)) {\n const link = document.createElement('link');\n link.id = FONTS_ID;\n link.rel = 'stylesheet';\n link.href = SPEC_FONTS_URL;\n webFontsSheet = new Promise<void>((resolve) => {\n link.addEventListener('load', () => resolve(), { once: true });\n link.addEventListener('error', () => resolve(), { once: true });\n });\n document.head.appendChild(link);\n }\n\n if (!document.getElementById(CAVEAT_ID)) {\n const base = (assets.fontBaseUrl ?? `https://cdn.jsdelivr.net/npm/@visualli/react@${SDK_VERSION}/fonts`).replace(/\\/$/, '');\n const style = document.createElement('style');\n style.id = CAVEAT_ID;\n style.textContent = SPEC_BUNDLED_FONTS\n .map((f) => `@font-face { font-family: \"${f.family}\"; src: url(\"${base}/${f.file}\"); font-weight: ${f.weight}; font-display: swap; }`)\n .join('\\n');\n document.head.appendChild(style);\n }\n return webFontsSheet;\n}\n\n// ── Fonts ─────────────────────────────────────────────────────────────────────\n\n/** First family of a font stack token, e.g. `font-hand` -> its handwriting face. */\nconst firstFamily = (stack: string): string => stack.split(',')[0]!.trim();\n\n/**\n * Faces the canvas draws with, derived from the design-system tokens and type styles.\n * Loading them up front means the first frame already uses the right fonts.\n */\nconst CANVAS_FONT_FACES = (['node-label', 'edge-label', 'body'] as const).map((style) => {\n const t = TYPE_STYLES[style];\n return `${t.weight} ${t.size}px ${firstFamily(TOKENS.light[t.family]!)}`;\n});\n\nlet fontsEpochValue = 0;\nconst fontListeners = new Set<() => void>();\n\n/** Bumps whenever web fonts finish loading; text measurement caches are keyed on it. */\nexport const fontsEpoch = (): number => fontsEpochValue;\n\n/** React hook: re-renders when fonts finish loading (so canvases redraw with the real faces). */\nexport function useFontsEpoch(): number {\n return useSyncExternalStore(onFontsChange, fontsEpoch, () => 0);\n}\nexport const onFontsChange = (cb: () => void): (() => void) => { fontListeners.add(cb); return () => fontListeners.delete(cb); };\n\n/**\n * Resolves once the canvas fonts are usable (or after `timeoutMs`, so an\n * offline reader still gets a map in the fallback faces).\n */\nexport function loadCanvasFonts(sheet: Promise<void> = Promise.resolve(), timeoutMs = 3000): Promise<void> {\n if (typeof document === 'undefined' || !('fonts' in document)) return Promise.resolve();\n const fonts = document.fonts;\n const loads = sheet.then(() => Promise.all(CANVAS_FONT_FACES.map((f) => fonts.load(f).catch(() => [])))).then(() => fonts.ready).then(() => undefined);\n const timeout = new Promise<void>((r) => setTimeout(r, timeoutMs));\n return Promise.race([loads, timeout]).then(() => { fontsEpochValue++; fontListeners.forEach((cb) => cb()); });\n}\n\nif (typeof document !== 'undefined' && 'fonts' in document) {\n // Late-arriving faces (slow network) invalidate cached text layouts and trigger a redraw.\n document.fonts.addEventListener?.('loadingdone', () => { fontsEpochValue++; fontListeners.forEach((cb) => cb()); });\n}\n\n// ── Pixel ratio ───────────────────────────────────────────────────────────────\n\n/** Device pixel ratio the canvas renders at (capped: >3 only costs memory). */\nexport const currentPixelRatio = (): number =>\n typeof window === 'undefined' ? 1 : Math.min(Math.max(window.devicePixelRatio || 1, 1), 3);\n\n/** Calls `cb` whenever devicePixelRatio changes (browser zoom, moving the window between displays). */\nexport function watchPixelRatio(cb: (ratio: number) => void): () => void {\n if (typeof window === 'undefined' || !window.matchMedia) return () => {};\n let mql: MediaQueryList;\n let stopped = false;\n const arm = () => {\n mql = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);\n mql.addEventListener('change', onChange, { once: true });\n };\n const onChange = () => { if (stopped) return; cb(currentPixelRatio()); arm(); };\n arm();\n return () => { stopped = true; mql.removeEventListener('change', onChange); };\n}\n","// GENERATED by scripts/gen-design-system.mjs from design-system/ (tokens/tokens.css, css/spec.css). Do not edit.\n// Change the design system instead; the next `npm run build` regenerates this file.\n\nexport const SPEC_TOKENS_CSS = \"/* Spec tokens for all 8 themes — generated from the Visualli design system (v0.2.1). Do not edit here: changes come in through PRs from the private design system. MIT license, see ../LICENSE. */\\n:root, [data-theme=\\\"light\\\"] {\\n --font-display: \\\"Atkinson Hyperlegible Next\\\", system-ui, sans-serif;\\n --font-ui: \\\"Atkinson Hyperlegible Next\\\", system-ui, -apple-system, \\\"Segoe UI\\\", sans-serif;\\n --font-hand: Kalam, \\\"Atkinson Hyperlegible Next\\\", cursive;\\n --font-note: Caveat, Kalam, cursive;\\n --font-mono: \\\"Atkinson Hyperlegible Mono\\\", ui-monospace, \\\"SF Mono\\\", Menlo, monospace;\\n --canvas: #f6f3ee;\\n --surface: #ffffff;\\n --surface-sunken: #f0ece5;\\n --surface-overlay: #ffffff;\\n --line: #e4dfd6;\\n --line-strong: #7a7f94;\\n --ink: #182140;\\n --ink-muted: #4f5671;\\n --ink-subtle: #5f647c;\\n --action: #182140;\\n --on-action: #ffffff;\\n --focus: #325e8c;\\n --link: #2f5a87;\\n --selection: rgba(18, 199, 211, 0.28);\\n --node-ink: #182140;\\n --edge: #2a3048;\\n --edge-label: #4f5671;\\n --topic-teal: #87f2f8;\\n --topic-teal-ring: #00cdd5;\\n --topic-harbor: #bcdbff;\\n --topic-harbor-ring: #76b2f5;\\n --topic-iris: #e0c8fe;\\n --topic-iris-ring: #bd96ea;\\n --topic-berry: #ffbdc4;\\n --topic-berry-ring: #f47e8f;\\n --topic-coral: #ffc7b2;\\n --topic-coral-ring: #f38e65;\\n --topic-amber: #ffcf9d;\\n --topic-amber-ring: #eb9c38;\\n --topic-sun: #ffea94;\\n --topic-sun-ring: #dfbd04;\\n --topic-stone: #e0dacf;\\n --topic-stone-ring: #bab09f;\\n --space-1: 4px;\\n --space-2: 8px;\\n --space-3: 12px;\\n --space-4: 16px;\\n --space-7: 48px;\\n --radius-sm: 10px;\\n --radius-md: 16px;\\n --radius-lg: 24px;\\n --radius-pill: 999px;\\n --shadow-float: 0 1px 2px rgba(24, 33, 64, 0.06), 0 8px 24px rgba(24, 33, 64, 0.08);\\n --shadow-pop: 0 2px 4px rgba(24, 33, 64, 0.08), 0 16px 40px rgba(24, 33, 64, 0.14);\\n --node-width: 200px;\\n --node-height: 148px;\\n --node-stroke: 3px;\\n --edge-width: 2.5px;\\n --edge-gap: 15px;\\n --edge-arc-max: 45px;\\n --immersion-alpha: 0.15;\\n --zoom-min: 0.3;\\n --zoom-max: 5;\\n --duration-instant: 100ms;\\n --duration-quick: 160ms;\\n --duration-base: 240ms;\\n --duration-zoom: 500ms;\\n --duration-reveal: 420ms;\\n --stagger-reveal: 70ms;\\n --ease-zoom: cubic-bezier(0.2, 0.8, 0.2, 1);\\n --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);\\n --ease-bloom: cubic-bezier(0.34, 1.4, 0.64, 1);\\n --z-chrome: 10;\\n --z-card: 20;\\n --z-menu: 40;\\n }\\n[data-theme=\\\"dark\\\"] {\\n --canvas: #0f1220;\\n --surface: #171b2b;\\n --surface-sunken: #0f1220;\\n --surface-overlay: #212639;\\n --line: #2b3148;\\n --line-strong: #6c7392;\\n --ink: #eef0f7;\\n --ink-muted: #b3b8cc;\\n --ink-subtle: #8f95ae;\\n --action: #f6f3ee;\\n --on-action: #182140;\\n --focus: #12c7d3;\\n --link: #5fd8e1;\\n --selection: rgba(18, 199, 211, 0.32);\\n --edge: #c9cddc;\\n --edge-label: #b3b8cc;\\n --topic-teal-ring: #0fc5cd;\\n --topic-harbor-ring: #73aceb;\\n --topic-iris-ring: #b691e1;\\n --topic-berry-ring: #eb798a;\\n --topic-coral-ring: #ea8962;\\n --topic-amber-ring: #e29737;\\n --topic-sun-ring: #d8b70a;\\n --topic-stone-ring: #b4a999;\\n --shadow-float: 0 1px 2px rgba(0, 0, 0, 0.40), 0 8px 24px rgba(0, 0, 0, 0.35);\\n --shadow-pop: 0 2px 4px rgba(0, 0, 0, 0.50), 0 16px 40px rgba(0, 0, 0, 0.50);\\n }\\n[data-theme=\\\"focus-light\\\"] {\\n --canvas: #f4f2ee;\\n --edge: #5a6079;\\n --edge-label: #5a6079;\\n --topic-teal: #bce8ea;\\n --topic-teal-ring: #67c6cb;\\n --topic-harbor: #c9d9ec;\\n --topic-harbor-ring: #8bb2de;\\n --topic-iris: #d9cfe8;\\n --topic-iris-ring: #b79ed4;\\n --topic-berry: #edc6c9;\\n --topic-berry-ring: #da9099;\\n --topic-coral: #eecec1;\\n --topic-coral-ring: #db9b82;\\n --topic-amber: #eed4ba;\\n --topic-amber-ring: #d6a570;\\n --topic-sun: #f4eac1;\\n --topic-sun-ring: #d2bf73;\\n --topic-stone: #dddad5;\\n }\\n[data-theme=\\\"focus-dark\\\"] {\\n --canvas: #12141c;\\n --surface: #171b2b;\\n --surface-sunken: #0f1220;\\n --surface-overlay: #212639;\\n --line: #2b3148;\\n --line-strong: #6c7392;\\n --ink: #eef0f7;\\n --ink-muted: #b3b8cc;\\n --ink-subtle: #8f95ae;\\n --action: #f6f3ee;\\n --on-action: #182140;\\n --focus: #12c7d3;\\n --link: #5fd8e1;\\n --selection: rgba(18, 199, 211, 0.32);\\n --edge: #a9aec0;\\n --edge-label: #b3b8cc;\\n --topic-teal: #bce8ea;\\n --topic-teal-ring: #71bdc1;\\n --topic-harbor: #c9d9ec;\\n --topic-harbor-ring: #8cabce;\\n --topic-iris: #d9cfe8;\\n --topic-iris-ring: #ae9bc6;\\n --topic-berry: #edc6c9;\\n --topic-berry-ring: #cc8e95;\\n --topic-coral: #eecec1;\\n --topic-coral-ring: #cd9884;\\n --topic-amber: #eed4ba;\\n --topic-amber-ring: #c9a176;\\n --topic-sun: #f4eac1;\\n --topic-sun-ring: #c9b97a;\\n --topic-stone: #dddad5;\\n --topic-stone-ring: #b4a999;\\n }\\n[data-theme=\\\"colorsafe-light\\\"] {\\n --topic-teal: #b0ecbc;\\n --topic-teal-ring: #6cc982;\\n --topic-harbor: #abdbfe;\\n --topic-harbor-ring: #60b4ec;\\n --topic-iris: #f6bde2;\\n --topic-iris-ring: #dc87c0;\\n --topic-berry: #feb79e;\\n --topic-berry-ring: #ec7f58;\\n --topic-coral: #fece96;\\n --topic-coral-ring: #e49d41;\\n --topic-amber: #b2e8fa;\\n --topic-amber-ring: #5cc4e2;\\n --topic-sun: #f6f097;\\n --topic-sun-ring: #d0c637;\\n --topic-stone: #dbdbdb;\\n --topic-stone-ring: #b7afb1;\\n }\\n[data-theme=\\\"colorsafe-dark\\\"] {\\n --canvas: #0f1220;\\n --surface: #171b2b;\\n --surface-sunken: #0f1220;\\n --surface-overlay: #212639;\\n --line: #2b3148;\\n --line-strong: #6c7392;\\n --ink: #eef0f7;\\n --ink-muted: #b3b8cc;\\n --ink-subtle: #8f95ae;\\n --action: #f6f3ee;\\n --on-action: #182140;\\n --focus: #12c7d3;\\n --link: #5fd8e1;\\n --selection: rgba(18, 199, 211, 0.32);\\n --edge: #c9cddc;\\n --edge-label: #b3b8cc;\\n --topic-teal: #b0ecbc;\\n --topic-teal-ring: #69c27e;\\n --topic-harbor: #abdbfe;\\n --topic-harbor-ring: #5eade2;\\n --topic-iris: #f6bde2;\\n --topic-iris-ring: #d383b9;\\n --topic-berry: #feb79e;\\n --topic-berry-ring: #e37a55;\\n --topic-coral: #fece96;\\n --topic-coral-ring: #db9840;\\n --topic-amber: #b2e8fa;\\n --topic-amber-ring: #5bbdda;\\n --topic-sun: #f6f097;\\n --topic-sun-ring: #c9bf37;\\n --topic-stone: #dbdbdb;\\n --topic-stone-ring: #b1a8aa;\\n }\\n[data-theme=\\\"contrast-light\\\"] {\\n --canvas: #ffffff;\\n --surface-sunken: #f2f2f2;\\n --line: #5c6178;\\n --line-strong: #000000;\\n --ink: #000000;\\n --ink-muted: #1f2433;\\n --ink-subtle: #3a3f52;\\n --action: #000000;\\n --focus: #0b4a8f;\\n --link: #0b4a8f;\\n --node-ink: #000000;\\n --edge: #000000;\\n --edge-label: #1f2433;\\n --topic-teal-ring: #006b70;\\n --topic-harbor-ring: #0e599d;\\n --topic-iris-ring: #683b92;\\n --topic-berry-ring: #96173a;\\n --topic-coral-ring: #923400;\\n --topic-amber-ring: #7e4d00;\\n --topic-sun-ring: #7a6600;\\n --topic-stone-ring: #63594b;\\n --shadow-float: none;\\n --shadow-pop: none;\\n }\\n[data-theme=\\\"contrast-dark\\\"] {\\n --canvas: #000000;\\n --surface: #000000;\\n --surface-sunken: #0d0d0d;\\n --surface-overlay: #0d0d0d;\\n --line: #9aa0b8;\\n --line-strong: #ffffff;\\n --ink: #ffffff;\\n --ink-muted: #e6e8f0;\\n --ink-subtle: #c8ccda;\\n --action: #ffffff;\\n --on-action: #000000;\\n --focus: #5fe8f0;\\n --link: #7ff0f5;\\n --selection: rgba(18, 199, 211, 0.32);\\n --node-ink: #000000;\\n --edge: #ffffff;\\n --edge-label: #e6e8f0;\\n --topic-teal-ring: #64eff7;\\n --topic-harbor-ring: #b0d5fe;\\n --topic-iris-ring: #dcbfff;\\n --topic-berry-ring: #feb3bb;\\n --topic-coral-ring: #ffbea5;\\n --topic-amber-ring: #ffc78a;\\n --topic-sun-ring: #ffe26d;\\n --topic-stone-ring: #ddd3c2;\\n --shadow-float: none;\\n --shadow-pop: none;\\n }\\n[data-motion=\\\"reduced\\\"] {\\n --duration-instant: 120ms;\\n --duration-quick: 0ms;\\n --duration-base: 0ms;\\n --duration-zoom: 0ms;\\n --duration-reveal: 0ms;\\n --stagger-reveal: 0ms;\\n }\\n@media (prefers-reduced-motion: reduce) {\\n :root:not([data-motion=\\\"full\\\"]) {\\n --duration-instant: 120ms;\\n --duration-quick: 0ms;\\n --duration-base: 0ms;\\n --duration-zoom: 0ms;\\n --duration-reveal: 0ms;\\n --stagger-reveal: 0ms;\\n }\\n}\\n\\n/* Type styles */\\n.vi-text-heading { font-family: var(--font-ui); font-size: 17px; line-height: 24px; font-weight: 700; }\\n.vi-text-body { font-family: var(--font-ui); font-size: 15px; line-height: 22px; font-weight: 400; }\\n.vi-text-body-sm { font-family: var(--font-ui); font-size: 13px; line-height: 18px; font-weight: 400; }\\n.vi-text-label { font-family: var(--font-ui); font-size: 13px; line-height: 16px; font-weight: 600; letter-spacing: 0.01em; }\\n.vi-text-caption { font-family: var(--font-ui); font-size: 12px; line-height: 16px; font-weight: 400; }\\n.vi-text-node-root { font-family: var(--font-hand); font-size: 30px; line-height: 34px; font-weight: 700; }\\n.vi-text-node-label { font-family: var(--font-hand); font-size: 22px; line-height: 26px; font-weight: 700; }\\n.vi-text-edge-label { font-family: var(--font-note); font-size: 18px; line-height: 20px; font-weight: 500; }\\n.vi-text-annotation { font-family: var(--font-note); font-size: 24px; line-height: 26px; font-weight: 600; }\\n\";\nexport const SPEC_COMPONENT_CSS = \"/* Styles for the spec components (map, nodes, connectors, peek, terms, depth trail, controls) — generated from the Visualli design system (v0.2.1). Do not edit here: changes come in through PRs from the private design system. MIT license, see ../LICENSE. */\\n:root { --vi-fs-body: 15px; --vi-fs-sm: 13px; --vi-fs-cap: 12px; --vi-lh-body: 22px; --vi-label-scale: 1; }\\n[data-theme$=\\\"dark\\\"] :where([class^=\\\"vi-\\\"], [class*=\\\" vi-\\\"]) { color-scheme: dark; }\\n[data-scale=\\\"lg\\\"] { --vi-fs-body: 17px; --vi-fs-sm: 15px; --vi-fs-cap: 14px; --vi-lh-body: 26px; --vi-label-scale: 1.15; }\\n[data-type=\\\"readable\\\"] { --font-hand: \\\"Atkinson Hyperlegible Next\\\", system-ui, sans-serif; --font-note: \\\"Atkinson Hyperlegible Next\\\", system-ui, sans-serif; --font-display: \\\"Atkinson Hyperlegible Next\\\", system-ui, sans-serif; }\\n[data-type=\\\"readable\\\"] .vi-node__label, [data-type=\\\"readable\\\"] .vi-edge__label, [data-type=\\\"readable\\\"] .vi-map__group-label { font-family: var(--font-ui) !important; font-weight: 700; letter-spacing: 0.02em; font-style: normal; }\\n.vi-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }\\n.vi-icon { flex: none; display: block; }\\n:where([class^=\\\"vi-\\\"], [class*=\\\" vi-\\\"]):where(button, a, input, textarea, [tabindex]):focus-visible, :where([class^=\\\"vi-\\\"], [class*=\\\" vi-\\\"]) :where(button, a, input, textarea, [tabindex]):focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }\\n.vi-iconbtn { display: inline-grid; place-items: center; border-radius: var(--radius-sm); border: 1.5px solid transparent; background: transparent; color: var(--ink); cursor: pointer; transition: background var(--duration-instant); flex: none; }\\n.vi-iconbtn--sm { width: 32px; height: 32px; }\\n.vi-iconbtn--md { width: 40px; height: 40px; }\\n.vi-iconbtn--lg { width: 48px; height: 48px; border-radius: var(--radius-md); }\\n.vi-iconbtn:hover { background: var(--surface-sunken); }\\n.vi-iconbtn--surface { background: var(--surface); border-color: var(--line); }\\n.vi-iconbtn--surface:hover { border-color: var(--line-strong); }\\n.vi-iconbtn--primary { background: var(--action); color: var(--on-action); border-radius: var(--radius-pill); }\\n.vi-iconbtn.is-active { background: var(--action); color: var(--on-action); }\\n[data-theme^=\\\"contrast\\\"] .vi-ctrls { border: 2px solid var(--line-strong); }\\n.vi-node { position: relative; display: inline-grid; place-items: center; border: 0; padding: 0; background: none; color: var(--node-ink); cursor: default; transition: transform var(--duration-base) var(--ease-bloom), opacity var(--duration-base); -webkit-tap-highlight-color: transparent; }\\nbutton.vi-node { cursor: pointer; }\\n.vi-node__svg { position: absolute; inset: 0; overflow: visible; }\\n.vi-node__body { filter: drop-shadow(var(--vi-node-shadow, 0 6px 14px rgba(24, 33, 64, .10))); }\\n[data-theme$=\\\"dark\\\"] .vi-node__body { --vi-node-shadow: 0 0 22px rgba(255, 255, 255, .10); }\\n[data-theme^=\\\"contrast\\\"] .vi-node__body { filter: none; }\\n.vi-node__rings { transform-origin: center; transition: transform var(--duration-base) var(--ease-standard); }\\n@media (hover: hover) {\\n button.vi-node:hover .vi-node__rings { transform: rotate(var(--vi-ring-turn, -2deg)) scale(var(--vi-ring-grow, 1.015)); }\\n button.vi-node:hover { transform: translateY(calc(var(--vi-lift, 2px) * -1)); }\\n}\\n.vi-node { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; touch-action: manipulation; }\\n.vi-node.is-selected { transform: translateY(-2px); }\\n.vi-node.is-selected .vi-node__rings { transform: rotate(var(--vi-ring-turn, -2deg)) scale(var(--vi-ring-grow, 1.015)); }\\n.vi-node.is-selected .vi-node__body { stroke-width: 4; }\\n.vi-node:focus-visible { outline: none; }\\n.vi-node:focus-visible .vi-node__body { stroke: var(--focus); stroke-width: 4; }\\n.vi-node.is-selected .vi-node__body { stroke: var(--ink); }\\n.vi-node__label { position: relative; text-align: center; color: var(--node-ink); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; font-size: calc(var(--vi-nfs, 22px) * var(--vi-label-scale) * var(--vi-ninv, 1)); line-height: 1.15; padding-top: 2px; }\\n.vi-node__label.node-root { --vi-nfs: 30px; }\\n.vi-node--mini .vi-node__label { --vi-nfs: 15px; }\\n.vi-node.is-dimmed { opacity: 1; }\\n[data-theme^=\\\"focus\\\"] .vi-node.is-dimmed { opacity: .4; }\\n.vi-map.is-touch .vi-node.is-dimmed { opacity: .6; }\\n[data-theme^=\\\"focus\\\"] .vi-map.is-touch .vi-node.is-dimmed { opacity: .4; }\\n.vi-edge__line { fill: none; stroke: var(--edge); stroke-width: 2.5; stroke-linecap: round; }\\n.vi-edge.is-dashed .vi-edge__line { stroke-dasharray: 7 7; }\\n.vi-edge__arrow { fill: none; stroke: var(--edge); stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }\\n.vi-edge__label { font: 500 calc(18px * var(--vi-inv, 1)) / 1 var(--font-note); fill: var(--edge-label); paint-order: stroke; stroke: var(--canvas); stroke-width: 5px; stroke-linejoin: round; letter-spacing: .01em; }\\n[data-type=\\\"readable\\\"] .vi-edge__label { font-size: calc(14px * var(--vi-inv, 1)); font-weight: 600; }\\n.vi-fact { position: relative; width: 300px; box-sizing: border-box; padding: var(--space-4) var(--space-4) var(--space-3); background: var(--surface-overlay); color: var(--ink); border: 2px solid var(--vi-fact-ring); border-radius: 14px 18px 12px 16px / 16px 12px 18px 14px; font: 400 var(--vi-fs-sm)/20px var(--font-ui); z-index: var(--z-card); animation: vi-pop var(--duration-quick) var(--ease-standard); }\\n.vi-fact { box-shadow: 5px 6px 0 0 var(--vi-fact-fill), 5px 6px 0 2px var(--vi-fact-ring); }\\n[data-theme^=\\\"contrast\\\"] .vi-fact { border-color: var(--ink); }\\n[data-theme^=\\\"contrast\\\"] .vi-fact { box-shadow: none; }\\n.vi-fact__title { font: 700 22px/26px var(--font-hand); margin-bottom: var(--space-1); }\\n.vi-fact__body { color: var(--ink); }\\n.vi-fact__foot { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); margin-top: var(--space-3); padding-top: var(--space-2); border-top: 1px dashed var(--line); }\\n.vi-fact__acts { display: inline-flex; gap: var(--space-3); align-items: center; flex: none; }\\n.vi-fact__link { color: var(--link); font: 600 var(--vi-fs-cap)/16px var(--font-ui); }\\n.vi-fact__step { display: inline-flex; align-items: center; gap: 2px; border: 0; background: var(--action); color: var(--on-action); font: 600 var(--vi-fs-cap)/16px var(--font-ui); padding: 5px 8px 5px 10px; border-radius: var(--radius-pill); cursor: pointer; }\\n.vi-trail ol { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; position: relative; }\\n.vi-trail li { position: relative; }\\n.vi-trail li + li::before { content: \\\"\\\"; position: absolute; left: 13px; top: -8px; height: 10px; border-left: 1.5px dashed var(--line-strong); }\\n.vi-trail button { display: inline-flex; align-items: center; gap: 6px; border: 0; background: none; padding: 4px 8px 4px 5px; border-radius: var(--radius-sm); color: var(--ink-muted); font: 400 var(--vi-fs-cap)/16px var(--font-ui); cursor: pointer; }\\n.vi-trail button span { display: inline-flex; align-items: center; gap: 4px; }\\n.vi-trail button:hover:not(:disabled) { background: var(--surface-sunken); color: var(--ink); }\\n.vi-trail li.is-current button { color: var(--ink); font-weight: 700; font-size: var(--vi-fs-sm); cursor: default; background: var(--surface); box-shadow: var(--shadow-float); }\\n.vi-trail li.is-current button:disabled { opacity: 1; }\\n.vi-ctrls { display: inline-flex; align-items: center; gap: 2px; padding: 4px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-md); box-shadow: var(--shadow-float); }\\n.vi-ctrls__pct { min-width: 44px; text-align: center; font: 600 var(--vi-fs-cap)/16px var(--font-ui); color: var(--ink-muted); font-variant-numeric: tabular-nums; }\\n.vi-ctrls__div { width: 1px; height: 20px; background: var(--line); margin: 0 4px; }\\n.vi-map { position: relative; overflow: hidden; background: var(--canvas); border-radius: inherit; isolation: isolate; }\\n.vi-map__immersion { position: absolute; inset: 0; opacity: var(--immersion-alpha); transition: background var(--duration-base); z-index: -1; }\\n.vi-map__world { position: absolute; left: 0; top: 0; transform-origin: 0 0; }\\n.vi-map__edges { position: absolute; overflow: visible; pointer-events: none; }\\n.vi-map__group rect { fill: none; stroke: var(--line-strong); stroke-width: 1.5; stroke-dasharray: 10 6; }\\n.vi-map__group-label { position: absolute; transform: translate(-50%, -50%); z-index: 2; max-width: 420px; box-sizing: border-box; padding: 6px 22px 8px; background: var(--topic-stone); border: 1.5px solid var(--topic-stone-ring); border-radius: var(--radius-pill); font: 700 22px/1.1 var(--font-note); color: var(--node-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; pointer-events: none; font-size: calc(26px * var(--vi-label-scale) * var(--vi-ninv, 1)); }\\n[data-theme^=\\\"contrast\\\"] .vi-map__group-label { border: 2px solid var(--line-strong); }\\n.vi-map__slot { position: absolute; transform: translate(-50%, -50%); }\\n.vi-map.is-reveal .vi-map__slot { animation: vi-bloom var(--duration-reveal) var(--ease-bloom) backwards; }\\n.vi-map.is-reveal .vi-edge { animation: vi-fade var(--duration-base) var(--ease-standard) backwards; }\\n.vi-map.is-reveal .vi-edge__line { stroke-dasharray: 1; stroke-dashoffset: 1; animation: vi-line var(--vi-line-draw, .5s) var(--ease-standard) forwards; animation-delay: inherit; }\\n.vi-map.is-reveal .vi-edge.is-dashed .vi-edge__line { stroke-dasharray: 7 7; stroke-dashoffset: 0; animation: vi-fade var(--vi-line-draw, .5s) var(--ease-standard) backwards; animation-delay: inherit; }\\n.vi-map:not(.is-reveal) .vi-edge__line { stroke-dasharray: none; }\\n.vi-map:not(.is-reveal) .vi-edge.is-dashed .vi-edge__line { stroke-dasharray: 7 7; }\\n.vi-map__lens { position: absolute; inset: 0; transform-origin: var(--vi-ox) var(--vi-oy); }\\n.vi-map.is-diving .vi-map__lens { transform: scale(var(--vi-dive-scale, 3.2)); opacity: 0; transition: transform var(--duration-zoom) var(--ease-zoom), opacity var(--vi-dive-fade, 160ms) var(--vi-dive-fade-delay, 150ms); }\\n.vi-map.is-surfacing .vi-map__lens { transform: scale(var(--vi-surface-scale, .6)); opacity: 0; transform-origin: 50% 50%; transition: transform var(--vi-surface-dur, 220ms) var(--ease-zoom), opacity var(--vi-surface-fade, 200ms); }\\n.vi-map.is-reveal .vi-map__lens { animation: vi-settle var(--vi-settle-dur, 260ms) var(--ease-standard); }\\n[data-motion=\\\"reduced\\\"] .vi-map__lens { animation: none !important; transform: none !important; }\\n.vi-map__fact { position: absolute; }\\n.vi-map.is-idle .vi-map__world { transition: transform var(--duration-base) var(--ease-standard); }\\n.vi-map__hint { position: absolute; left: var(--space-4); right: var(--space-4); margin: 0; text-align: center; color: var(--ink-muted); pointer-events: none; z-index: var(--z-chrome); animation: vi-fade var(--duration-base) var(--ease-standard); }\\n.vi-fact__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-2); }\\n.vi-fact__back { display: inline-flex; align-items: center; gap: 2px; border: 0; background: none; padding: 2px 0; margin-bottom: var(--space-1); color: var(--link); font: 600 var(--vi-fs-cap)/16px var(--font-ui); cursor: pointer; }\\n.vi-term { border: 0; background: none; padding: 0; font: inherit; color: var(--link); text-decoration: underline; text-decoration-style: dotted; text-decoration-thickness: 1.5px; text-underline-offset: 3px; cursor: pointer; }\\n.vi-fact--sheet { position: absolute; left: 0; right: 0; bottom: 0; width: auto; max-width: 560px; margin: 0 auto; max-height: var(--vi-sheet-h, 300px); overflow-y: auto; overscroll-behavior: contain; padding: 0 var(--space-4) calc(var(--space-4) + env(safe-area-inset-bottom, 0px)); border: 0; border-top: 2px solid var(--vi-fact-ring); border-radius: var(--radius-lg) var(--radius-lg) 0 0; box-shadow: 0 -6px 0 0 var(--vi-fact-fill), var(--shadow-pop); font-size: var(--vi-fs-body); line-height: var(--vi-lh-body); animation: vi-sheet-in var(--duration-base) var(--ease-standard); transition: transform var(--duration-quick) var(--ease-standard), max-height var(--duration-base) var(--ease-standard); }\\n.vi-fact--sheet.is-expanded { max-height: calc(100% - var(--space-7)); }\\n.vi-fact__grip { position: sticky; top: 0; display: flex; justify-content: center; margin: 0 calc(var(--space-4) * -1); background: var(--surface-overlay); touch-action: none; cursor: grab; z-index: 1; }\\n.vi-fact__handle { position: relative; width: 64px; height: 24px; border: 0; padding: 0; background: none; cursor: pointer; }\\n.vi-fact__handle::after { content: \\\"\\\"; position: absolute; left: 12px; right: 12px; top: 10px; height: 5px; border-radius: var(--radius-pill); background: var(--line-strong); }\\n.vi-fact--sheet .vi-fact__title { font-size: calc(24px * var(--vi-label-scale)); line-height: 1.15; padding-top: var(--space-1); }\\n.vi-fact--sheet .vi-fact__close { margin: 0 calc(var(--space-2) * -1) 0 0; }\\n.vi-fact--sheet .vi-fact__step { min-height: 44px; padding: 0 var(--space-3) 0 var(--space-4); font-size: var(--vi-fs-sm); }\\n.vi-fact--sheet .vi-fact__link { font-size: var(--vi-fs-sm); min-height: 44px; display: inline-flex; align-items: center; }\\n[data-motion=\\\"reduced\\\"] .vi-fact--sheet { animation: vi-fade 120ms; }\\n@media (prefers-reduced-motion: reduce) {\\n .vi-fact--sheet { animation: vi-fade 120ms; }\\n .vi-map.is-idle .vi-map__world { transition: none; }\\n}\\n.vi-map__trail { position: absolute; top: var(--space-4); left: var(--space-4); z-index: var(--z-chrome); }\\n.vi-map__ctrls { position: absolute; top: var(--space-4); right: var(--space-4); z-index: var(--z-chrome); }\\n[data-reveal=\\\"instant\\\"] .vi-map.is-reveal .vi-map__slot, [data-motion=\\\"reduced\\\"] .vi-map.is-reveal .vi-map__slot { animation: vi-fade var(--vi-reduced-fade, 120ms) backwards; animation-delay: 0ms !important; }\\n[data-reveal=\\\"instant\\\"] .vi-map.is-reveal .vi-edge, [data-reveal=\\\"instant\\\"] .vi-map.is-reveal .vi-edge__line, [data-motion=\\\"reduced\\\"] .vi-map.is-reveal .vi-edge, [data-motion=\\\"reduced\\\"] .vi-map.is-reveal .vi-edge__line { animation: none; stroke-dashoffset: 0; }\\n@media (prefers-reduced-motion: reduce) {\\n .vi-map.is-reveal .vi-map__slot { animation: vi-fade var(--vi-reduced-fade, 120ms) backwards; animation-delay: 0ms !important; }\\n .vi-map.is-reveal .vi-edge, .vi-map.is-reveal .vi-edge__line { animation: none; stroke-dashoffset: 0; }\\n}\\n[data-motion=\\\"reduced\\\"] :where([class^=\\\"vi-\\\"], [class*=\\\" vi-\\\"]), [data-motion=\\\"reduced\\\"] :where([class^=\\\"vi-\\\"], [class*=\\\" vi-\\\"])::before, [data-motion=\\\"reduced\\\"] :where([class^=\\\"vi-\\\"], [class*=\\\" vi-\\\"])::after { transition-duration: 1ms !important; }\\n.vi-fact__acts { flex-wrap: wrap; justify-content: flex-end; }\\n.vi-fact__link { display: inline-flex; align-items: center; gap: 2px; }\\n.vi-anchor { position: relative; display: inline; }\\n.vi-anchor.is-open .vi-term { background: var(--selection); border-radius: 3px; }\\n.vi-anchor__pop { position: absolute; left: -12px; top: calc(100% + 6px); z-index: var(--z-menu); display: block; width: max-content; }\\n.vi-anchor-card { position: relative; display: block; width: min(300px, calc(100vw - 32px)); box-sizing: border-box; padding: var(--space-3) var(--space-4) var(--space-3); background: var(--surface-overlay); color: var(--ink); text-align: left; white-space: normal; font: 400 var(--vi-fs-sm)/20px var(--font-ui); border: 2px solid var(--vi-fact-ring); border-radius: 12px 16px 10px 14px / 14px 10px 16px 12px; box-shadow: 4px 5px 0 0 var(--vi-fact-fill), 4px 5px 0 2px var(--vi-fact-ring), var(--shadow-pop); animation: vi-pop var(--duration-quick) var(--ease-standard); }\\n.vi-anchor-card.is-in-sheet { width: auto; border: 0; box-shadow: none; padding: 0; animation: none; background: transparent; }\\n[data-theme^=\\\"contrast\\\"] .vi-anchor-card { border-color: var(--ink); box-shadow: none; }\\n.vi-anchor-card__eyebrow { font: 400 11px/14px var(--font-display); letter-spacing: .14em; text-transform: uppercase; color: var(--ink-muted); }\\n.vi-anchor-card__word { font: 700 20px/24px var(--font-hand); color: var(--ink); margin: 2px 0 var(--space-1); }\\n.vi-fact--sheet .vi-anchor-card__word { font-size: calc(24px * var(--vi-label-scale)); line-height: 1.15; }\\n.vi-anchor-card__desc { margin: 0; color: var(--ink); }\\n.vi-anchor-card__acts { display: flex; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: var(--space-3); margin-top: var(--space-3); padding-top: var(--space-2); border-top: 1px dashed var(--line); }\\n.vi-fact--sheet .vi-anchor-card__acts .vi-fact__link { min-height: 44px; }\\n[data-type=\\\"readable\\\"] .vi-anchor-card__word { font-family: var(--font-ui); }\\n[data-motion=\\\"reduced\\\"] .vi-anchor-card { animation: vi-fade 120ms; }\\n@media (prefers-reduced-motion: reduce) {\\n .vi-anchor-card { animation: vi-fade 120ms; }\\n}\\n.vi-peek .vi-fact__foot { flex-wrap: wrap; row-gap: var(--space-2); }\\n.vi-peek .vi-fact__acts { margin-left: auto; }\\n.vi-map.has-highlight .vi-node.is-dimmed { opacity: .35; transition: opacity var(--duration-quick) var(--ease-standard); }\\n.vi-map.has-highlight .vi-node.is-selected .vi-node__body { stroke: var(--ink); }\\n.vi-map { container-type: inline-size; }\\n.vi-edge__hit { fill: none; stroke: transparent; stroke-width: 18; pointer-events: stroke; cursor: pointer; }\\n.vi-edge__hit:hover + .vi-edge__line { stroke-width: 3.5; }\\n.vi-edge.is-selected .vi-edge__line, .vi-edge.is-selected .vi-edge__arrow { stroke: var(--focus); stroke-width: 3.5; }\\n.vi-map__group-hit { fill: none; stroke: transparent; stroke-width: 16; pointer-events: stroke; cursor: pointer; }\\n.vi-map__group.is-selected rect:not(.vi-map__group-hit) { stroke: var(--focus); stroke-width: 2.5; stroke-dasharray: none; }\\n.vi-map__group-label.is-selected { border-color: var(--focus); color: var(--focus); box-shadow: 0 0 0 1px var(--focus); }\\n.vi-map { touch-action: pan-x pan-y; }\\n.vi-map.is-app { touch-action: none; }\\n.vi-map.is-pinching .vi-map__world { transition: none; }\\n.vi-map.is-instant.is-reveal .vi-map__slot { animation: vi-fade var(--vi-reduced-fade, 120ms) backwards; animation-delay: 0ms !important; }\\n.vi-map.is-instant.is-reveal .vi-edge, .vi-map.is-instant.is-reveal .vi-edge__line { animation: none; stroke-dashoffset: 0; }\\n.vi-map.is-instant .vi-node, .vi-map.is-instant .vi-node__rings { transition: none; }\\n.vi-map.is-detail-body .vi-node:not(.is-selected):not(:focus-visible):not(:hover) :is(.vi-node__rings, .vi-node__label), .vi-map.is-detail-speck .vi-node:not(.is-selected):not(:focus-visible):not(:hover) :is(.vi-node__rings, .vi-node__label) { display: none; }\\n.vi-map.is-detail-body .vi-node:not(.is-selected):not(:focus-visible):not(:hover) .vi-node__body, .vi-map.is-detail-speck .vi-node:not(.is-selected):not(:focus-visible):not(:hover) .vi-node__body, .vi-map.no-shadows .vi-node__body { filter: none; }\\n@keyframes vi-pop { from { opacity: 0; transform: translateY(-4px) scale(.98); } }\\n@keyframes vi-fade { from { opacity: 0; } }\\n@keyframes vi-bloom { from { opacity: 0; transform: translate(calc(-50% + var(--vi-dx)), calc(-50% + var(--vi-dy))) scale(var(--vi-bloom-from, .55)); } }\\n@keyframes vi-line { to { stroke-dashoffset: 0; } }\\n@keyframes vi-settle { from { transform: scale(var(--vi-settle-from, .94)); } }\\n@keyframes vi-sheet-in { from { transform: translateY(100%); } }\\n\";\nexport const SPEC_FONTS_URL = \"https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible+Next:ital,wght@0,200..800;1,200..800&family=Atkinson+Hyperlegible+Mono:wght@400;600&family=Kalam:wght@400;700&display=swap\";\nexport const SPEC_DESIGN_SYSTEM_VERSION = \"0.2.1\";\n/** Font files shipped with the package (fonts/ directory), from design-system/fonts/fonts.css. */\nexport const SPEC_BUNDLED_FONTS = [\n {\n \"family\": \"Caveat\",\n \"file\": \"Caveat-Variable.ttf\",\n \"weight\": \"400 700\"\n }\n] as const;\n","// ─── KonvaNodeLayer ───────────────────────────────────────────────────────────\n//\n// One Konva <Shape> paints every visible idea. Culling uses the stage's live\n// transform at draw time (so panning, which moves the stage directly without\n// React state, never shows blank areas) and the idea's centred visual bounds\n// (RBush above 200 ideas). Hit testing stays outside Konva (stage-level RBush).\n\nimport React, { useRef, useLayoutEffect, useMemo } from 'react';\nimport { KLayer as Layer, KShape as Shape } from '../konvaCompat';\nimport type Konva from 'konva';\nimport { CANVAS_STYLE, RBushSpatialIndex, layerBlooms, shadowsShown, intersectsViewport, nodeBounds, type FlatNode } from '@visualli/core';\nimport { useNodeStore } from '../stores/useNodeStore';\nimport { DEFAULT_DESIGN, type Design } from '../design/design';\nimport { useFontsEpoch } from '../design/runtime';\nimport { IDLE, drawIdea, type IdeaState } from '../design/drawing';\nimport { HoverTweens, type RevealClock, type Arrival } from '../design/choreography';\nimport { useFrames } from './useFrames';\n\nconst SPATIAL_INDEX_THRESHOLD = 200;\nexport interface KonvaNodeLayerProps {\n nodes?: FlatNode[];\n isTransitioning?: boolean;\n isDragging?: boolean;\n hoveredNodeId?: string | null;\n pressedNodeId?: string | null;\n selectedNodeId?: string | null;\n /** Idea with keyboard focus (accessible layer). */\n focusedNodeId?: string | null;\n design?: Design;\n /** The layer's arrival timeline (bloom). Omit for no arrival animation. */\n clock?: RevealClock;\n /** Touch layout (`.vi-map.is-touch`): the other ideas fade while one is peeked. */\n touch?: boolean;\n /** Idea whose peek (sheet) is open on touch. */\n peekedNodeId?: string | null;\n}\n\n/** World-space rectangle currently visible in the stage. */\nexport function stageViewRect(stage: Konva.Stage) {\n const s = stage.scaleX() || 1;\n return { minX: -stage.x() / s, minY: -stage.y() / s, maxX: (stage.width() - stage.x()) / s, maxY: (stage.height() - stage.y()) / s };\n}\n\nexport default function KonvaNodeLayer({\n nodes: propNodes,\n isDragging = false,\n hoveredNodeId = null,\n pressedNodeId = null,\n selectedNodeId = null,\n focusedNodeId = null,\n design = DEFAULT_DESIGN,\n clock,\n touch = false,\n peekedNodeId = null,\n}: KonvaNodeLayerProps) {\n const layerRef = useRef<Konva.Layer | null>(null);\n const fonts = useFontsEpoch();\n const storeNodes = useNodeStore((s) => s.nodes);\n const nodes: FlatNode[] = useMemo(() => propNodes ?? Array.from(storeNodes.values()), [propNodes, storeNodes]);\n\n // Spatial index over visual bounds. Rebuilt only when the node set changes; while dragging we draw everything.\n const index = useMemo(() => {\n if (nodes.length < SPATIAL_INDEX_THRESHOLD || isDragging) return null;\n const idx = new RBushSpatialIndex();\n idx.bulkLoad(nodes.map((n) => ({ nodeId: n.id, bounds: nodeBounds(n) })));\n return idx;\n }, [nodes, isDragging]);\n const byId = useMemo(() => (index ? new Map(nodes.map((n) => [n.id, n])) : null), [index, nodes]);\n\n // While an idea is peeked the others are dimmed (`.vi-node.is-dimmed`): unchanged by default, faded in the focus\n // themes and on touch — the design system's opacities (CANVAS_STYLE from css/spec.css).\n const highlighted = hoveredNodeId ?? peekedNodeId ?? selectedNodeId;\n const N = CANVAS_STYLE.node;\n const focusTheme = design.theme.startsWith('focus');\n const dimOpacity = focusTheme ? (touch ? N.dimmedOpacityFocusTouch : N.dimmedOpacityFocus) : touch ? N.dimmedOpacityTouch : N.dimmedOpacity;\n const dimOthers = highlighted !== null && dimOpacity !== 1;\n\n // Hover / press / select: the design system's lift and ring turn, tweened rather than snapped.\n const tweens = useRef(new HoverTweens()).current;\n const frames = useFrames(layerRef, () => clock?.active() || tweens.active());\n useLayoutEffect(() => {\n const raised = new Set<string>();\n if (hoveredNodeId) raised.add(hoveredNodeId);\n if (pressedNodeId) raised.add(pressedNodeId);\n if (selectedNodeId) raised.add(selectedNodeId);\n if (tweens.set(raised, design.comfort.reducedMotion || !layerBlooms(nodes.length))) frames.run();\n }, [hoveredNodeId, pressedNodeId, selectedNodeId, design.comfort.reducedMotion, layerBlooms(nodes.length), tweens, frames]); // eslint-disable-line react-hooks/exhaustive-deps\n useLayoutEffect(() => clock?.subscribe(() => frames.run()), [clock, frames]);\n\n useLayoutEffect(() => { layerRef.current?.batchDraw(); }, [nodes, index, design, fonts, hoveredNodeId, pressedNodeId, selectedNodeId, focusedNodeId, isDragging, touch, peekedNodeId]);\n\n const sceneFunc = (ctx: { _context: CanvasRenderingContext2D }, shape: Konva.Shape) => {\n const stage = shape.getStage();\n if (!stage) return;\n const zoom = stage.scaleX() || 1;\n const view = stageViewRect(stage);\n let visible: FlatNode[];\n if (isDragging) visible = nodes;\n else if (index && byId) visible = index.query(view).map((id) => byId.get(id)!).filter(Boolean);\n else visible = nodes.filter((n) => intersectsViewport(n, view));\n\n const c = ctx._context;\n const m = c.getTransform();\n const opt = { shadows: !isDragging && shadowsShown(visible.length), k: Math.hypot(m.a, m.b), base: m, dimOpacity };\n const st: IdeaState = { ...IDLE };\n const now = performance.now();\n const arrival: Arrival = { alpha: 1, scale: 1, dx: 0, dy: 0 };\n const arriving = clock?.active(now) ?? false;\n for (let i = 0; i < visible.length; i++) {\n const n = visible[i]!;\n st.hovered = n.id === hoveredNodeId;\n st.pressed = n.id === pressedNodeId;\n st.selected = n.id === selectedNodeId;\n st.focused = n.id === focusedNodeId;\n st.dimmed = dimOthers && n.id !== highlighted;\n if (tweens.has(n.id)) { const p = tweens.progress(n.id, now); st.lift = p.lift; st.ring = p.ring; } else { st.lift = undefined; st.ring = undefined; }\n st.arrival = arriving && clock!.node(n.id, n.x, n.y, now, arrival) ? arrival : null;\n drawIdea(c, n, design, zoom, st, opt);\n }\n c.setTransform(m);\n c.globalAlpha = 1;\n };\n\n return (\n <Layer ref={layerRef} name=\"nodes\" listening={false}>\n <Shape sceneFunc={sceneFunc} listening={false} perfectDrawEnabled={false} />\n </Layer>\n );\n}\n","// ─── Design object ───────────────────────────────────────────────────────────\n//\n// Everything the canvas needs for one theme + comfort combination, resolved\n// once from the design-system tokens (no colour or font literals here).\n\nimport {\n CANVAS_STYLE,\n TYPE_STYLES,\n isContrastTheme,\n isDarkTheme,\n labelScale,\n metricsFor,\n resolveComfort,\n resolveTheme,\n type Comfort,\n type Metrics,\n type ResolvedComfort,\n type ThemeInput,\n type ThemeName,\n TOKENS,\n} from '@visualli/core';\n\nexport interface NodeShadow { x: number; y: number; blur: number; color: string }\n\nexport interface Design {\n theme: ThemeName;\n comfort: ResolvedComfort;\n tokens: Readonly<Record<string, string>>;\n metrics: Metrics;\n isDark: boolean;\n /** CSS font stacks, already switched to the readable face when that comfort setting is on. */\n fontHand: string;\n fontNote: string;\n fontUi: string;\n /** Multiplier for label sizes (`--vi-label-scale`). */\n labelScale: number;\n /** Idea drop shadow for this theme; null when the theme turns it off (high contrast). */\n nodeShadow: NodeShadow | null;\n /** Attributes the spec CSS keys off; put them on the renderer's root element. */\n attrs: Record<string, string>;\n /** Canvas weight/size for connector labels (the readable face is smaller and bolder). */\n edgeLabel: { weight: number; size: number };\n}\n\n/** Parse a CSS shadow like `0 6px 14px rgba(…)` as written in the design-system CSS. */\nfunction parseShadow(css: string): NodeShadow | null {\n const m = /^(-?[\\d.]+)(?:px)?\\s+(-?[\\d.]+)(?:px)?\\s+([\\d.]+)(?:px)?\\s+(.+)$/.exec(css.trim());\n return m ? { x: +m[1]!, y: +m[2]!, blur: +m[3]!, color: m[4]!.trim() } : null;\n}\n\nconst cache = new Map<string, Design>();\n\nexport function makeDesign(theme: ThemeName, comfortIn: ResolvedComfort): Design {\n const key = `${theme}|${+comfortIn.readableType}${+comfortIn.largerText}${+comfortIn.reducedMotion}`;\n const hit = cache.get(key);\n if (hit) return hit;\n\n const tokens = TOKENS[theme];\n const ui = tokens['font-ui']!;\n const d: Design = {\n theme,\n comfort: comfortIn,\n tokens,\n metrics: metricsFor(comfortIn),\n isDark: isDarkTheme(theme),\n fontHand: comfortIn.readableType ? ui : tokens['font-hand']!,\n fontNote: comfortIn.readableType ? ui : tokens['font-note']!,\n fontUi: ui,\n labelScale: labelScale(comfortIn),\n nodeShadow: isContrastTheme(theme) ? null : parseShadow(isDarkTheme(theme) ? CANVAS_STYLE.node.shadowDark : CANVAS_STYLE.node.shadowLight),\n attrs: {\n 'data-theme': theme,\n ...(comfortIn.readableType ? { 'data-type': 'readable' } : {}),\n ...(comfortIn.largerText ? { 'data-scale': 'lg' } : {}),\n ...(comfortIn.reducedMotion ? { 'data-motion': 'reduced' } : {}),\n },\n edgeLabel: comfortIn.readableType ? { weight: CANVAS_STYLE.edge.readableLabelWeight, size: CANVAS_STYLE.edge.readableLabelSize } : { weight: CANVAS_STYLE.edge.labelWeight, size: CANVAS_STYLE.edge.labelSize },\n };\n cache.set(key, d);\n return d;\n}\n\n/** Canvas font shorthand for an idea label at its natural (unscaled) size. */\nexport function ideaFont(d: Design, px: number): string {\n const weight = TYPE_STYLES['node-label'].weight;\n return `${weight} ${px}px ${d.fontHand}`;\n}\n\nexport const DEFAULT_DESIGN: Design = makeDesign('light', { readableType: false, largerText: false, reducedMotion: false });\n\nexport interface DesignProps {\n /**\n * One of the 8 design-system themes ('light', 'dark', 'focus-light', 'focus-dark',\n * 'colorsafe-light', 'colorsafe-dark', 'contrast-light', 'contrast-dark'), a family\n * ('focus' | 'colorsafe' | 'contrast') or 'auto' (follow the reader's colour scheme).\n */\n theme?: ThemeInput;\n /** @deprecated use `theme`. Kept for one release: true -> 'dark', false -> 'light'. */\n isDark?: boolean;\n /** Readable type, larger text, reduced motion. */\n comfort?: Comfort;\n /** Switch to the matching high-contrast theme under forced-colors (Windows high contrast etc.). Default true. */\n respectForcedColors?: boolean;\n}\n\n/** Resolve props + reader environment (colour scheme, forced colours, reduced motion) to a Design. */\nexport function resolveDesign(props: DesignProps, env: { prefersDark: boolean; forcedColors: boolean; prefersReducedMotion: boolean }): Design {\n const input: ThemeInput | undefined = props.theme ?? (props.isDark === undefined ? undefined : props.isDark ? 'dark' : 'light');\n let theme = resolveTheme(input, { prefersDark: env.prefersDark, forcedColors: env.forcedColors });\n // Forced colours override the reader's palette: honour that with the high-contrast theme of the same scheme.\n if (env.forcedColors && props.respectForcedColors !== false && !isContrastTheme(theme)) {\n theme = (isDarkTheme(theme) ? 'contrast-dark' : 'contrast-light') as ThemeName;\n }\n return makeDesign(theme, resolveComfort(props.comfort, { prefersReducedMotion: env.prefersReducedMotion }));\n}\n","// ─── Canvas drawing ──────────────────────────────────────────────────────────\n//\n// Draws ideas and connectors onto a native 2D context using the\n// design system's geometry and tokens. Konva owns the stage, layers, viewport\n// and layer transitions; these functions only paint.\n//\n// Performance notes:\n// - Outlines are cached as Path2D per (shape, rx, ry): built once, reused every frame.\n// - Label line breaks are cached per (font epoch, font, width, text).\n// - No allocations on the per-idea hot path except the label array on a cache miss.\n\nimport {\n CANVAS_STYLE,\n IDEA,\n ideaDetail,\n TYPE_STYLES,\n blobPath,\n ideaStyle,\n labelGrowth,\n nodeRadii,\n ringsFor,\n shapeOfLevel,\n type ConnectorGeometry,\n type FlatNode,\n} from '@visualli/core';\nimport type { Design } from './design';\nimport { fontsEpoch } from './runtime';\nimport type { Arrival, EdgeArrival } from './choreography';\n\nconst DEG = Math.PI / 180;\n\n// ── Path2D cache ──────────────────────────────────────────────────────────────\n\nconst MAX_CACHED_PATHS = 4096;\nconst pathCache = new Map<string, Path2D>();\n\n/** Outline of a blob centred on the origin, as a cached Path2D (SVG path data from the design system). */\nexport function blobPath2D(shape: number, rx: number, ry: number): Path2D {\n const key = `${shape}|${rx}|${ry}`;\n let p = pathCache.get(key);\n if (!p) {\n if (pathCache.size >= MAX_CACHED_PATHS) pathCache.delete(pathCache.keys().next().value as string);\n p = new Path2D(blobPath(shape, rx, ry));\n pathCache.set(key, p);\n }\n return p;\n}\n\n/** Test hook. */\nexport const _pathCacheSize = (): number => pathCache.size;\n\nconst NO_DASH: number[] = [];\nconst NO_RINGS: ReadonlyArray<never> = [];\nconst dashCache = new Map<string, number[]>();\nfunction dashOf(spec: string): number[] {\n if (!spec) return NO_DASH;\n let d = dashCache.get(spec);\n if (!d) { d = spec.split(/\\s+/).map(Number); dashCache.set(spec, d); }\n return d;\n}\n\n// ── Label layout ──────────────────────────────────────────────────────────────\n\nconst lineCache = new Map<string, string[]>();\nconst MAX_CACHED_LAYOUTS = 8192;\n\n/** Greedy word wrap at `maxWidth` (natural px), clamped to `maxLines` with an ellipsis (ideas pass Infinity: they are\n * sized to hold their whole label). */\nexport function layoutLabel(c: CanvasRenderingContext2D, text: string, font: string, maxWidth: number, maxLines: number = Infinity): string[] {\n const key = `${fontsEpoch()}|${font}|${maxWidth}|${text}`;\n const hit = lineCache.get(key);\n if (hit) return hit;\n c.font = font;\n const words = text.split(/\\s+/).filter(Boolean);\n const lines: string[] = [];\n let cur = '';\n const fit = (s: string) => c.measureText(s).width <= maxWidth;\n for (const w of words) {\n const next = cur ? `${cur} ${w}` : w;\n if (fit(next)) { cur = next; continue; }\n if (cur) lines.push(cur);\n // A single word wider than the box is broken by characters.\n let rest = w;\n while (!fit(rest) && rest.length > 1) {\n let n = rest.length - 1;\n while (n > 1 && !fit(rest.slice(0, n))) n--;\n lines.push(rest.slice(0, n));\n rest = rest.slice(n);\n }\n cur = rest;\n }\n if (cur) lines.push(cur);\n if (lines.length > maxLines) {\n lines.length = maxLines;\n let last = lines[maxLines - 1]! + '…';\n while (last.length > 1 && !fit(last)) last = last.slice(0, -2) + '…';\n lines[maxLines - 1] = last;\n }\n if (lineCache.size >= MAX_CACHED_LAYOUTS) lineCache.clear();\n lineCache.set(key, lines);\n return lines;\n}\n\n// ── Ideas ─────────────────────────────────────────────────────────────────────\n\nexport interface IdeaState {\n hovered: boolean;\n pressed: boolean;\n selected: boolean;\n /** Keyboard focus (the accessible layer is focused on this idea). */\n focused: boolean;\n dimmed: boolean;\n /** Hover/select progress (0 at rest, 1 raised) from the choreography; defaults to the boolean state when omitted. */\n lift?: number;\n ring?: number;\n /** Arrival look mid-reveal (bloom); null/omitted once arrived. */\n arrival?: Arrival | null;\n}\nexport const IDLE: IdeaState = { hovered: false, pressed: false, selected: false, focused: false, dimmed: false };\n\nexport interface IdeaOptions {\n /** Drop shadows are skipped for big maps / while dragging. */\n shadows: boolean;\n /** Device pixels per world unit (canvas shadows are in device space). Computed once per frame by the caller; derived from the transform when omitted. */\n k?: number;\n /** Opacity of a dimmed idea (the design system's `.vi-node.is-dimmed` for the theme and layout); default the focus themes'. */\n dimOpacity?: number;\n /** The context's transform at the start of the frame. When given, ideas are placed with setTransform (no save/restore); the caller must restore it afterwards. */\n base?: DOMMatrix;\n}\n\n/** Fill + ring an idea is drawn with in `d`'s theme: its topic's, or its custom colour as given (the design system's colour rule). */\nexport const ideaColors = (d: Design, n: Pick<FlatNode, 'topic' | 'custom'>) => ideaStyle(d.theme, n);\n\n/** An idea's label size in natural px: the design system's size for its kind × the comfort label scale. */\nexport const ideaLabelPx = (n: Pick<FlatNode, 'kind'>, d: Design): number => IDEA.labelSize[n.kind ?? 'node'] * d.labelScale;\n\n/**\n * Paint one idea (rings, body, label) centred on node.x / node.y.\n *\n * With `opt.base` (the context's transform at the start of the frame) the idea is\n * positioned with a single setTransform and no save/restore: the caller restores\n * the base transform after the last idea. Without it, state is saved and restored.\n */\nexport function drawIdea(c: CanvasRenderingContext2D, node: FlatNode, d: Design, zoom: number, st: IdeaState, opt: IdeaOptions): void {\n const { rx, ry } = nodeRadii(node);\n const { fill, ring } = ideaColors(d, node);\n const screenW = node.width * zoom;\n const base = opt.base;\n\n // Specks: one filled box, no transform changes.\n // Level of detail (geometry/detail.ts): a speck below DETAIL.speckBelow, body only below DETAIL.bodyOnlyBelow.\n const detail = ideaDetail(screenW, st.selected || st.focused || st.hovered);\n if (detail === 'speck') {\n const a = (st.dimmed ? opt.dimOpacity ?? CANVAS_STYLE.node.dimmedOpacityFocus : 1) * (st.arrival ? st.arrival.alpha : 1);\n if (a !== 1) c.globalAlpha = a;\n c.fillStyle = fill;\n c.fillRect(node.x - rx, node.y - ry, rx * 2, ry * 2);\n if (a !== 1) c.globalAlpha = 1;\n return;\n }\n\n const detailed = detail === 'full';\n const shape = shapeOfLevel(node.level);\n const rings = detailed ? ringsFor(node.branchCount) : NO_RINGS;\n const raised = st.hovered || st.pressed || st.selected;\n const lift = st.lift ?? (raised ? 1 : 0);\n const ringT = st.ring ?? (raised ? 1 : 0);\n const arr = st.arrival;\n const y = node.y + lift * CANVAS_STYLE.node.hoverLift + (arr ? arr.dy : 0);\n const x = node.x + (arr ? arr.dx : 0);\n let k = opt.k;\n if (k === undefined) { const m = c.getTransform(); k = Math.hypot(m.a, m.b); } // device px per world unit\n\n if (base) c.setTransform(base.a, base.b, base.c, base.d, base.e + base.a * x + base.c * y, base.f + base.b * x + base.d * y);\n else { c.save(); c.translate(x, y); }\n if (arr) c.scale(arr.scale, arr.scale);\n c.lineJoin = 'round';\n const baseAlpha = (st.dimmed ? opt.dimOpacity ?? CANVAS_STYLE.node.dimmedOpacityFocus : 1) * (arr ? arr.alpha : 1);\n c.globalAlpha = baseAlpha;\n\n // Rings, outermost first so the inner ones sit on top.\n if (rings.length) {\n const ringSpin = ringT * CANVAS_STYLE.node.hoverRingsRotate;\n const ringGrow = 1 + ringT * (CANVAS_STYLE.node.hoverRingsScale - 1);\n c.fillStyle = fill;\n c.strokeStyle = ring;\n let dashed = false;\n for (let i = rings.length - 1; i >= 0; i--) {\n const r = rings[i]!;\n const angle = (r.rotate + ringSpin) * DEG;\n c.rotate(angle);\n c.globalAlpha = baseAlpha * r.opacity;\n const path = blobPath2D(shape, rx * r.scale * ringGrow, ry * r.scale * ringGrow);\n c.fill(path);\n c.lineWidth = r.width;\n if (r.dash) { c.setLineDash(dashOf(r.dash)); dashed = true; } else if (dashed) { c.setLineDash(NO_DASH); dashed = false; }\n c.stroke(path);\n c.rotate(-angle);\n }\n if (dashed) c.setLineDash(NO_DASH);\n c.globalAlpha = baseAlpha;\n }\n\n // Body.\n const body = blobPath2D(shape, rx, ry);\n c.fillStyle = fill;\n const shadow = detailed && opt.shadows ? d.nodeShadow : null;\n if (shadow) {\n c.shadowColor = shadow.color;\n c.shadowBlur = shadow.blur * k;\n c.shadowOffsetX = shadow.x * k;\n c.shadowOffsetY = shadow.y * k;\n }\n c.fill(body);\n if (shadow) { c.shadowColor = 'transparent'; c.shadowBlur = 0; c.shadowOffsetX = 0; c.shadowOffsetY = 0; }\n c.strokeStyle = st.focused ? d.tokens['focus']! : st.selected ? d.tokens['ink']! : ring;\n c.lineWidth = st.selected || st.focused ? CANVAS_STYLE.node.selectedStrokeWidth : d.metrics.nodeStroke;\n c.stroke(body);\n\n // Label.\n // Label: the whole label (the idea is sized for it, idea.ts), growing up to LABEL_GROWTH.idea when zoomed out.\n if (detailed && node.title) {\n const px = ideaLabelPx(node, d);\n const font = `${TYPE_STYLES['node-label'].weight} ${px}px ${d.fontHand}`;\n const lines = layoutLabel(c, node.title, font, node.width - IDEA.labelInset);\n const s = labelGrowth(zoom).idea;\n const lh = px * IDEA.labelLineHeight;\n c.scale(s, s);\n c.font = font;\n c.fillStyle = d.tokens['node-ink']!;\n c.textAlign = 'center';\n c.textBaseline = 'middle';\n if (d.comfort.readableType && 'letterSpacing' in c) (c as unknown as { letterSpacing: string }).letterSpacing = `${(px * 0.02).toFixed(2)}px`;\n const y0 = -((lines.length - 1) * lh) / 2;\n for (let i = 0; i < lines.length; i++) c.fillText(lines[i]!, 0, y0 + i * lh);\n }\n if (base) c.globalAlpha = 1; else c.restore();\n}\n\n// ── Connectors ────────────────────────────────────────────────────────────────\n\nexport interface PreparedConnector extends ConnectorGeometry {\n path: Path2D;\n arrowPath: Path2D;\n /** Length of the curve in world units (for drawing it from source to target). */\n len: number;\n}\n\n/** Length of the connector's cubic (\"M x y C x y x y x y\"), by sampling. */\nfunction cubicLength(d: string): number {\n const v = d.match(/-?\\d+(?:\\.\\d+)?/g)?.map(Number);\n if (!v || v.length < 8) return 0;\n const [x0, y0, x1, y1, x2, y2, x3, y3] = v as [number, number, number, number, number, number, number, number];\n let len = 0, px = x0, py = y0;\n for (let i = 1; i <= 16; i++) {\n const t = i / 16, u = 1 - t;\n const x = u * u * u * x0 + 3 * u * u * t * x1 + 3 * u * t * t * x2 + t * t * t * x3;\n const y = u * u * u * y0 + 3 * u * u * t * y1 + 3 * u * t * t * y2 + t * t * t * y3;\n len += Math.hypot(x - px, y - py); px = x; py = y;\n }\n return len;\n}\n\nexport function prepareConnector(g: ConnectorGeometry): PreparedConnector {\n return { ...g, path: new Path2D(g.d), arrowPath: new Path2D(g.arrow), len: cubicLength(g.d) };\n}\n\n/** Connectors shorter than this on screen, and labels smaller than LABEL_MIN_SCREEN_PX, are invisible: skipped. */\nconst CONNECTOR_MIN_SCREEN_PX = 3;\nconst LABEL_MIN_SCREEN_PX = 6;\n\nexport function drawConnector(c: CanvasRenderingContext2D, g: PreparedConnector, d: Design, zoom: number, dashed: boolean, label: string | undefined, arrival?: EdgeArrival | null): void {\n if (Math.hypot(g.b.x - g.a.x, g.b.y - g.a.y) * zoom < CONNECTOR_MIN_SCREEN_PX) return;\n c.save();\n if (arrival) c.globalAlpha = arrival.alpha;\n c.strokeStyle = d.tokens['edge']!;\n c.lineWidth = d.metrics.edgeWidth;\n c.lineCap = 'round';\n c.lineJoin = 'round';\n if (dashed) c.setLineDash([...CANVAS_STYLE.edge.dash]);\n else if (arrival && arrival.draw < 1) c.setLineDash([g.len * arrival.draw, g.len * 2]); // draws from source to target\n if (!(arrival && arrival.draw <= 0.001)) c.stroke(g.path);\n c.setLineDash([]);\n c.stroke(g.arrowPath);\n\n // The design system's connector label (`.vi-edge__label`), growing up to LABEL_GROWTH.connector when zoomed out (`--vi-inv`); the readable face is smaller and bolder.\n const labelPx = label ? d.edgeLabel.size * labelGrowth(zoom).connector : 0;\n if (label && labelPx * zoom >= LABEL_MIN_SCREEN_PX) {\n const px = labelPx;\n c.font = `${d.edgeLabel.weight} ${px}px ${d.fontNote}`;\n c.textAlign = 'center';\n c.textBaseline = 'middle';\n // paint-order: stroke — a halo in the canvas colour keeps the label legible over the line.\n c.lineWidth = CANVAS_STYLE.edge.labelHaloWidth;\n c.strokeStyle = d.tokens['canvas']!;\n c.strokeText(label, g.mid.x, g.mid.y);\n c.fillStyle = d.tokens['edge-label']!;\n c.fillText(label, g.mid.x, g.mid.y);\n }\n c.restore();\n}\n\n","// ─── useFrames ───────────────────────────────────────────────────────────────\n//\n// Redraws a Konva layer every animation frame for as long as `busy()` says an\n// animation is running. Nothing runs while the map is at rest. `run()` draws at\n// once (sharing the frame with any draw already queued, so a state change plus an\n// animation start still paints once) and keeps drawing each frame while busy.\n\nimport { useEffect, useMemo, useRef, type RefObject } from 'react';\nimport type Konva from 'konva';\n\nexport function useFrames(layerRef: RefObject<Konva.Layer | null>, busy: () => boolean): { run: () => void } {\n const raf = useRef<number | null>(null);\n const busyRef = useRef(busy);\n busyRef.current = busy;\n useEffect(() => () => { if (raf.current !== null) cancelAnimationFrame(raf.current); raf.current = null; }, []);\n return useMemo(() => {\n const tick = () => {\n raf.current = null;\n if (!busyRef.current()) return;\n layerRef.current?.batchDraw();\n raf.current = requestAnimationFrame(tick);\n };\n return {\n run: () => {\n layerRef.current?.batchDraw();\n if (raf.current === null) raf.current = requestAnimationFrame(tick);\n },\n };\n }, [layerRef]);\n}\n","// ─── KonvaEdgeLayer ───────────────────────────────────────────────────────────\n//\n// One Konva <Shape> paints every visible connector. Geometry (endpoints, cubic\n// curve, arrowhead) comes from the design system via connectorGeometry and is\n// cached per connector until one of its two ideas moves or resizes.\n\nimport React, { useRef, useLayoutEffect, useMemo } from 'react';\nimport { KLayer as Layer, KShape as Shape } from '../konvaCompat';\nimport type Konva from 'konva';\nimport { connectorGeometry, type FlatNode, type MindMapConnection } from '@visualli/core';\nimport { useNodeStore } from '../stores/useNodeStore';\nimport { DEFAULT_DESIGN, type Design } from '../design/design';\nimport { useFontsEpoch } from '../design/runtime';\nimport { drawConnector, prepareConnector, type PreparedConnector } from '../design/drawing';\nimport { stageViewRect } from './KonvaNodeLayer';\nimport type { RevealClock, EdgeArrival } from '../design/choreography';\nimport { useFrames } from './useFrames';\n\nexport interface KonvaEdgeLayerProps {\n nodes: FlatNode[];\n connections: MindMapConnection[];\n currentLevel?: number;\n /** @deprecated pass `design`; kept so existing callers still compile. */\n isDark?: boolean;\n /** Pass true while an idea is being dragged (connectors are always drawn then). */\n isDragging?: boolean;\n design?: Design;\n /** The layer's arrival timeline (connectors draw in after the ideas). Omit for no arrival animation. */\n clock?: RevealClock;\n}\n\nconst key = (n: FlatNode) => `${n.x},${n.y},${n.width},${n.level},${n.branchCount ?? 0}`;\nconst MARGIN = 80; // bow + arrowhead + label slack around the endpoints' box\n\nexport default function KonvaEdgeLayer({ connections, isDragging = false, design = DEFAULT_DESIGN, clock }: KonvaEdgeLayerProps) {\n const layerRef = useRef<Konva.Layer | null>(null);\n const fonts = useFontsEpoch();\n // Live positions: connectors follow dragged ideas.\n const storeNodes = useNodeStore((s) => s.nodes);\n const cache = useRef(new Map<string, { k: string; g: PreparedConnector }>());\n\n const edges = useMemo(() => {\n const out: Array<{ g: PreparedConnector; dashed: boolean; label?: string }> = [];\n const seen = new Set<string>();\n connections.forEach((conn, i) => {\n const src = storeNodes.get(conn.from);\n const tgt = storeNodes.get(conn.to);\n if (!src || !tgt) return;\n const id = `${conn.from}>${conn.to}#${i}`;\n seen.add(id);\n const k = `${key(src)}|${key(tgt)}`;\n let hit = cache.current.get(id);\n if (!hit || hit.k !== k) {\n hit = { k, g: prepareConnector(connectorGeometry(src, tgt, design.metrics.edgeGap)) };\n cache.current.set(id, hit);\n }\n out.push({ g: hit.g, dashed: conn.style === 'dashed', label: conn.label });\n });\n for (const id of cache.current.keys()) if (!seen.has(id)) cache.current.delete(id);\n return out;\n }, [connections, storeNodes, design.metrics.edgeGap]);\n\n const frames = useFrames(layerRef, () => clock?.active() ?? false);\n useLayoutEffect(() => clock?.subscribe(() => frames.run()), [clock, frames]);\n\n useLayoutEffect(() => { layerRef.current?.batchDraw(); }, [edges, design, fonts, isDragging]);\n\n const sceneFunc = (ctx: { _context: CanvasRenderingContext2D }, shape: Konva.Shape) => {\n const stage = shape.getStage();\n if (!stage) return;\n const zoom = stage.scaleX() || 1;\n const v = stageViewRect(stage);\n const c = ctx._context;\n const now = performance.now();\n const arriving = clock?.active(now) ?? false;\n const arrival: EdgeArrival = { alpha: 1, draw: 1 };\n for (let i = 0; i < edges.length; i++) {\n const e = edges[i]!;\n const { a, b, mid } = e.g;\n const minX = Math.min(a.x, b.x, mid.x) - MARGIN, maxX = Math.max(a.x, b.x, mid.x) + MARGIN;\n const minY = Math.min(a.y, b.y, mid.y) - MARGIN, maxY = Math.max(a.y, b.y, mid.y) + MARGIN;\n if (maxX < v.minX || minX > v.maxX || maxY < v.minY || minY > v.maxY) continue;\n drawConnector(c, e.g, design, zoom, e.dashed, e.label, arriving && clock!.edge(i, e.dashed, now, arrival) ? arrival : null);\n }\n };\n\n return (\n <Layer ref={layerRef} listening={false}>\n <Shape sceneFunc={sceneFunc} listening={false} perfectDrawEnabled={false} />\n </Layer>\n );\n}\n","// ─── KonvaContainerLayer ─────────────────────────────────────────────────────\n//\n// Container hulls (the design system's dashed hull, geometry/container.ts),\n// beneath connectors and ideas (non-interactive). Their names are painted above\n// the ideas by KonvaContainerLabelLayer from the same layout. Member positions\n// come from the live node store so hulls follow dragged ideas.\n\nimport React, { useRef, useLayoutEffect, useMemo } from 'react';\nimport { KLayer as Layer, KShape as Shape } from '../konvaCompat';\nimport type Konva from 'konva';\nimport type { FlatNode } from '@visualli/core';\nimport { useNodeStore } from '../stores/useNodeStore';\nimport { DEFAULT_DESIGN, type Design } from '../design/design';\nimport { useFontsEpoch } from '../design/runtime';\nimport { drawHull, layoutContainers, type ConnectionInput, type PlacedContainer } from '../design/containers';\n\nexport interface ContainerGroup {\n id: string;\n label?: string;\n nodeIds: string[];\n level: number;\n}\n\nexport interface KonvaContainerLayerProps {\n /** Layout-snapshot nodes (kept for API compatibility). */\n nodes: FlatNode[];\n containers: ContainerGroup[];\n /** The layer's connections: container names are placed clear of them. */\n connections?: ConnectionInput[];\n /** @deprecated pass `design`. */\n isDark?: boolean;\n design?: Design;\n}\n\n/** Hulls and name positions for the current layer, from the live node store (shared by both container layers). */\nexport function useContainerLayout(containers: ContainerGroup[], connections: ConnectionInput[] = [], design: Design = DEFAULT_DESIGN): PlacedContainer[] {\n const fonts = useFontsEpoch();\n const storeNodes = useNodeStore((s) => s.nodes);\n return useMemo(\n () => layoutContainers(containers, storeNodes, connections, design),\n // fonts: the names are measured, so measure again once the web fonts are in.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [containers, connections, storeNodes, design, fonts],\n );\n}\n\nexport default function KonvaContainerLayer({ containers, connections = [], design = DEFAULT_DESIGN }: KonvaContainerLayerProps) {\n const layerRef = useRef<Konva.Layer | null>(null);\n const placed = useContainerLayout(containers, connections, design);\n\n useLayoutEffect(() => { layerRef.current?.batchDraw(); }, [placed, design]);\n\n if (containers.length === 0) return null;\n\n return (\n <Layer ref={layerRef} listening={false}>\n <Shape\n listening={false}\n perfectDrawEnabled={false}\n sceneFunc={(ctx: { _context: CanvasRenderingContext2D }) => { for (const p of placed) drawHull(ctx._context, p.hull, design); }}\n />\n </Layer>\n );\n}\n","// ─── Containers ──────────────────────────────────────────────────────────────\n//\n// The design system's containers (geometry/container.ts, copied verbatim into\n// @visualli/core): a dashed hull around the member ideas (HULL.padX / HULL.padY\n// beyond their centres, more for large ideas: HULL_CLEAR) with HULL.radius corners, and the group's name as a pill straddling\n// the hull's edge. Where the pill goes is the design system's placeContainerLabel:\n// candidate spots along all four edges, scored against every idea on the layer\n// (with its outermost ring), every connector curve and the names placed before\n// it. The pill's look comes from .vi-map__group-label in css/spec.css\n// (CANVAS_STYLE.group). Hull and pill are painted by the two container layers.\n\nimport {\n CANVAS_STYLE,\n RINGS,\n connectorGeometry,\n connectorSamples,\n containerHull,\n labelGrowth,\n nodeRadii,\n placeContainerLabel,\n ringsFor,\n type FlatNode,\n type Hull,\n type LabelBox,\n type LabelSide,\n} from '@visualli/core';\nimport type { Design } from './design';\n\nconst PILL = CANVAS_STYLE.group;\n\nexport interface ContainerInput { id: string; label?: string; nodeIds: string[] }\nexport interface ConnectionInput { from: string; to: string }\n\nexport interface PlacedPill { text: string; x: number; y: number; side: LabelSide; w: number; h: number }\nexport interface PlacedContainer { id: string; hull: Hull; pill: PlacedPill | null }\n\n/** The pill's font at `px`: the note face (the UI face in readable type, via Design.fontNote). */\nexport const pillFont = (d: Design, px: number): string => `${PILL.labelWeight} ${px}px ${d.fontNote}`;\n\n\nlet measureCtx: CanvasRenderingContext2D | null = null;\nfunction measurer(): CanvasRenderingContext2D | null {\n if (!measureCtx && typeof document !== 'undefined') measureCtx = document.createElement('canvas').getContext('2d');\n return measureCtx;\n}\n\n/** The pill's box in world units for `text` (ellipsised past labelMaxWidth), with the text grown by `k`. */\nexport function measurePill(text: string, d: Design, k: number, c: CanvasRenderingContext2D | null = measurer()): PlacedPill {\n const px = PILL.labelSize * d.labelScale * k;\n const padX = PILL.labelPadding.x, border = PILL.labelBorderWidth;\n const room = PILL.labelMaxWidth - padX * 2 - border * 2;\n let shown = text, tw = text.length * px * 0.5;\n if (c) {\n c.font = pillFont(d, px);\n tw = c.measureText(text).width;\n if (tw > room) {\n // One-line ellipsis, like text-overflow: ellipsis.\n let lo = 0, hi = text.length;\n while (lo < hi) { const mid = (lo + hi + 1) >> 1; if (c.measureText(text.slice(0, mid).trimEnd() + '…').width <= room) lo = mid; else hi = mid - 1; }\n shown = text.slice(0, lo).trimEnd() + '…';\n tw = c.measureText(shown).width;\n }\n }\n return {\n text: shown, x: 0, y: 0, side: 'bottom',\n w: Math.min(PILL.labelMaxWidth, tw + padX * 2 + border * 2),\n h: px * PILL.labelLineHeight + PILL.labelPadding.top + PILL.labelPadding.bottom + border * 2,\n };\n}\n\n/** The box an idea occupies, its outermost ring included (what a container name must not cover). */\nfunction ideaBox(n: FlatNode): LabelBox {\n const { rx, ry } = nodeRadii(n);\n const rings = ringsFor(n.branchCount);\n const s = rings.length ? RINGS[rings.length - 1]!.scale : 1;\n return { x0: n.x - rx * s, x1: n.x + rx * s, y0: n.y - ry * s, y1: n.y + ry * s };\n}\n\n/**\n * Hulls and name positions for a layer's containers, in file order (each name\n * avoids the ones placed before it). Placement uses the names' size at 100%\n * (k = 1), so they don't hop while zooming; they follow ideas that are dragged.\n */\nexport function layoutContainers(\n containers: ReadonlyArray<ContainerInput>,\n nodes: ReadonlyMap<string, FlatNode>,\n connections: ReadonlyArray<ConnectionInput>,\n d: Design,\n): PlacedContainer[] {\n if (containers.length === 0) return [];\n const ideas: LabelBox[] = [];\n for (const n of nodes.values()) ideas.push(ideaBox(n));\n const lines = connections.flatMap((c) => {\n const a = nodes.get(c.from), b = nodes.get(c.to);\n if (!a || !b) return [];\n const g = connectorGeometry(a, b, d.metrics.edgeGap);\n return [connectorSamples(g.a, g.mid, g.b)];\n });\n const placed: LabelBox[] = [];\n const out: PlacedContainer[] = [];\n for (const c of containers) {\n const members = c.nodeIds.map((id) => nodes.get(id)).filter((n): n is FlatNode => !!n);\n const hull = containerHull(members.map((n) => ({ x: n.x, y: n.y, ...nodeRadii(n) })));\n if (!hull) continue;\n let pill: PlacedPill | null = null;\n if (c.label) {\n const size = measurePill(c.label, d, 1);\n const at = placeContainerLabel(hull, size, { ideas, connectors: lines, labels: placed });\n pill = { ...size, x: at.x, y: at.y, side: at.side };\n placed.push({ x0: at.x - size.w / 2, x1: at.x + size.w / 2, y0: at.y - size.h / 2, y1: at.y + size.h / 2 });\n }\n out.push({ id: c.id, hull, pill });\n }\n return out;\n}\n\n/** The dashed hull (beneath connectors and ideas). */\nexport function drawHull(c: CanvasRenderingContext2D, h: Hull, d: Design): void {\n c.save();\n c.strokeStyle = d.tokens['line-strong']!;\n c.lineWidth = PILL.strokeWidth;\n c.setLineDash([...PILL.dash]);\n c.beginPath();\n c.roundRect(h.x0, h.y0, h.x1 - h.x0, h.y1 - h.y0, h.radius);\n c.stroke();\n c.restore();\n}\n\n/** The name pill (above connectors and ideas), its text growing like idea labels when zoomed out (labelGrowth). */\nexport function drawPill(c: CanvasRenderingContext2D, p: PlacedPill, d: Design, zoom: number): void {\n const k = labelGrowth(zoom).idea;\n const size = k === 1 ? p : measurePill(p.text, d, k, c);\n const contrast = d.theme.startsWith('contrast');\n const bw = contrast ? PILL.contrastLabelBorderWidth : PILL.labelBorderWidth;\n c.save();\n c.beginPath();\n c.roundRect(p.x - size.w / 2 + bw / 2, p.y - size.h / 2 + bw / 2, size.w - bw, size.h - bw, (size.h - bw) / 2);\n c.fillStyle = d.tokens[PILL.labelFill]!;\n c.fill();\n c.lineWidth = bw;\n c.strokeStyle = d.tokens[contrast ? PILL.contrastLabelBorder : PILL.labelBorder]!;\n c.stroke();\n c.font = pillFont(d, PILL.labelSize * d.labelScale * k);\n c.fillStyle = d.tokens[PILL.labelInk]!;\n c.textAlign = 'center';\n c.textBaseline = 'middle';\n // Centre of the text box: the padding is uneven (top < bottom), so nudge by half the difference.\n c.fillText(size.text, p.x, p.y + (PILL.labelPadding.top - PILL.labelPadding.bottom) / 2);\n c.restore();\n}\n","// ─── KonvaContainerLabelLayer ────────────────────────────────────────────────\n//\n// Container names: pills straddling their hull's edge, at the spot the design\n// system's placeContainerLabel picks (clear of ideas, connectors and other\n// names). Painted above connectors and ideas so nothing runs over a name\n// (non-interactive). Shares its layout with KonvaContainerLayer.\n\nimport React, { useRef, useLayoutEffect } from 'react';\nimport { KLayer as Layer, KShape as Shape } from '../konvaCompat';\nimport type Konva from 'konva';\nimport { DEFAULT_DESIGN, type Design } from '../design/design';\nimport { drawPill, type ConnectionInput } from '../design/containers';\nimport { useContainerLayout, type ContainerGroup } from './KonvaContainerLayer';\n\nexport interface KonvaContainerLabelLayerProps {\n containers: ContainerGroup[];\n connections?: ConnectionInput[];\n design?: Design;\n}\n\nexport default function KonvaContainerLabelLayer({ containers, connections = [], design = DEFAULT_DESIGN }: KonvaContainerLabelLayerProps) {\n const layerRef = useRef<Konva.Layer | null>(null);\n const placed = useContainerLayout(containers, connections, design);\n\n useLayoutEffect(() => { layerRef.current?.batchDraw(); }, [placed, design]);\n\n if (!placed.some((p) => p.pill)) return null;\n\n return (\n <Layer ref={layerRef} listening={false}>\n <Shape\n listening={false}\n perfectDrawEnabled={false}\n sceneFunc={(ctx: { _context: CanvasRenderingContext2D }, shape: Konva.Shape) => {\n const zoom = shape.getStage()?.scaleX() || 1;\n for (const p of placed) if (p.pill) drawPill(ctx._context, p.pill, design, zoom);\n }}\n />\n </Layer>\n );\n}\n","// ─── NavigationStack ──────────────────────────────────────────────────────────\n//\n// The depth trail. Kept as a named component for existing callers; it renders\n// the design system's trail (DepthTrail) from layer entries.\n\nimport React, { memo, useMemo } from 'react';\nimport type { VisualliLayer } from '@visualli/core';\nimport { DepthTrail, type IdeaPaint } from './Overlays';\n\nexport interface NavStackEntry {\n layerId: string;\n layer: VisualliLayer;\n label: string;\n /** Colour of the idea this layer opens from (the design system's TRAIL: the clicked idea's own colour); the first\n * entry, the map's title, is TRAIL.rootTopic. */\n paint?: IdeaPaint;\n}\n\nexport interface NavigationStackProps {\n stack: NavStackEntry[];\n onNavigateBack: (index: number) => void;\n /** @deprecated theme comes from the surrounding data-theme. */\n isDark?: boolean;\n /** Override the trail's default offset from the top-left corner. */\n top?: string;\n left?: string;\n}\n\nconst NavigationStack = memo(function NavigationStack({ stack, onNavigateBack, top, left }: NavigationStackProps) {\n const entries = useMemo(\n () => stack.map((e) => ({ layerId: e.layerId, label: e.label, level: e.layer.level, paint: e.paint ?? {} })),\n [stack],\n );\n return (\n <div className=\"vi-map__trail\" style={top || left ? { top, left } : undefined}>\n <DepthTrail stack={entries} onNavigateBack={onNavigateBack} />\n </div>\n );\n});\n\nexport default NavigationStack;\n","// ─── Overlay chrome (DOM) ─────────────────────────────────────────────────────\n//\n// Peek, term cards, depth trail and canvas controls are plain DOM styled by the\n// design system's own CSS (.vi-fact, .vi-anchor-card, .vi-trail, .vi-ctrls,\n// .vi-iconbtn …). No colours or fonts are set here: topic colours reach the CSS\n// as the --topic-* custom properties of the active theme; a custom colour is used\n// as given (the design system's colour rule).\n\nimport React, { memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport { SHEET, TERM, TRAIL, VIEW, blobPath, hoverOpensTerm, shapeOfLevel, type FlatNode, type SemanticAnchor } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\n\n// ── Icons (stroke = currentColor) ─────────────────────────────────────────────\n\nconst Icon = ({ children, size = 20 }: { children: React.ReactNode; size?: number }) => (\n <svg className=\"vi-icon\" width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n {children}\n </svg>\n);\nconst MinusIcon = () => <Icon><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" /></Icon>;\nconst PlusIcon = () => <Icon><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" /><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" /></Icon>;\nconst FitIcon = () => <Icon><path d=\"M8 3H5a2 2 0 0 0-2 2v3\" /><path d=\"M21 8V5a2 2 0 0 0-2-2h-3\" /><path d=\"M3 16v3a2 2 0 0 0 2 2h3\" /><path d=\"M16 21h3a2 2 0 0 0 2-2v-3\" /></Icon>;\nconst ChevronLeftIcon = () => <Icon size={14}><polyline points=\"15 6 9 12 15 18\" /></Icon>;\nconst ChevronIcon = () => <Icon size={14}><polyline points=\"9 6 15 12 9 18\" /></Icon>;\nconst ExternalIcon = () => <Icon size={14}><path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" /><polyline points=\"15 3 21 3 21 9\" /><line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" /></Icon>;\nconst HomeIcon = () => <Icon size={TRAIL.homeIconSize}><path d=\"m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z\" /><polyline points=\"9 22 9 12 15 12 15 22\" /></Icon>;\nconst CloseIcon = () => <Icon size={18}><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" /><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" /></Icon>;\n\n// ── Canvas controls ───────────────────────────────────────────────────────────\n\nexport interface ZoomControlsProps {\n /** Re-fit the current layer into view. */\n onFit?: () => void;\n /** Touch layout: larger targets (the design system's `md` icon buttons). */\n touch?: boolean;\n /** @deprecated theme comes from the surrounding data-theme; kept so existing callers compile. */\n isDark?: boolean;\n}\n\nexport const ZoomControls = memo(function ZoomControls({ onFit, touch = false }: ZoomControlsProps) {\n const size = touch ? 'vi-iconbtn--md' : 'vi-iconbtn--sm';\n const zoom = useViewportStore((s) => s.zoomLevel);\n const setZoom = useViewportStore((s) => s.setZoom);\n // As the design system's canvas controls: zoom is shown relative to the layer's fit (fit = 100%), the store keeps\n // it within VIEW's limits, and Fit is disabled while the whole layer is already in view.\n const fitted = useViewportStore((s) => Math.abs(s.zoomLevel - s.fitScale) < 1e-6 && Math.abs(s.centerX - s.fitCenterX) < 0.5 && Math.abs(s.centerY - s.fitCenterY) < 0.5);\n const fit = useViewportStore((s) => s.fitScale);\n const zoomIn = useCallback(() => setZoom(zoom * VIEW.zoomStep), [zoom, setZoom]);\n const zoomOut = useCallback(() => setZoom(zoom / VIEW.zoomStep), [zoom, setZoom]);\n return (\n <div className=\"vi-ctrls\" role=\"toolbar\" aria-label=\"Canvas\" data-help=\"zoom-controls\">\n <button type=\"button\" className={`vi-iconbtn ${size}`} aria-label=\"Zoom out\" onClick={zoomOut}><MinusIcon /></button>\n <span className=\"vi-ctrls__pct\" aria-live=\"polite\">{Math.round((zoom / fit) * 100)}%</span>\n <button type=\"button\" className={`vi-iconbtn ${size}`} aria-label=\"Zoom in\" onClick={zoomIn}><PlusIcon /></button>\n {onFit && (<>\n <span className=\"vi-ctrls__div\" aria-hidden=\"true\" />\n <button type=\"button\" className={`vi-iconbtn ${size}`} aria-label=\"Fit map to view\" disabled={fitted} onClick={onFit}><FitIcon /></button>\n </>)}\n </div>\n );\n});\n\n// ── Depth trail ───────────────────────────────────────────────────────────────\n\n/** An idea's colour: its topic, or a custom colour drawn as given (FlatNode.topic / FlatNode.custom). */\nexport type IdeaPaint = Pick<FlatNode, 'topic' | 'custom'>;\n\n/** CSS fill + ring for an idea's colour, as the design system's topicColors: the active theme's topic properties, or\n * the custom colour with its darker ring (the `edge` token when it has none). */\nexport function paintVars(p: IdeaPaint): { fill: string; ring: string } {\n if (p.custom) return { fill: p.custom.fill, ring: p.custom.ring ?? 'var(--edge)' };\n const t = p.topic ?? TRAIL.rootTopic;\n return { fill: `var(--topic-${t})`, ring: `var(--topic-${t}-ring)` };\n}\n\n/** A depth trail entry: the idea stepped into (its title and colour); the first is the map (home glyph, its title as the accessible name). */\nexport interface TrailEntry { layerId: string; label: string; level: number; paint: IdeaPaint }\n\n/** The trail dot: the level's blob shape in the idea's colour (the design system's TRAIL). */\nconst TrailDot = ({ level, paint, current }: { level: number; paint: IdeaPaint; current: boolean }) => {\n const { fill, ring } = paintVars(paint);\n return (\n <svg width={TRAIL.dotBox} height={TRAIL.dotBox} viewBox={`${-TRAIL.dotBox / 2} ${-TRAIL.dotBox / 2} ${TRAIL.dotBox} ${TRAIL.dotBox}`} aria-hidden=\"true\">\n <path d={blobPath(shapeOfLevel(level), TRAIL.dotRadius, TRAIL.dotRadius)} fill={fill} stroke={ring} strokeWidth={current ? TRAIL.currentStroke : TRAIL.stroke} />\n </svg>\n );\n};\n\nexport interface DepthTrailProps { stack: TrailEntry[]; onNavigateBack: (index: number) => void }\n\nexport const DepthTrail = memo(function DepthTrail({ stack, onNavigateBack }: DepthTrailProps) {\n if (stack.length === 0) return null;\n const current = stack.length - 1;\n // The map's own entry: the home glyph only, its title as the accessible name and tooltip (the design system's TRAIL.rootLabel).\n const iconOnly = TRAIL.rootLabel === 'icon';\n return (\n <nav className=\"vi-trail\" aria-label=\"Depth trail\" data-help=\"navigation-stack\">\n <ol>\n {stack.map((e, i) => (\n <li key={`${e.layerId}-${i}`} className={i === current ? 'is-current' : undefined}>\n <button type=\"button\" disabled={i === current} aria-current={i === current ? 'location' : undefined} onClick={() => onNavigateBack(i)}\n {...(i === 0 && iconOnly ? { 'aria-label': e.label, title: e.label } : {})}>\n <TrailDot level={e.level} paint={e.paint} current={i === current} />\n <span>{i === 0 ? (iconOnly ? <HomeIcon /> : <><HomeIcon /> {e.label}</>) : e.label}</span>\n </button>\n </li>\n ))}\n </ol>\n </nav>\n );\n});\n\n// ── Terms (semantic anchors) ──────────────────────────────────────────────────\n\nconst escapeRe = (s: string) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/** Split `text` into plain runs and runs that match an anchor word (longest word wins, whole words only). */\nexport function splitTerms(text: string, anchors: ReadonlyArray<SemanticAnchor>): Array<string | SemanticAnchor> {\n const words = anchors.filter((a) => a.word).sort((a, b) => b.word.length - a.word.length);\n if (!words.length) return [text];\n const re = new RegExp(`(${words.map((a) => escapeRe(a.word)).join('|')})`, 'giu');\n const byWord = new Map(words.map((a) => [a.word.toLowerCase(), a]));\n const isWordChar = (ch: string | undefined) => !!ch && /[\\p{L}\\p{N}]/u.test(ch);\n const out: Array<string | SemanticAnchor> = [];\n let last = 0;\n for (const m of text.matchAll(re)) {\n const start = m.index!, end = start + m[0].length;\n // Whole words only (no lookbehind: it is not available in older Safari).\n if (isWordChar(text[start - 1]) || isWordChar(text[end])) continue;\n if (start > last) out.push(text.slice(last, start));\n out.push({ ...byWord.get(m[0].toLowerCase())!, word: m[0] });\n last = end;\n }\n if (last < text.length) out.push(text.slice(last));\n return out;\n}\n\nexport const TermCard = ({ anchor, inSheet = false }: { anchor: SemanticAnchor; inSheet?: boolean }) => (\n <span className={`vi-anchor-card${inSheet ? ' is-in-sheet' : ''}`} role=\"note\">\n <span className=\"vi-anchor-card__eyebrow\">Term</span>\n <span className=\"vi-anchor-card__word\" style={{ display: 'block' }}>{anchor.word}</span>\n <p className=\"vi-anchor-card__desc\">{anchor.description}</p>\n {anchor.knowMoreUrl && (\n <span className=\"vi-anchor-card__acts\">\n <a className=\"vi-fact__link\" href={anchor.knowMoreUrl} target=\"_blank\" rel=\"noopener noreferrer\">{TERM.learnMoreLabel} <ExternalIcon /></a>\n </span>\n )}\n </span>\n);\n\n// ── Term (semantic anchor) in a peek ─────────────────────────────────────────\n\n/**\n * An underlined term and its definition card, behaving as the design system's\n * `SemanticAnchor` (rules from geometry/interaction.ts → TERM): a mouse opens\n * it after TERM.hoverOpen and it closes TERM.hoverClose after the pointer leaves\n * the term and its card; a click, Enter or Space pins it (pressing again closes);\n * Escape closes it (without stepping out of the layer) and returns focus to the\n * term; a press outside closes it; opening by click / keyboard moves focus into\n * the card; the card stays TERM.viewportMargin inside the viewport.\n */\nexport function TermAnchor({ anchor }: { anchor: SemanticAnchor }) {\n const [open, setOpen] = useState(false);\n const [shift, setShift] = useState(0);\n const pinned = useRef(false);\n const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n const wrap = useRef<HTMLSpanElement>(null), btn = useRef<HTMLButtonElement>(null), card = useRef<HTMLSpanElement>(null);\n const show = (pin: boolean) => { clearTimeout(timer.current); if (pin) pinned.current = true; setOpen(true); };\n const hide = () => { clearTimeout(timer.current); pinned.current = false; setOpen(false); };\n useEffect(() => () => clearTimeout(timer.current), []);\n useLayoutEffect(() => { // keep the card inside the viewport\n if (!open || !card.current) { setShift(0); return; }\n const r = card.current.getBoundingClientRect(), vw = document.documentElement.clientWidth, m = TERM.viewportMargin;\n setShift(r.right > vw - m ? vw - m - r.right : r.left < m ? m - r.left : 0);\n }, [open]);\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') { e.stopPropagation(); hide(); btn.current?.focus(); } };\n const onPress = (e: PointerEvent) => { if (!wrap.current?.contains(e.target as Node)) hide(); };\n document.addEventListener('keydown', onKey, true);\n document.addEventListener('pointerdown', onPress, true);\n return () => { document.removeEventListener('keydown', onKey, true); document.removeEventListener('pointerdown', onPress, true); };\n }, [open]);\n return (\n <span\n ref={wrap}\n className={`vi-anchor${open ? ' is-open' : ''}`}\n data-semantic-tooltip=\"true\"\n onPointerEnter={(e) => { if (!hoverOpensTerm(e.pointerType)) return; clearTimeout(timer.current); timer.current = setTimeout(() => setOpen(true), TERM.hoverOpen); }}\n onPointerLeave={(e) => { if (!hoverOpensTerm(e.pointerType) || pinned.current) return; clearTimeout(timer.current); timer.current = setTimeout(() => setOpen(false), TERM.hoverClose); }}\n onBlur={(e) => { if (!wrap.current?.contains(e.relatedTarget as Node | null)) hide(); }}\n >\n <button\n ref={btn}\n type=\"button\"\n className=\"vi-term\"\n aria-expanded={open}\n onClick={() => {\n if (open && pinned.current) { hide(); return; }\n show(true);\n setTimeout(() => card.current?.querySelector<HTMLElement>('a, button')?.focus(), 0);\n }}\n >\n {anchor.word}\n </button>\n {open && <span ref={card} className=\"vi-anchor__pop\" style={shift ? { transform: `translateX(${shift}px)` } : undefined}><TermCard anchor={anchor} /></span>}\n </span>\n );\n}\n\n// ── Peek ─────────────────────────────────────────────────────────────────────\n\nexport interface PeekCardProps {\n node: FlatNode;\n anchors: ReadonlyArray<SemanticAnchor>;\n /** Present when the idea has a layer inside it. */\n onStepInside?: () => void;\n onClose?: () => void;\n /** Replaces the plain summary text (extension point kept from earlier versions). */\n renderContent?: (summary: string) => React.ReactNode;\n}\n\nexport const PeekCard = memo(function PeekCard({ node, anchors, onStepInside, onClose, renderContent }: PeekCardProps) {\n const parts = useMemo(() => splitTerms(node.description ?? '', anchors), [node.description, anchors]);\n const { fill, ring } = paintVars(node);\n const style = { ['--vi-fact-fill' as string]: fill, ['--vi-fact-ring' as string]: ring } as React.CSSProperties;\n return (\n <div className=\"vi-fact vi-peek\" style={style} role=\"dialog\" aria-label={node.title} data-node-tooltip=\"true\">\n <div className=\"vi-fact__head\">\n <div className=\"vi-fact__title\">{node.title}</div>\n {onClose && <button type=\"button\" className=\"vi-iconbtn vi-iconbtn--sm vi-fact__close\" aria-label=\"Close\" onClick={onClose}><CloseIcon /></button>}\n </div>\n <div className=\"vi-fact__body\">\n {renderContent ? renderContent(node.description ?? '') : parts.map((p, i) =>\n typeof p === 'string' ? <React.Fragment key={i}>{p}</React.Fragment> : (\n <TermAnchor key={i} anchor={p} />\n ))}\n </div>\n {onStepInside && (\n <div className=\"vi-fact__foot\">\n <span />\n <div className=\"vi-fact__acts\">\n <button type=\"button\" className=\"vi-fact__step\" onClick={onStepInside}>Step inside <ChevronIcon /></button>\n </div>\n </div>\n )}\n </div>\n );\n});\n\n// ── Peek as a bottom sheet (touch) ────────────────────────────────────────────\n\nexport interface PeekSheetProps extends Omit<PeekCardProps, 'onClose'> {\n onClose: () => void;\n expanded: boolean;\n onToggleExpanded: () => void;\n /** Collapsed height in px (`--vi-sheet-h`). */\n height: number;\n}\n\n// Swipe thresholds on the sheet's grip: the design system's SHEET (geometry/interaction.ts).\n\n/**\n * The peek on touch devices: the design system's bottom sheet (`.vi-fact--sheet`).\n * Stays open until dismissed (close button, swipe down, tap on empty canvas, Esc).\n * A tapped term opens its definition inside the sheet, with a Back button.\n */\nexport const PeekSheet = memo(function PeekSheet({ node, anchors, onStepInside, onClose, renderContent, expanded, onToggleExpanded, height }: PeekSheetProps) {\n const [term, setTerm] = useState<SemanticAnchor | null>(null);\n const parts = useMemo(() => splitTerms(node.description ?? '', anchors), [node.description, anchors]);\n const startY = useRef<number | null>(null);\n const swiped = useRef(false);\n const { fill, ring } = paintVars(node);\n const style = {\n ['--vi-fact-fill' as string]: fill,\n ['--vi-fact-ring' as string]: ring,\n ['--vi-sheet-h' as string]: `${height}px`,\n zIndex: 'var(--z-card)',\n } as React.CSSProperties;\n\n return (\n <div className={`vi-fact vi-fact--sheet vi-peek${expanded ? ' is-expanded' : ''}`} style={style} role=\"dialog\" aria-label={node.title} data-node-tooltip=\"true\">\n <div\n className=\"vi-fact__grip\"\n onPointerDown={(e) => { startY.current = e.clientY; swiped.current = false; }}\n onPointerUp={(e) => {\n if (startY.current === null) return;\n const dy = e.clientY - startY.current;\n startY.current = null;\n if (dy < -SHEET.expandDrag) { swiped.current = true; if (!expanded) onToggleExpanded(); }\n else if (dy > SHEET.dismissDrag) { swiped.current = true; if (expanded) onToggleExpanded(); else onClose(); }\n }}\n >\n <button type=\"button\" className=\"vi-fact__handle\" aria-label={expanded ? 'Collapse' : 'Expand'} aria-expanded={expanded} onClick={() => { if (!swiped.current) onToggleExpanded(); swiped.current = false; }} />\n </div>\n {term ? (\n <>\n <button type=\"button\" className=\"vi-fact__back\" onClick={() => setTerm(null)}><ChevronLeftIcon /> Back</button>\n <TermCard anchor={term} inSheet />\n </>\n ) : (\n <>\n <div className=\"vi-fact__head\">\n <div className=\"vi-fact__title\">{node.title}</div>\n <button type=\"button\" className=\"vi-iconbtn vi-iconbtn--md vi-fact__close\" aria-label=\"Close\" onClick={onClose}><CloseIcon /></button>\n </div>\n <div className=\"vi-fact__body\">\n {renderContent ? renderContent(node.description ?? '') : parts.map((p, i) =>\n typeof p === 'string' ? <React.Fragment key={i}>{p}</React.Fragment> : (\n <span key={i} className=\"vi-anchor\" data-semantic-tooltip=\"true\">\n <button type=\"button\" className=\"vi-term\" onClick={() => setTerm(p)}>{p.word}</button>\n </span>\n ))}\n </div>\n {onStepInside && (\n <div className=\"vi-fact__foot\">\n <span />\n <div className=\"vi-fact__acts\">\n <button type=\"button\" className=\"vi-fact__step\" onClick={onStepInside}>Step inside <ChevronIcon /></button>\n </div>\n </div>\n )}\n </>\n )}\n </div>\n );\n});\n","// ─── Accessible layer ─────────────────────────────────────────────────────────\n//\n// The canvas is a picture, so ideas are mirrored as a visually hidden DOM list:\n// one button per visible idea (label, depth, \"has more inside\"), reachable with\n// Tab and activated with Enter/Space exactly like a click. Focus is drawn on\n// the canvas (the idea gets the spec's focus outline).\n//\n// Only ideas in view are mirrored (capped), so a 10k-idea map never creates a\n// 10k-element DOM.\n\nimport React, { memo, useEffect, useMemo, useState } from 'react';\nimport { intersectsViewport, nodeBounds, type FlatNode } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\n\nconst MAX_MIRRORED = 150;\n\nexport interface A11yLayerProps {\n nodes: FlatNode[];\n /** Accessible name of the list, e.g. the layer title. */\n label: string;\n hasChildLayer: (nodeId: string) => boolean;\n onActivate: (node: FlatNode) => void;\n onFocusNode: (nodeId: string | null) => void;\n /** Spoken when the layer changes. */\n announcement?: string;\n}\n\nexport const A11yLayer = memo(function A11yLayer({ nodes, label, hasChildLayer, onActivate, onFocusNode, announcement }: A11yLayerProps) {\n const cx = useViewportStore((s) => s.centerX);\n const cy = useViewportStore((s) => s.centerY);\n const zoom = useViewportStore((s) => s.zoomLevel);\n const w = useViewportStore((s) => s.canvasWidth);\n const h = useViewportStore((s) => s.canvasHeight);\n\n // Debounce: wheel-zoom updates the store on every event.\n const [view, setView] = useState({ cx, cy, zoom, w, h });\n useEffect(() => {\n const t = setTimeout(() => setView({ cx, cy, zoom, w, h }), 120);\n return () => clearTimeout(t);\n }, [cx, cy, zoom, w, h]);\n\n const items = useMemo(() => {\n const halfW = view.w / 2 / view.zoom, halfH = view.h / 2 / view.zoom;\n const bounds = { minX: view.cx - halfW, maxX: view.cx + halfW, minY: view.cy - halfH, maxY: view.cy + halfH };\n const visible = nodes.filter((n) => intersectsViewport(n, bounds));\n // Keep the nearest ones when there are too many, then restore reading order (rows, then left to right).\n const picked = visible.length > MAX_MIRRORED\n ? visible.map((n) => ({ n, d: (n.x - view.cx) ** 2 + (n.y - view.cy) ** 2 })).sort((a, b) => a.d - b.d).slice(0, MAX_MIRRORED).map((e) => e.n)\n : visible;\n const row = (n: FlatNode) => Math.round(nodeBounds(n).minY / 150);\n return [...picked].sort((a, b) => row(a) - row(b) || a.x - b.x);\n }, [nodes, view]);\n\n return (\n <>\n <div className=\"vi-sr\" role=\"list\" aria-label={label}>\n {items.map((n) => (\n <div role=\"listitem\" key={n.id}>\n <button\n type=\"button\"\n data-node-id={n.id}\n aria-label={`${n.title}. Depth ${n.level + 1}.${hasChildLayer(n.id) ? ' Has more inside; press Enter to step inside.' : ''}`}\n onFocus={() => onFocusNode(n.id)}\n onBlur={() => onFocusNode(null)}\n onClick={() => onActivate(n)}\n />\n </div>\n ))}\n </div>\n <div className=\"vi-sr\" role=\"status\" aria-live=\"polite\">{announcement}</div>\n </>\n );\n});\n","// ─── useDesign ───────────────────────────────────────────────────────────────\n//\n// Resolves theme + comfort props against the reader's environment (colour\n// scheme, forced colours, reduced motion) and keeps them live.\n\nimport { useMemo, useSyncExternalStore } from 'react';\nimport { resolveDesign, type Design, type DesignProps } from './design';\n\nfunction useMedia(query: string): boolean {\n const subscribe = (cb: () => void) => {\n if (typeof window === 'undefined' || !window.matchMedia) return () => {};\n const mq = window.matchMedia(query);\n mq.addEventListener('change', cb);\n return () => mq.removeEventListener('change', cb);\n };\n const get = () => (typeof window !== 'undefined' && !!window.matchMedia && window.matchMedia(query).matches);\n return useSyncExternalStore(subscribe, get, () => false);\n}\n\n/** The reader's current preferences. */\nexport function useReaderEnv() {\n return {\n prefersDark: useMedia('(prefers-color-scheme: dark)'),\n forcedColors: useMedia('(forced-colors: active)'),\n prefersReducedMotion: useMedia('(prefers-reduced-motion: reduce)'),\n };\n}\n\nexport function useDesign(props: DesignProps): Design {\n const env = useReaderEnv();\n const { theme, isDark, respectForcedColors } = props;\n const { readableType, largerText, reducedMotion } = props.comfort ?? {};\n return useMemo(\n () => resolveDesign({ theme, isDark, respectForcedColors, comfort: { readableType, largerText, reducedMotion } }, env),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [theme, isDark, respectForcedColors, readableType, largerText, reducedMotion, env.prefersDark, env.forcedColors, env.prefersReducedMotion],\n );\n}\n","// ─── Label measurement ────────────────────────────────────────────────────────\n//\n// The text measurement the design system's ideaSize (geometry/idea.ts) needs:\n// the idea label's width in its own face and weight — Kalam, or the UI face with\n// its .02em tracking in readable type — on a 2D canvas, the same engine that draws it.\n\nimport { TYPE_STYLES, approximateMeasure, type IdeaMeasure } from '@visualli/core';\nimport type { Design } from './design';\nimport { fontsEpoch } from './runtime';\n\nlet ctx: CanvasRenderingContext2D | null | undefined;\nconst cache = new Map<string, number>();\nconst MAX_CACHED = 8192;\n\n/** Width of a label in `d`'s idea face (cached per face, size, text and font load). */\nexport function ideaMeasure(d: Pick<Design, 'fontHand' | 'comfort'>): IdeaMeasure {\n if (ctx === undefined) ctx = typeof document !== 'undefined' ? document.createElement('canvas').getContext('2d') : null;\n const c = ctx;\n if (!c) return approximateMeasure;\n const weight = TYPE_STYLES['node-label'].weight;\n const tracking = d.comfort.readableType ? 0.02 : 0;\n return (text, px) => {\n const font = `${weight} ${px}px ${d.fontHand}`;\n const key = `${fontsEpoch()}|${font}|${text}`;\n let w = cache.get(key);\n if (w === undefined) {\n c.font = font;\n w = c.measureText(text).width + text.length * px * tracking;\n if (cache.size >= MAX_CACHED) cache.clear();\n cache.set(key, w);\n }\n return w;\n };\n}\n","// ─── Visualli Context ─────────────────────────────────────────────────────────\n//\n// React Context for Visualli components (minimal implementation)\n\nimport React, { createContext, useContext } from 'react';\n\n// Reserved for future use (public type, kept as an open interface).\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface VisualliContextValue {}\n\nconst VisualliContext = createContext<VisualliContextValue | null>(null);\n\nexport interface VisualliProviderProps {\n children: React.ReactNode;\n}\n\n/**\n * Provider for Visualli context\n * \n * @example\n * ```tsx\n * <VisualliProvider>\n * <VisualliCanvas document={doc} />\n * </VisualliProvider>\n * ```\n */\nexport function VisualliProvider({\n children,\n}: VisualliProviderProps) {\n const value: VisualliContextValue = {};\n\n return (\n <VisualliContext.Provider value={value}>\n {children}\n </VisualliContext.Provider>\n );\n}\n\n/**\n * Hook to access Visualli context\n * \n * Returns default empty values if used outside of VisualliProvider\n */\nexport function useVisualli(): VisualliContextValue {\n const ctx = useContext(VisualliContext);\n if (!ctx) {\n return {};\n }\n return ctx;\n}\n","// ─── useViewportNodes ─────────────────────────────────────────────────────────\n//\n// Returns the subset of nodes currently visible in the viewport.\n// Signature: useViewportNodes(nodes, levelFilter?, skipCulling?)\n//\n// When skipCulling=true (e.g. during layer transitions) all nodes are returned\n// so the full layer is rendered when opacity ramps in.\n\nimport { useMemo, useRef } from 'react';\nimport type { FlatNode } from '@visualli/core';\nimport { RBushSpatialIndex, getViewportVisibleNodes } from '@visualli/core';\nimport { useViewportStore } from '../stores/useViewportStore';\n\nconst SPATIAL_INDEX_THRESHOLD = 200;\n\nexport function useViewportNodes(\n nodes: FlatNode[],\n levelFilter?: number,\n skipCulling = false,\n /** When true, skip culling so dragged nodes are always visible and the\n * spatial index (keyed on layout positions) is not consulted. */\n isDragging = false,\n): FlatNode[] {\n const { centerX, centerY, zoomLevel, canvasWidth, canvasHeight } = useViewportStore();\n\n const indexRef = useRef<RBushSpatialIndex | null>(null);\n const nodesHashRef = useRef<number>(0);\n const nodesHash = nodes.length;\n\n if (nodesHash !== nodesHashRef.current) {\n nodesHashRef.current = nodesHash;\n indexRef.current = null; // rebuild below\n }\n\n return useMemo(() => {\n if (nodes.length === 0) return [];\n\n if (!indexRef.current && nodes.length >= SPATIAL_INDEX_THRESHOLD && !skipCulling && !isDragging) {\n indexRef.current = new RBushSpatialIndex();\n indexRef.current.bulkLoad(nodes.map(n => ({\n nodeId: n.id,\n bounds: { minX: n.x, minY: n.y, maxX: n.x + n.width, maxY: n.y + n.height },\n })));\n }\n\n return getViewportVisibleNodes({\n nodes,\n viewport: { centerX, centerY, zoomLevel, rotation: 0, visibleBounds: { minX: 0, minY: 0, maxX: 0, maxY: 0 } },\n canvasWidth,\n canvasHeight,\n levelFilter,\n skipCulling,\n isDragging,\n spatialIndex: indexRef.current,\n spatialIndexThreshold: SPATIAL_INDEX_THRESHOLD,\n });\n }, [nodes, levelFilter, skipCulling, isDragging, centerX, centerY, zoomLevel, canvasWidth, canvasHeight]);\n}\n","// ─── KonvaNode ────────────────────────────────────────────────────────────────\n//\n// A single idea as one Konva shape (rings + body + label), drawn with the design\n// system's geometry and tokens. The canvas layers batch all ideas into one shape\n// (KonvaNodeLayer); this component is for composing custom Konva scenes.\n\nimport React from 'react';\nimport { KShape as Shape } from '../konvaCompat';\nimport { type FlatNode } from '@visualli/core';\nimport { DEFAULT_DESIGN, type Design } from '../design/design';\nimport { IDLE, drawIdea } from '../design/drawing';\n\nexport interface KonvaNodeProps {\n node: FlatNode;\n zoomLevel: number;\n /** True when the pointer is currently over this node (stage-level hit test). */\n isExternallyHovered?: boolean;\n /** True while this node is being pressed/dragged. */\n isExternallyPressed?: boolean;\n isSelected?: boolean;\n /** True while any node is being dragged — disables the drop shadow. */\n isDragging?: boolean;\n design?: Design;\n}\n\nconst KonvaNode = React.memo(function KonvaNode({\n node, zoomLevel, isExternallyHovered = false, isExternallyPressed = false, isSelected = false, isDragging = false, design = DEFAULT_DESIGN,\n}: KonvaNodeProps) {\n return (\n <Shape\n listening={false}\n perfectDrawEnabled={false}\n sceneFunc={(ctx: { _context: CanvasRenderingContext2D }) => {\n drawIdea(ctx._context, node, design, zoomLevel, { ...IDLE, hovered: isExternallyHovered, pressed: isExternallyPressed, selected: isSelected }, {\n shadows: !isDragging,\n });\n }}\n />\n );\n});\n\nexport default KonvaNode;\n","// ─── KonvaEdge ────────────────────────────────────────────────────────────────\n//\n// A single connector between two ideas: the design system's cubic curve, open\n// arrowhead and label. Endpoints sit `edge-gap` outside the real outline of each\n// idea (including its outermost ring). The canvas layers batch connectors\n// (KonvaEdgeLayer); this component is for composing custom Konva scenes.\n\nimport React, { memo, useMemo } from 'react';\nimport { KShape as Shape } from '../konvaCompat';\nimport { connectorGeometry, type FlatNode, type MindMapConnection } from '@visualli/core';\nimport { DEFAULT_DESIGN, type Design } from '../design/design';\nimport { drawConnector, prepareConnector } from '../design/drawing';\n\nexport interface KonvaEdgeProps {\n sourceNode: FlatNode;\n targetNode: FlatNode;\n connection?: MindMapConnection;\n /** @deprecated pass `design`. */\n isDark?: boolean;\n /** @deprecated connectors use the design system's edge colour; kept so existing callers compile. */\n colorOverride?: string;\n zoomLevel?: number;\n design?: Design;\n}\n\nconst KonvaEdge = memo(function KonvaEdge({ sourceNode: from, targetNode: to, connection, zoomLevel = 1, design = DEFAULT_DESIGN }: KonvaEdgeProps) {\n const g = useMemo(\n () => prepareConnector(connectorGeometry(from, to, design.metrics.edgeGap)),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [from.x, from.y, from.width, from.level, from.branchCount, to.x, to.y, to.width, to.level, to.branchCount, design.metrics.edgeGap],\n );\n return (\n <Shape\n listening={false}\n perfectDrawEnabled={false}\n sceneFunc={(ctx: { _context: CanvasRenderingContext2D }) => {\n drawConnector(ctx._context, g, design, zoomLevel, connection?.style === 'dashed', connection?.label);\n }}\n />\n );\n});\n\nexport default KonvaEdge;\n","// ─── KonvaContainer ───────────────────────────────────────────────────────────\n//\n// One container — the design system's dashed hull around a group of ideas, with\n// its name as a pill on the hull's edge — for composing custom Konva scenes.\n// It only knows its own members, so the name avoids them (not other ideas or\n// connectors); the canvas uses KonvaContainerLayer + KonvaContainerLabelLayer,\n// which place names against the whole layer.\n\nimport React, { memo, useMemo } from 'react';\nimport { KShape as Shape } from '../konvaCompat';\nimport type { FlatNode } from '@visualli/core';\nimport { DEFAULT_DESIGN, type Design } from '../design/design';\nimport { drawHull, drawPill, layoutContainers } from '../design/containers';\n\nexport interface KonvaContainerProps {\n /** All nodes in this container group (already resolved from nodeMap). */\n nodes: FlatNode[];\n /** The group's name, drawn as a pill on the hull. */\n label?: string;\n /** @deprecated unused: the hull and name use the design system's container style. */\n color?: string;\n /** @deprecated pass `design`. */\n isDark?: boolean;\n zoomLevel?: number;\n design?: Design;\n}\n\nconst KonvaContainer = memo(function KonvaContainer({ nodes, label = '', zoomLevel = 1, design = DEFAULT_DESIGN }: KonvaContainerProps) {\n const placed = useMemo(() => {\n const map = new Map(nodes.map((n) => [n.id, n] as const));\n return layoutContainers([{ id: 'c', label: label || undefined, nodeIds: nodes.map((n) => n.id) }], map, [], design)[0] ?? null;\n }, [nodes, label, design]);\n if (!placed) return null;\n return (\n <Shape\n listening={false}\n perfectDrawEnabled={false}\n sceneFunc={(ctx: { _context: CanvasRenderingContext2D }) => {\n drawHull(ctx._context, placed.hull, design);\n if (placed.pill) drawPill(ctx._context, placed.pill, design, zoomLevel);\n }}\n />\n );\n});\n\nexport default KonvaContainer;\n"],"mappings":"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","names":["import_react","import_core","import_react","import_core","set","import_zustand","import_zustand","import_core","import_react","import_core","import_core","import_core","import_react","import_react","import_core","KonvaStage","Konva","import_react","import_core","import_core","key","import_core","key","key","import_react","import_jsx_runtime","ctx","import_react","import_core","import_jsx_runtime","cache","ctx","import_react","import_core","import_jsx_runtime","ctx","import_react","import_jsx_runtime","ctx","import_react","import_react","import_core","import_jsx_runtime","ZoomControls","DepthTrail","PeekCard","React","PeekSheet","import_jsx_runtime","NavigationStack","import_react","import_core","import_jsx_runtime","A11yLayer","import_react","import_core","cache","key","import_jsx_runtime","rx","ry","import_jsx_runtime","import_react","import_jsx_runtime","ctx","import_react","import_core","SPATIAL_INDEX_THRESHOLD","import_core","import_react","import_jsx_runtime","React","KonvaNode","ctx","import_react","import_core","import_jsx_runtime","KonvaEdge","ctx","import_react","import_jsx_runtime","KonvaContainer","ctx"]}