@visualli/react 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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/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=\"label\" style={{ margin: 0, color: 'var(--ink)' }}>{title}</p>\n {children && <div className=\"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=\"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.0). 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.heading { font-family: var(--font-ui); font-size: 17px; line-height: 24px; font-weight: 700; }\\n.body { font-family: var(--font-ui); font-size: 15px; line-height: 22px; font-weight: 400; }\\n.body-sm { font-family: var(--font-ui); font-size: 13px; line-height: 18px; font-weight: 400; }\\n.label { font-family: var(--font-ui); font-size: 13px; line-height: 16px; font-weight: 600; letter-spacing: 0.01em; }\\n.caption { font-family: var(--font-ui); font-size: 12px; line-height: 16px; font-weight: 400; }\\n.node-root { font-family: var(--font-hand); font-size: 30px; line-height: 34px; font-weight: 700; }\\n.node-label { font-family: var(--font-hand); font-size: 22px; line-height: 26px; font-weight: 700; }\\n.edge-label { font-family: var(--font-note); font-size: 18px; line-height: 20px; font-weight: 500; }\\n.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.0). 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; color-scheme: light; }\\n[data-theme$=\\\"dark\\\"] { 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; letter-spacing: 0.01em; }\\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\\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.vi-map :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\\\"] *, [data-motion=\\\"reduced\\\"] *::before, [data-motion=\\\"reduced\\\"] *::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.0\";\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"]}
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.2). 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.2). 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__note { margin: var(--space-2) 0 0; font: 400 var(--vi-fs-cap)/16px var(--font-ui); color: var(--ink-muted); }\\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.2\";\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"]}